From 4371ee22f97884a3add60d2b4b8871d5881c55fb Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 4 Jun 2012 01:17:37 +0000 Subject: Theme Colors for NLA Strips and DopeSheet Summary * NLA Strip colors are now themable * Changed the "Active Action"/"Summary" colors to be a bit more muted. The new colors are now closer to those for keyframes, though they are still different enough to be clearly distinguishable. * Removed some colors wihch don't seem to be used (from NLA theme colors) * Added function to get theme colors + alpha as floats --- .../editors/animation/anim_channels_defines.c | 7 +- source/blender/editors/include/UI_resources.h | 18 ++++- source/blender/editors/interface/resources.c | 88 +++++++++++++++++++++- source/blender/editors/space_action/action_draw.c | 4 +- source/blender/editors/space_nla/nla_draw.c | 86 +++++++-------------- source/blender/makesdna/DNA_userdef_types.h | 13 +++- source/blender/makesrna/intern/rna_userdef.c | 83 ++++++++++++++++---- 7 files changed, 216 insertions(+), 83 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 386313b1d3c..7f7d269a7c3 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -395,11 +395,8 @@ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListEle /* get backdrop color for summary widget */ static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3]) { - // FIXME: hardcoded color - same as the 'action' line in NLA - // reddish color - r_color[0] = 0.8f; - r_color[1] = 0.2f; - r_color[2] = 0.0f; + /* reddish color - same as the 'action' line in NLA */ + UI_GetThemeColor3fv(TH_ANIM_ACTIVE, r_color); } /* backdrop for summary widget */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 257f5c2119c..2ef5277a3c6 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -200,7 +200,20 @@ enum { TH_MATCH, /* highlight color for search matches */ TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */ - TH_SKIN_ROOT + TH_SKIN_ROOT, + + TH_ANIM_ACTIVE, /* active action */ + TH_ANIM_INACTIVE, /* no active action */ + + TH_NLA_TWEAK, /* 'tweaking' track in NLA */ + TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */ + + TH_NLA_TRANSITION, + TH_NLA_TRANSITION_SEL, + TH_NLA_META, + TH_NLA_META_SEL, + TH_NLA_SOUND, + TH_NLA_SOUND_SEL }; /* XXX WARNING: previous is saved in file, so do not change order! */ @@ -239,6 +252,9 @@ void UI_GetThemeColor3fv(int colorid, float col[3]); void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]); void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]); +// get four color values, scaled to 0.0-1.0 range +void UI_GetThemeColor4fv(int colorid, float col[4]); + // get the 3 or 4 byte values void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]); void UI_GetThemeColor4ubv(int colorid, unsigned char col[4]); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 5aec4b3c211..f2ea81abcbf 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -473,6 +473,39 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_SKIN_ROOT: cp = ts->skin_root; break; + + case TH_ANIM_ACTIVE: + cp = ts->anim_active; + break; + case TH_ANIM_INACTIVE: + cp = ts->anim_non_active; + break; + + case TH_NLA_TWEAK: + cp = ts->nla_tweaking; + break; + case TH_NLA_TWEAK_DUPLI: + cp = ts->nla_tweakdupli; + break; + + case TH_NLA_TRANSITION: + cp = ts->nla_transition; + break; + case TH_NLA_TRANSITION_SEL: + cp = ts->nla_transition_sel; + break; + case TH_NLA_META: + cp = ts->nla_meta; + break; + case TH_NLA_META_SEL: + cp = ts->nla_meta_sel; + break; + case TH_NLA_SOUND: + cp = ts->nla_sound; + break; + case TH_NLA_SOUND_SEL: + cp = ts->nla_sound_sel; + break; } } } @@ -735,19 +768,34 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tipo.handle_sel_auto_clamped, 0xf0, 0xaf, 0x90, 255); btheme->tipo.handle_vertex_size = 4; - rgba_char_args_set(btheme->tipo.ds_channel, 82, 96, 110, 255); + rgba_char_args_set(btheme->tipo.ds_channel, 82, 96, 110, 255); rgba_char_args_set(btheme->tipo.ds_subchannel, 124, 137, 150, 255); - rgba_char_args_set(btheme->tipo.group, 79, 101, 73, 255); - rgba_char_args_set(btheme->tipo.group_active, 135, 177, 125, 255); + rgba_char_args_set(btheme->tipo.group, 79, 101, 73, 255); + rgba_char_args_set(btheme->tipo.group_active, 135, 177, 125, 255); /* dopesheet */ btheme->tact = btheme->tipo; rgba_char_args_set(btheme->tact.strip, 12, 10, 10, 128); rgba_char_args_set(btheme->tact.strip_select, 255, 140, 0, 255); + rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102); + /* space nla */ btheme->tnla = btheme->tact; + rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as for dopesheet; duplicate here for easier reference */ + rgba_char_args_set(btheme->tnla.anim_non_active,153, 135, 97, 77); + + rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77); + rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255); + + rgba_char_args_set(btheme->tnla.nla_transition, 28, 38, 48, 255); + rgba_char_args_set(btheme->tnla.nla_transition_sel, 46, 117, 219, 255); + rgba_char_args_set(btheme->tnla.nla_meta, 51, 38, 66, 255); + rgba_char_args_set(btheme->tnla.nla_meta_sel, 105, 33, 150, 255); + rgba_char_args_set(btheme->tnla.nla_sound, 43, 61, 61, 255); + rgba_char_args_set(btheme->tnla.nla_sound_sel, 31, 122, 122, 255); + /* space file */ /* to have something initialized */ btheme->tfile = btheme->tv3d; @@ -1043,6 +1091,17 @@ void UI_GetThemeColor3fv(int colorid, float col[3]) col[2] = ((float)cp[2]) / 255.0f; } +void UI_GetThemeColor4fv(int colorid, float col[4]) +{ + const unsigned char *cp; + + cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + col[0] = ((float)cp[0]) / 255.0f; + col[1] = ((float)cp[1]) / 255.0f; + col[2] = ((float)cp[2]) / 255.0f; + col[3] = ((float)cp[3]) / 255.0f; +} + // get the color, range 0.0-1.0, complete with shading offset void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]) { @@ -1816,6 +1875,29 @@ void init_userdef_do_versions(void) for (btheme = U.themes.first; btheme; btheme = btheme->next) rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255); } + + if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 7)) { + bTheme *btheme; + + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + /* DopeSheet Summary */ + rgba_char_args_set(btheme->tact.anim_active, 204, 112, 26, 102); + + /* NLA Colors */ + rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as dopesheet above */ + rgba_char_args_set(btheme->tnla.anim_non_active,153, 135, 97, 77); + + rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77); + rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255); + + rgba_char_args_set(btheme->tnla.nla_transition, 28, 38, 48, 255); + rgba_char_args_set(btheme->tnla.nla_transition_sel, 46, 117, 219, 255); + rgba_char_args_set(btheme->tnla.nla_meta, 51, 38, 66, 255); + rgba_char_args_set(btheme->tnla.nla_meta_sel, 105, 33, 150, 255); + rgba_char_args_set(btheme->tnla.nla_sound, 43, 61, 61, 255); + rgba_char_args_set(btheme->tnla.nla_sound_sel, 31, 122, 122, 255); + } + } /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 3961e566f80..84ff038a050 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -236,8 +236,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) switch (ale->type) { case ANIMTYPE_SUMMARY: { - // FIXME: hardcoded colors - reddish color from NLA - glColor4f(0.8f, 0.2f, 0.0f, 0.4f); + /* reddish color from NLA */ + UI_ThemeColor4(TH_ANIM_ACTIVE); } break; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index a6578ffb3f7..7eb0f676707 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -80,26 +80,17 @@ static void nla_action_get_color(AnimData *adt, bAction *act, float color[4]) { if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { - // greenish color (same as tweaking strip) - hardcoded for now - color[0] = 0.30f; - color[1] = 0.95f; - color[2] = 0.10f; - color[3] = 0.30f; + /* greenish color (same as tweaking strip) */ + UI_GetThemeColor4fv(TH_NLA_TWEAK, color); } else { if (act) { - // reddish color - hardcoded for now - color[0] = 0.8f; - color[1] = 0.2f; - color[2] = 0.0f; - color[3] = 0.4f; + /* reddish color - same as dopesheet summary */ + UI_GetThemeColor4fv(TH_ANIM_ACTIVE, color); } else { - // greyish-red color - hardcoded for now - color[0] = 0.6f; - color[1] = 0.5f; - color[2] = 0.5f; - color[3] = 0.3f; + /* greyish-red color */ + UI_GetThemeColor4fv(TH_ANIM_INACTIVE, color); } } @@ -166,17 +157,11 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col /* Transition Clip */ if (strip->flag & NLASTRIP_FLAG_SELECT) { /* selected - use a bright blue color */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.18f; - color[1] = 0.46f; - color[2] = 0.86f; + UI_GetThemeColor3fv(TH_NLA_TRANSITION_SEL, color); } else { /* normal, unselected strip - use (hardly noticeable) blue tinge */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.11f; - color[1] = 0.15f; - color[2] = 0.19f; + UI_GetThemeColor3fv(TH_NLA_TRANSITION, color); } } else if (strip->type == NLASTRIP_TYPE_META) { @@ -184,34 +169,22 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col // TODO: should temporary metas get different colors too? if (strip->flag & NLASTRIP_FLAG_SELECT) { /* selected - use a bold purple color */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.41f; - color[1] = 0.13f; - color[2] = 0.59f; + UI_GetThemeColor3fv(TH_NLA_META_SEL, color); } else { /* normal, unselected strip - use (hardly noticeable) dark purple tinge */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.20f; - color[1] = 0.15f; - color[2] = 0.26f; + UI_GetThemeColor3fv(TH_NLA_META, color); } } else if (strip->type == NLASTRIP_TYPE_SOUND) { /* Sound Clip */ if (strip->flag & NLASTRIP_FLAG_SELECT) { /* selected - use a bright teal color */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.12f; - color[1] = 0.48f; - color[2] = 0.48f; + UI_GetThemeColor3fv(TH_NLA_SOUND_SEL, color); } else { /* normal, unselected strip - use (hardly noticeable) teal tinge */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.17f; - color[1] = 0.24f; - color[2] = 0.24f; + UI_GetThemeColor3fv(TH_NLA_SOUND, color); } } else { @@ -220,19 +193,13 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col /* active strip should be drawn green when it is acting as the tweaking strip. * however, this case should be skipped for when not in EditMode... */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.3f; - color[1] = 0.95f; - color[2] = 0.1f; + UI_GetThemeColor3fv(TH_NLA_TWEAK, color); } else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) { /* alert user that this strip is also used by the tweaking track (this is set when going into * 'editmode' for that strip), since the edits made here may not be what the user anticipated */ - // FIXME: hardcoded temp-hack colors - color[0] = 0.85f; - color[1] = 0.0f; - color[2] = 0.0f; + UI_GetThemeColor3fv(TH_NLA_TWEAK_DUPLI, color); } else if (strip->flag & NLASTRIP_FLAG_SELECT) { /* selected strip - use theme color for selected */ @@ -792,21 +759,24 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View glEnable(GL_BLEND); /* draw backing strip behind channel name */ + // FIXME: hardcoded colors!!! if (group == 5) { - /* Action Line */ - // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now) + float color[4]; + + /* Action Line + * The alpha values action_get_color returns are only useful for drawing + * strips backgrounds but here we're doing channel list backgrounds instead + * so we ignore that and use our own when needed + */ + nla_action_get_color(adt, (bAction *)ale->data, color); + if (adt && (adt->flag & ADT_NLA_EDIT_ON)) { - // greenish color (same as tweaking strip) - hardcoded for now - glColor3f(0.3f, 0.95f, 0.1f); + /* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */ + glColor3fv(color); } else { - /* if a track is being solo'd, action is ignored, so draw less boldly (alpha lower) */ - float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f; - - if (ale->data) - glColor4f(0.8f, 0.2f, 0.0f, alpha); // reddish color - hardcoded for now - else - glColor4f(0.6f, 0.5f, 0.5f, alpha); // greyish-red color - hardcoded for now + float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3 : 1.0f; + glColor4f(color[0], color[1], color[2], alpha); } offset += 7 * indent; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index be2268aa492..f06a2b6f80a 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -263,8 +263,19 @@ typedef struct ThemeSpace { char selected_highlight[4]; /* outliner - selected item */ char skin_root[4]; /* Skin modifier root color */ - + int pad4; + + /* NLA */ + char anim_active[4]; /* Active Action + Summary Channel */ + char anim_non_active[4]; /* Active Action = NULL */ + + char nla_tweaking[4]; /* NLA 'Tweaking' action/strip */ + char nla_tweakdupli[4]; /* NLA - warning color for duplicate instances of tweaking strip */ + + char nla_transition[4], nla_transition_sel[4]; /* NLA "Transition" strips */ + char nla_meta[4], nla_meta_sel[4]; /* NLA "Meta" strips */ + char nla_sound[4], nla_sound_sel[4]; /* NLA "Sound" strips */ } ThemeSpace; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 956b3a15a4c..ec215120f0c 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1919,6 +1919,12 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "DopeSheet Sub-Channel", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "summary", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "anim_active"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Summary", "Color of summary channel"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) @@ -1947,28 +1953,79 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) RNA_def_property_ui_text(prop, "View Sliders", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop = RNA_def_property(srna, "bars", PROP_FLOAT, PROP_COLOR_GAMMA); - RNA_def_property_float_sdna(prop, NULL, "shade2"); - RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Bars", ""); + prop = RNA_def_property(srna, "active_action", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "anim_active"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Active Action", "Animation data block has active action"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop = RNA_def_property(srna, "bars_selected", PROP_FLOAT, PROP_COLOR_GAMMA); - RNA_def_property_float_sdna(prop, NULL, "hilite"); - RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Bars Selected", ""); + + prop = RNA_def_property(srna, "active_action_unset", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "anim_non_active"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "No Active Action", "Animation data block doesn't have active action"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Strips", ""); + RNA_def_property_ui_text(prop, "Strips", "Action-Clip Strip - Unselected"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + prop = RNA_def_property(srna, "strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip_select"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Strips Selected", ""); + RNA_def_property_ui_text(prop, "Strips Selected", "Action-Clip Strip - Selected"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "transition_strips", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_transition"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Transitions", "Transition Strip - Unselected"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "transition_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_transition_sel"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Transitions Selected", "Transition Strip - Selected"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "meta_strips", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_meta"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Meta Strips", "Meta Strip - Unselected. For grouping related strips"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "meta_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_meta_sel"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Meta Strips Selected", "Meta Strip - Selected. For grouping related strips"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "sound_strips", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_sound"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Sound Strips", + "Sound Strip - Unselected. For timing speaker sounds"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "sound_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_sound_sel"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Sound Strips Selected", + "Sound Strip - Selected. For timing speaker sounds"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "tweak", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_tweaking"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Tweak", "Color for strip/action being 'tweaked' or edited"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "tweak_duplicate", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "nla_tweakdupli"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Tweak Duplicate Flag", + "Warning/error indicator color for strips referencing the strip being tweaked"); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "frame_current", PROP_FLOAT, PROP_COLOR_GAMMA); -- cgit v1.2.3 From 4414f38cbfa22d875039c4660af2954f6d7cdfc3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 07:24:19 +0000 Subject: patch [#31644] Py Console: Indent and unindent independent of cursor (aligned) [Tab / Shift + Tab / Ctrl + Tab] from Sebastian Nell (codemanx) --- release/scripts/startup/bl_ui/space_console.py | 8 ++ .../blender/editors/space_console/console_intern.h | 3 + source/blender/editors/space_console/console_ops.c | 95 +++++++++++++++++++++- .../blender/editors/space_console/space_console.c | 9 +- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py index fc1d8e2d4be..5ec9d06ec89 100644 --- a/release/scripts/startup/bl_ui/space_console.py +++ b/release/scripts/startup/bl_ui/space_console.py @@ -41,8 +41,16 @@ class CONSOLE_MT_console(Menu): def draw(self, context): layout = self.layout + layout.operator("console.indent") + layout.operator("console.unindent") + + layout.separator() + layout.operator("console.clear") layout.operator("console.clear_line") + + layout.separator() + layout.operator("console.copy") layout.operator("console.paste") layout.menu("CONSOLE_MT_language") diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h index c0abd094e62..3d30dcad710 100644 --- a/source/blender/editors/space_console/console_intern.h +++ b/source/blender/editors/space_console/console_intern.h @@ -54,6 +54,9 @@ void CONSOLE_OT_move(struct wmOperatorType *ot); void CONSOLE_OT_delete(struct wmOperatorType *ot); void CONSOLE_OT_insert(struct wmOperatorType *ot); +void CONSOLE_OT_indent(struct wmOperatorType *ot); +void CONSOLE_OT_unindent(struct wmOperatorType *ot); + void CONSOLE_OT_history_append(struct wmOperatorType *ot); void CONSOLE_OT_scrollback_append(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 5ed384d22af..44dda60edd0 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -364,9 +364,8 @@ static int console_insert_exec(bContext *C, wmOperator *op) char *str = RNA_string_get_alloc(op->ptr, "text", NULL, 0); int len; - // XXX, alligned tab key hack if (str[0] == '\t' && str[1] == '\0') { - len = TAB_LENGTH - (ci->cursor % TAB_LENGTH); + len = TAB_LENGTH; MEM_freeN(str); str = MEM_mallocN(len + 1, "insert_exec"); memset(str, ' ', len); @@ -430,6 +429,95 @@ void CONSOLE_OT_insert(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +static int console_indent_exec(bContext *C, wmOperator *op) +{ + SpaceConsole *sc = CTX_wm_space_console(C); + ARegion *ar = CTX_wm_region(C); + ConsoleLine *ci = console_history_verify(C); + int spaces; + int len; + + for (spaces = 0; spaces < ci->len; spaces++) { + if (ci->line[spaces] != ' ') + break; + } + + len = TAB_LENGTH - spaces % TAB_LENGTH; + + console_line_verify_length(ci, ci->len + len); + + memmove(ci->line + len, ci->line, ci->len); + memset(ci->line, ' ', len); + ci->len += len; + console_line_cursor_set(ci, ci->cursor + len); + + console_textview_update_rect(sc, ar); + ED_area_tag_redraw(CTX_wm_area(C)); + + console_scroll_bottom(ar); + + return OPERATOR_FINISHED; +} + +void CONSOLE_OT_indent(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Indent"; + ot->description = "Add 4 spaces at line beginning"; + ot->idname = "CONSOLE_OT_indent"; + + /* api callbacks */ + ot->exec = console_indent_exec; + ot->poll = ED_operator_console_active; +} + +static int console_unindent_exec(bContext *C, wmOperator *op) +{ + SpaceConsole *sc = CTX_wm_space_console(C); + ARegion *ar = CTX_wm_region(C); + ConsoleLine *ci = console_history_verify(C); + int spaces; + int len; + + for (spaces = 0; spaces < ci->len; spaces++) { + if (ci->line[spaces] != ' ') + break; + } + + if (spaces == 0) + return OPERATOR_CANCELLED; + + len = spaces % TAB_LENGTH; + if (len == 0) + len = TAB_LENGTH; + + console_line_verify_length(ci, ci->len - len); + + memmove(ci->line, ci->line + len, (ci->len - len) + 1); + ci->len -= len; + console_line_cursor_set(ci, ci->cursor - len); + + //console_select_offset(sc, -4); + + console_textview_update_rect(sc, ar); + ED_area_tag_redraw(CTX_wm_area(C)); + + console_scroll_bottom(ar); + + return OPERATOR_FINISHED; +} + +void CONSOLE_OT_unindent(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Unindent"; + ot->description = "Delete 4 spaces from line beginning"; + ot->idname = "CONSOLE_OT_unindent"; + + /* api callbacks */ + ot->exec = console_unindent_exec; + ot->poll = ED_operator_console_active; +} static EnumPropertyItem console_delete_type_items[] = { {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, @@ -757,7 +845,8 @@ void CONSOLE_OT_scrollback_append(wmOperatorType *ot) {CONSOLE_LINE_INPUT, "INPUT", 0, "Input", ""}, {CONSOLE_LINE_INFO, "INFO", 0, "Information", ""}, {CONSOLE_LINE_ERROR, "ERROR", 0, "Error", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "Scrollback Append"; diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index a25606db2b3..460b31d69bd 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -246,6 +246,9 @@ static void console_operatortypes(void) WM_operatortype_append(CONSOLE_OT_move); WM_operatortype_append(CONSOLE_OT_delete); WM_operatortype_append(CONSOLE_OT_insert); + + WM_operatortype_append(CONSOLE_OT_indent); + WM_operatortype_append(CONSOLE_OT_unindent); /* for use by python only */ WM_operatortype_append(CONSOLE_OT_history_append); @@ -332,7 +335,11 @@ static void console_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CONSOLE_OT_select_set", LEFTMOUSE, KM_PRESS, 0, 0); - RNA_string_set(WM_keymap_add_item(keymap, "CONSOLE_OT_insert", TABKEY, KM_PRESS, 0, 0)->ptr, "text", "\t"); /* fake tabs */ + RNA_string_set(WM_keymap_add_item(keymap, "CONSOLE_OT_insert", TABKEY, KM_PRESS, KM_CTRL, 0)->ptr, "text", "\t"); /* fake tabs */ + + WM_keymap_add_item(keymap, "CONSOLE_OT_indent", TABKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "CONSOLE_OT_unindent", TABKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "CONSOLE_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last! } -- cgit v1.2.3 From 46cd2a6a38a67c7dfc3e5a8880b6f7f055e50a8a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 07:29:45 +0000 Subject: Fix #31093: Brush's "Paint curve presets" in Image paint in UV\Image Editor doesn't work if weight paint mode is active Some operators like curve presets, color sample and some more were using object's mode to distinguish in which mode user is currently painting. Such approach fails in cases when there's paint mode active in 3D viewport and Image Editor. Changed logic here to use some context's state like active space which helps distinguishing current paint mode more accurate. Ported all areas which uses paint_get_active() to new paint_get_active_from_context(). There're still some calls to paint_get_active(), but that shouldn't be harmful due to that places indeed have object's mode as priority when getting paint mode. --- source/blender/blenkernel/BKE_paint.h | 2 + source/blender/blenkernel/intern/paint.c | 48 ++++++++++++++++++++++ source/blender/editors/sculpt_paint/paint_cursor.c | 6 +-- source/blender/editors/sculpt_paint/paint_image.c | 5 +-- source/blender/editors/sculpt_paint/paint_intern.h | 2 +- source/blender/editors/sculpt_paint/paint_ops.c | 8 ++-- source/blender/editors/sculpt_paint/paint_stroke.c | 13 +++--- source/blender/editors/sculpt_paint/paint_utils.c | 8 ++-- .../editors/space_buttons/buttons_texture.c | 2 +- source/blender/editors/space_view3d/view3d_edit.c | 2 +- 10 files changed, 73 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index b32b7145ff4..419fb4cedae 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -32,6 +32,7 @@ * \ingroup bke */ +struct bContext; struct Brush; struct MDisps; struct MeshElemMap; @@ -55,6 +56,7 @@ void free_paint(struct Paint *p); void copy_paint(struct Paint *src, struct Paint *tar); struct Paint *paint_get_active(struct Scene *sce); +struct Paint *paint_get_active_from_context(const struct bContext *C); struct Brush *paint_brush(struct Paint *paint); void paint_brush_set(struct Paint *paint, struct Brush *br); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index c7f904755d9..25553448306 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -41,6 +41,7 @@ #include "BLI_utildefines.h" #include "BKE_brush.h" +#include "BKE_context.h" #include "BKE_library.h" #include "BKE_paint.h" #include "BKE_subsurf.h" @@ -83,6 +84,53 @@ Paint *paint_get_active(Scene *sce) return NULL; } +Paint *paint_get_active_from_context(const bContext *C) +{ + Scene *sce = CTX_data_scene(C); + + if (sce) { + ToolSettings *ts = sce->toolsettings; + Object *obact = NULL; + + if (sce->basact && sce->basact->object) + obact = sce->basact->object; + + if (CTX_wm_space_image(C) != NULL) { + if (obact->mode == OB_MODE_EDIT) { + if (ts->use_uv_sculpt) + return &ts->uvsculpt->paint; + else + return &ts->imapaint.paint; + } + else { + return &ts->imapaint.paint; + } + } + else { + switch (obact->mode) { + case OB_MODE_SCULPT: + return &ts->sculpt->paint; + case OB_MODE_VERTEX_PAINT: + return &ts->vpaint->paint; + case OB_MODE_WEIGHT_PAINT: + return &ts->wpaint->paint; + case OB_MODE_TEXTURE_PAINT: + return &ts->imapaint.paint; + case OB_MODE_EDIT: + if (ts->use_uv_sculpt) + return &ts->uvsculpt->paint; + else + return &ts->imapaint.paint; + } + + /* default to image paint */ + return &ts->imapaint.paint; + } + } + + return NULL; +} + Brush *paint_brush(Paint *p) { return p ? p->brush : NULL; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index b5d44676cf6..5ca436b07b2 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -333,7 +333,7 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, float location[3]) { Scene *scene = CTX_data_scene(C); - Paint *paint = paint_get_active(scene); + Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); float window[2]; int hit; @@ -503,7 +503,7 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) { Scene *scene = CTX_data_scene(C); - Paint *paint = paint_get_active(scene); + Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); ViewContext vc; float final_radius; @@ -605,7 +605,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) void paint_cursor_start(bContext *C, int (*poll)(bContext *C)) { - Paint *p = paint_get_active(CTX_data_scene(C)); + Paint *p = paint_get_active_from_context(C); if (p && !p->paint_cursor) p->paint_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), poll, paint_draw_cursor, NULL); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index ed86cb67687..4dee83dbb82 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -5215,7 +5215,7 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) Scene *scene = CTX_data_scene(C); //Brush *brush= image_paint_brush(C); - Paint *paint = paint_get_active(scene); + Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); if (paint && brush && paint->flags & PAINT_SHOW_BRUSH) { @@ -5420,13 +5420,12 @@ void PAINT_OT_grab_clone(wmOperatorType *ot) static int sample_color_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); Brush *brush = image_paint_brush(C); ARegion *ar = CTX_wm_region(C); int location[2]; RNA_int_get_array(op->ptr, "location", location); - paint_sample_color(scene, ar, location[0], location[1]); + paint_sample_color(C, ar, location[0], location[1]); WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush); diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index de149bf2806..794e7755636 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -137,7 +137,7 @@ float paint_get_tex_pixel(struct Brush *br, float u, float v); int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface); void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]); -void paint_sample_color(struct Scene *scene, struct ARegion *ar, int x, int y); +void paint_sample_color(const struct bContext *C, struct ARegion *ar, int x, int y); void BRUSH_OT_curve_preset(struct wmOperatorType *ot); void PAINT_OT_face_select_linked(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 23d1c0090a0..7df6a893b5c 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -60,7 +60,7 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)) { /*int type = RNA_enum_get(op->ptr, "type");*/ - Paint *paint = paint_get_active(CTX_data_scene(C)); + Paint *paint = paint_get_active_from_context(C); struct Brush *br = paint_brush(paint); if (br) @@ -68,7 +68,7 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)) else br = BKE_brush_add("Brush"); - paint_brush_set(paint_get_active(CTX_data_scene(C)), br); + paint_brush_set(paint, br); return OPERATOR_FINISHED; } @@ -91,7 +91,7 @@ static void BRUSH_OT_add(wmOperatorType *ot) static int brush_scale_size_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Paint *paint = paint_get_active(scene); + Paint *paint = paint_get_active_from_context(C); struct Brush *brush = paint_brush(paint); // Object *ob= CTX_data_active_object(C); float scalar = RNA_float_get(op->ptr, "scalar"); @@ -173,7 +173,7 @@ static void PAINT_OT_vertex_color_set(wmOperatorType *ot) static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op)) { - Paint *paint = paint_get_active(CTX_data_scene(C)); + Paint *paint = paint_get_active_from_context(C); struct Brush *brush = paint_brush(paint); Object *ob = CTX_data_active_object(C); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 987ab932fd6..e36056e0fd9 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -100,10 +100,11 @@ typedef struct PaintStroke { /*** Cursor ***/ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata) { - Brush *brush = paint_brush(paint_get_active(CTX_data_scene(C))); + Paint *paint = paint_get_active_from_context(C); + Brush *brush = paint_brush(paint); PaintStroke *stroke = customdata; - glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col); + glColor4ubv(paint->paint_cursor_col); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); @@ -141,7 +142,7 @@ static float event_tablet_data(wmEvent *event, int *pen_flip) static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse_in[2]) { Scene *scene = CTX_data_scene(C); - Paint *paint = paint_get_active(scene); + Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); PaintStroke *stroke = op->customdata; float mouse[3]; @@ -281,7 +282,7 @@ PaintStroke *paint_stroke_new(bContext *C, { PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke"); - stroke->brush = paint_brush(paint_get_active(CTX_data_scene(C))); + stroke->brush = paint_brush(paint_get_active_from_context(C)); view3d_set_viewcontext(C, &stroke->vc); view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats); @@ -394,7 +395,7 @@ static void paint_stroke_sample_average(const PaintStroke *stroke, int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) { - Paint *p = paint_get_active(CTX_data_scene(C)); + Paint *p = paint_get_active_from_context(C); PaintStroke *stroke = op->customdata; PaintSample sample_average; float mouse[2]; @@ -518,7 +519,7 @@ void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data) int paint_poll(bContext *C) { - Paint *p = paint_get_active(CTX_data_scene(C)); + Paint *p = paint_get_active_from_context(C); Object *ob = CTX_data_active_object(C); return p && ob && paint_brush(p) && diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 4c374674c9a..082e40f8e4c 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -333,9 +333,9 @@ int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *index, } /* used for both 3d view and image window */ -void paint_sample_color(Scene *scene, ARegion *ar, int x, int y) /* frontbuf */ +void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* frontbuf */ { - Brush *br = paint_brush(paint_get_active(scene)); + Brush *br = paint_brush(paint_get_active_from_context(C)); unsigned int col; char *cp; @@ -357,7 +357,7 @@ void paint_sample_color(Scene *scene, ARegion *ar, int x, int y) /* frontbuf static int brush_curve_preset_exec(bContext *C, wmOperator *op) { - Brush *br = paint_brush(paint_get_active(CTX_data_scene(C))); + Brush *br = paint_brush(paint_get_active_from_context(C)); BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape")); return OPERATOR_FINISHED; @@ -365,7 +365,7 @@ static int brush_curve_preset_exec(bContext *C, wmOperator *op) static int brush_curve_preset_poll(bContext *C) { - Brush *br = paint_brush(paint_get_active(CTX_data_scene(C))); + Brush *br = paint_brush(paint_get_active_from_context(C)); return br && br->curve; } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 5c5c24f7bc1..cdecda63432 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -175,7 +175,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * if (!(pinid || pinid == &scene->id)) { ob = (scene->basact) ? scene->basact->object : NULL; wrld = scene->world; - brush = paint_brush(paint_get_active(scene)); + brush = paint_brush(paint_get_active_from_context(C)); } if (ob && ob->type == OB_LAMP && !la) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 8ba0d75c786..d632314f3ca 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -498,7 +498,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) static void viewops_data_free(bContext *C, wmOperator *op) { ARegion *ar; - Paint *p = paint_get_active(CTX_data_scene(C)); + Paint *p = paint_get_active_from_context(C); if (op->customdata) { ViewOpsData *vod = op->customdata; -- cgit v1.2.3 From eb811920692551995526b6449ef618e70de8981d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 07:43:36 +0000 Subject: Tag unused variables --- source/blender/editors/space_console/console_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 44dda60edd0..7efcbcceb3c 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -429,7 +429,7 @@ void CONSOLE_OT_insert(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -static int console_indent_exec(bContext *C, wmOperator *op) +static int console_indent_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceConsole *sc = CTX_wm_space_console(C); ARegion *ar = CTX_wm_region(C); @@ -471,7 +471,7 @@ void CONSOLE_OT_indent(wmOperatorType *ot) ot->poll = ED_operator_console_active; } -static int console_unindent_exec(bContext *C, wmOperator *op) +static int console_unindent_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceConsole *sc = CTX_wm_space_console(C); ARegion *ar = CTX_wm_region(C); -- cgit v1.2.3 From 1511bd8eb47fdbd37af065ee4d06d499fa8a68b6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 07:44:57 +0000 Subject: Correction to recent changes in paint module -- missed NULL check for active object --- source/blender/blenkernel/intern/paint.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 25553448306..f7e3e103e99 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -106,7 +106,7 @@ Paint *paint_get_active_from_context(const bContext *C) return &ts->imapaint.paint; } } - else { + else if (obact) { switch (obact->mode) { case OB_MODE_SCULPT: return &ts->sculpt->paint; @@ -122,7 +122,8 @@ Paint *paint_get_active_from_context(const bContext *C) else return &ts->imapaint.paint; } - + } + else { /* default to image paint */ return &ts->imapaint.paint; } -- cgit v1.2.3 From 617027fdf33f2406ef7ea32ee6121825e3e18a5d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 10:41:18 +0000 Subject: Fix #31352: Image sequence texture - can't load image after changing image source Added new flag to Imageuser which indicates whether user frame calculation is needed. This flag is getting set in BKE_image_signal and handled in actual image usage areas where both image user and current frame is known. --- source/blender/blenkernel/BKE_image.h | 5 ++ source/blender/blenkernel/intern/image.c | 80 +++++++++++++++++++++- source/blender/editors/space_image/image_buttons.c | 2 + source/blender/editors/space_image/image_ops.c | 57 +++------------ source/blender/editors/space_image/space_image.c | 3 +- source/blender/makesdna/DNA_image_types.h | 1 + .../blender/render/intern/source/render_texture.c | 3 +- 7 files changed, 97 insertions(+), 54 deletions(-) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 91e3e9edbf0..ac3daef77f7 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -44,6 +44,7 @@ struct anim; struct Scene; struct Object; struct ImageFormatData; +struct Main; /* call from library */ void BKE_image_free(struct Image *me); @@ -143,6 +144,9 @@ struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf); /* for reload, refresh, pack */ void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal); +void BKE_image_walk_all_users(const struct Main *mainp, void *customdata, + void callback(struct Image *ima, struct ImageUser *iuser, void *customdata)); + /* ensures an Image exists for viewing nodes or render */ struct Image *BKE_image_verify_viewer(int type, const char *name); @@ -151,6 +155,7 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); /* called on frame change or before render */ void BKE_image_user_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); +void BKE_image_user_check_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); int BKE_image_user_frame_get(const struct ImageUser *iuser, int cfra, int fieldnr); /* sets index offset for multilayer files */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a2b1fb10500..3748a474ddd 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -91,6 +91,14 @@ #include "BLO_sys_types.h" // for intptr_t support +/* for image user iteration */ +#include "DNA_node_types.h" +#include "DNA_space_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" + +#include "WM_api.h" + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -1814,6 +1822,65 @@ void BKE_image_assign_ibuf(Image *ima, ImBuf *ibuf) image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } +void BKE_image_walk_all_users(const Main *mainp, void *customdata, + void callback(Image *ima, ImageUser *iuser, void *customdata)) +{ + wmWindowManager *wm; + wmWindow *win; + Tex *tex; + + /* texture users */ + for (tex = mainp->tex.first; tex; tex = tex->id.next) { + if (tex->type == TEX_IMAGE && tex->ima) { + if (ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + callback(tex->ima, &tex->iuser, customdata); + } + } + } + + /* image window, compo node users */ + for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ + for (win = wm->windows.first; win; win = win->next) { + ScrArea *sa; + for (sa = win->screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + View3D *v3d = sa->spacedata.first; + BGpic *bgpic; + for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { + callback(bgpic->ima, &bgpic->iuser, customdata); + } + } + else if (sa->spacetype == SPACE_IMAGE) { + SpaceImage *sima = sa->spacedata.first; + callback(sima->image, &sima->iuser, customdata); + } + else if (sa->spacetype == SPACE_NODE) { + SpaceNode *snode = sa->spacedata.first; + if ((snode->treetype == NTREE_COMPOSIT) && (snode->nodetree)) { + bNode *node; + for (node = snode->nodetree->nodes.first; node; node = node->next) { + if (node->id && node->type == CMP_NODE_IMAGE) { + Image *ima = (Image *)node->id; + ImageUser *iuser = node->storage; + callback(ima, iuser, customdata); + } + } + } + } + } + } + } +} + +static void image_tag_frame_recalc(Image *ima, ImageUser *iuser, void *customdata) +{ + Image *changed_image = customdata; + + if (ima == changed_image) { + iuser->flag |= IMA_NEED_FRAME_RECALC; + } +} + void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) { if (ima == NULL) @@ -1847,6 +1914,9 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) ima->ok = 1; if (iuser) iuser->ok = 1; + + BKE_image_walk_all_users(G.main, ima, image_tag_frame_recalc); + break; case IMA_SIGNAL_RELOAD: @@ -2669,6 +2739,15 @@ void BKE_image_user_frame_calc(ImageUser *iuser, int cfra, int fieldnr) if (iuser->ok == 0) iuser->ok = 1; } +void BKE_image_user_check_frame_calc(ImageUser *iuser, int cfra, int fieldnr) +{ + if ((iuser->flag & IMA_ANIM_ALWAYS) || (iuser->flag & IMA_NEED_FRAME_RECALC)) { + BKE_image_user_frame_calc(iuser, cfra, fieldnr); + + iuser->flag &= ~IMA_NEED_FRAME_RECALC; + } +} + int BKE_image_has_alpha(struct Image *image) { ImBuf *ibuf; @@ -2684,4 +2763,3 @@ int BKE_image_has_alpha(struct Image *image) else return 0; } - diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 6e52056ff2b..332a2ecada4 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -637,6 +637,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char ima = imaptr.data; iuser = userptr->data; + BKE_image_user_check_frame_calc(iuser, (int)scene->r.cfra, 0); + cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); cb->ptr = *ptr; cb->prop = prop; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 2cb36841082..02b95f8e7c8 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2443,56 +2443,15 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot) /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */ +static void image_update_frame(struct Image *UNUSED(ima), struct ImageUser *iuser, void *customdata) +{ + int cfra = *(int*)customdata; + + BKE_image_user_check_frame_calc(iuser, cfra, 0); +} + void ED_image_update_frame(const Main *mainp, int cfra) { - wmWindowManager *wm; - wmWindow *win; - Tex *tex; - - /* texture users */ - for (tex = mainp->tex.first; tex; tex = tex->id.next) { - if (tex->type == TEX_IMAGE && tex->ima) { - if (ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - if (tex->iuser.flag & IMA_ANIM_ALWAYS) - BKE_image_user_frame_calc(&tex->iuser, cfra, 0); - } - } - } - - /* image window, compo node users */ - for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ - for (win = wm->windows.first; win; win = win->next) { - ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - View3D *v3d = sa->spacedata.first; - BGpic *bgpic; - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) - if (bgpic->iuser.flag & IMA_ANIM_ALWAYS) - BKE_image_user_frame_calc(&bgpic->iuser, cfra, 0); - } - else if (sa->spacetype == SPACE_IMAGE) { - SpaceImage *sima = sa->spacedata.first; - if (sima->iuser.flag & IMA_ANIM_ALWAYS) - BKE_image_user_frame_calc(&sima->iuser, cfra, 0); - } - else if (sa->spacetype == SPACE_NODE) { - SpaceNode *snode = sa->spacedata.first; - if ((snode->treetype == NTREE_COMPOSIT) && (snode->nodetree)) { - bNode *node; - for (node = snode->nodetree->nodes.first; node; node = node->next) { - if (node->id && node->type == CMP_NODE_IMAGE) { - Image *ima = (Image *)node->id; - ImageUser *iuser = node->storage; - if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) - if (iuser->flag & IMA_ANIM_ALWAYS) - BKE_image_user_frame_calc(iuser, cfra, 0); - } - } - } - } - } - } - } + BKE_image_walk_all_users(mainp, &cfra, image_update_frame); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a8d83500cc1..a2a16fd84a8 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -590,8 +590,7 @@ static void image_refresh(const bContext *C, ScrArea *UNUSED(sa)) ima = ED_space_image(sima); - if (sima->iuser.flag & IMA_ANIM_ALWAYS) - BKE_image_user_frame_calc(&sima->iuser, scene->r.cfra, 0); + BKE_image_user_check_frame_calc(&sima->iuser, scene->r.cfra, 0); /* check if we have to set the image from the editmesh */ if (ima && (ima->source == IMA_SRC_VIEWER || sima->pin)) ; diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index dfc70e5bd66..f6c4822bb55 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -65,6 +65,7 @@ typedef struct ImageUser { #define IMA_ANIM_ALWAYS 1 #define IMA_ANIM_REFRESHED 2 /* #define IMA_DO_PREMUL 4 */ +#define IMA_NEED_FRAME_RECALC 8 typedef struct Image { ID id; diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 5c45be3f03a..f6fe8e8974d 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -3534,8 +3534,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene) /* update image sequences and movies */ if (tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - if (tex->iuser.flag & IMA_ANIM_ALWAYS) - BKE_image_user_frame_calc(&tex->iuser, (int)scene->r.cfra, 0); + BKE_image_user_check_frame_calc(&tex->iuser, (int)scene->r.cfra, 0); } } } -- cgit v1.2.3 From 0f2b4d4dff0ee17933571cd2f572670ea2770c86 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 10:51:00 +0000 Subject: Fix for relative blur size for non-fast gaussian blur methods. Call base blur's initExecution from GaussianBokehBlurOperation and GaussianXBlurOperation --- source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp | 2 ++ source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index b5d175729f3..642a28627bd 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -43,6 +43,8 @@ void *GaussianBokehBlurOperation::initializeTileData(rcti *rect, MemoryBuffer ** void GaussianBokehBlurOperation::initExecution() { + BlurBaseOperation::initExecution(); + if (this->sizeavailable) { updateGauss(NULL); } diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 121bbbd45a0..852754416f4 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -45,6 +45,8 @@ void *GaussianXBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memo void GaussianXBlurOperation::initExecution() { + BlurBaseOperation::initExecution(); + if (this->sizeavailable) { float rad = size*this->data->sizex; if (rad<1) -- cgit v1.2.3 From 9a488fd8b8174f3f052f9b2b21a7ff1f1d73a46d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 Jun 2012 12:01:49 +0000 Subject: Fix for recent library linking fix, this triggered another issue that was hidden by libraries getting loaded twice, hopefully it's working ok now, tested with various .blend files. --- source/blender/blenloader/intern/readfile.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8710c5fe075..8e9394a886e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7859,10 +7859,17 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old) /* Update: the issue is that in file reading, the oldnewmap is OK, but for existing data, it has to be * inserted in the map to be found! */ - if (id->flag & LIB_PRE_EXISTING) - oldnewmap_insert(fd->libmap, bhead->old, id, 1); - + + /* Update: previously it was checking for id->flag & LIB_PRE_EXISTING, however that does not affect file + * reading. For file reading we may need to insert it into the libmap as well, because you might have + * two files indirectly linking the same datablock, and in that case we need this in the libmap for the + * fd of both those files. + * + * The crash that this check avoided earlier was because bhead->code wasn't properly passed in, making + * change_idid_adr not detect the mapping was for an ID_ID datablock. */ + oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code); change_idid_adr_fd(fd, bhead->old, id); + // commented because this can print way too much // if (G.debug & G_DEBUG) printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name); } @@ -7878,7 +7885,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old) else { /* this is actually only needed on UI call? when ID was already read before, and another append * happens which invokes same ID... in that case the lookup table needs this entry */ - oldnewmap_insert(fd->libmap, bhead->old, id, 1); + oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code); // commented because this can print way too much // if (G.debug & G_DEBUG) printf("expand: already read %s\n", id->name); } @@ -8763,7 +8770,7 @@ static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, cons else { /* already linked */ printf("append: already linked\n"); - oldnewmap_insert(fd->libmap, bhead->old, id, 1); + oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code); if (id->flag & LIB_INDIRECT) { id->flag -= LIB_INDIRECT; id->flag |= LIB_EXTERN; -- cgit v1.2.3 From 4b4bf1146997636e581465a73074b8f68b56f8a9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 12:10:38 +0000 Subject: Fix #31172: applying boolean removes uv maps The issue was caused by CDDM_tessfaces_to_faces not dealing with CD layers. There was already function BKE_mesh_convert_mfaces_to_mpolys which converted mfaces to mpolys with converting all CD layers. Made it a bit more general so it might work with given arrays of faces/polys and re-used it from CDDM module. Checked with UV and sculpt data from Blender 2.61 and it loaded nice, so hopefully there's no regressions in loading older files. --- source/blender/blenkernel/BKE_mesh.h | 8 ++ source/blender/blenkernel/intern/cdderivedmesh.c | 93 ++------------ source/blender/blenkernel/intern/mesh.c | 147 ++++++++++++++--------- 3 files changed, 102 insertions(+), 146 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 7abec074647..1878e43f577 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -33,6 +33,7 @@ /***/ +struct ID; struct BoundBox; struct DispList; struct ListBase; @@ -150,6 +151,13 @@ void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); void BKE_mesh_delete_material_index(struct Mesh *me, short index); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh); +void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id, + struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, + int totedge_i, int totface_i, int totloop_i, int totpoly_i, + struct MEdge *medge, struct MFace *mface, + int *totloop_r, int *totpoly_r, + struct MLoop **mloop_r, struct MPoly **mpoly_r); + void BKE_mesh_calc_normals_tessface(struct MVert *mverts, int numVerts, struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]); /* used for unit testing; compares two meshes, checking only diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 4e6a4b4a43c..e5e73061d52 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2594,94 +2594,15 @@ MPoly *CDDM_get_polys(DerivedMesh *dm) void CDDM_tessfaces_to_faces(DerivedMesh *dm) { - /*converts mfaces to mpolys/mloops*/ + /* converts mfaces to mpolys/mloops */ CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - MFace *mf; - MEdge *me; - EdgeHash *eh = BLI_edgehash_new(); - int i, totloop; - /* ... on second thaughts, better comment this and assume caller knows edge state. */ -#if 0 - /* ensure we have all the edges we need */ - CDDM_calc_edges_tessface(dm); -#else -# ifndef NDEBUG - { - /* ensure we have correct edges on non release builds */ - i = cddm->dm.numEdgeData; - CDDM_calc_edges_tessface(dm); - BLI_assert(cddm->dm.numEdgeData == i); - } -# endif -#endif - - /*build edge hash*/ - me = cddm->medge; - for (i = 0; i < cddm->dm.numEdgeData; i++, me++) { - BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); - } - - mf = cddm->mface; - totloop = 0; - for (i = 0; i < cddm->dm.numTessFaceData; i++, mf++) { - totloop += mf->v4 ? 4 : 3; - } - - CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData); - CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData); - - cddm->dm.numLoopData = totloop; - cddm->dm.numPolyData = cddm->dm.numTessFaceData; - - if (totloop) { - MLoop *ml; - MPoly *mp; - int l, *polyindex; - - cddm->mloop = MEM_callocN(sizeof(MLoop) * totloop, "cddm->mloop in CDDM_tessfaces_to_faces"); - cddm->mpoly = MEM_callocN(sizeof(MPoly) * cddm->dm.numTessFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces"); - - CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop); - CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData); - CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, - CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numTessFaceData); - - polyindex = CustomData_get_layer(&cddm->dm.faceData, CD_POLYINDEX); - - mf = cddm->mface; - mp = cddm->mpoly; - ml = cddm->mloop; - l = 0; - for (i = 0; i < cddm->dm.numTessFaceData; i++, mf++, mp++, polyindex++) { - mp->flag = mf->flag; - mp->loopstart = l; - mp->mat_nr = mf->mat_nr; - mp->totloop = mf->v4 ? 4 : 3; - - ml->v = mf->v1; - ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); - ml++, l++; - - ml->v = mf->v2; - ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3)); - ml++, l++; - - ml->v = mf->v3; - ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4 ? mf->v4 : mf->v1)); - ml++, l++; - - if (mf->v4) { - ml->v = mf->v4; - ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1)); - ml++, l++; - } - - *polyindex = i; - } - } - - BLI_edgehash_free(eh, NULL); + BKE_mesh_convert_mfaces_to_mpolys_ex(NULL, &cddm->dm.faceData, &cddm->dm.loopData, &cddm->dm.polyData, + cddm->dm.numEdgeData, cddm->dm.numTessFaceData, + cddm->dm.numLoopData, cddm->dm.numPolyData, + cddm->medge, cddm->mface, + &cddm->dm.numLoopData, &cddm->dm.numPolyData, + &cddm->mloop, &cddm->mpoly); } void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index fd952b7b518..5db565d343c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1946,8 +1946,8 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, MEM_freeN(fnors); } - -static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, int numCol) +static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, + MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol) { MTFace *texface; MTexPoly *texpoly; @@ -1957,15 +1957,15 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, MFace *mf; int i; - mf = me->mface + findex; + mf = mface + findex; for (i = 0; i < numTex; i++) { - texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i); - texpoly = CustomData_get_n(&me->pdata, CD_MTEXPOLY, findex, i); - + texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, findex, i); + ME_MTEXFACE_CPY(texpoly, texface); - - mloopuv = CustomData_get_n(&me->ldata, CD_MLOOPUV, loopstart, i); + + mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i); copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++; copy_v2_v2(mloopuv->uv, texface->uv[1]); mloopuv++; copy_v2_v2(mloopuv->uv, texface->uv[2]); mloopuv++; @@ -1976,8 +1976,8 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, } for (i = 0; i < numCol; i++) { - mloopcol = CustomData_get_n(&me->ldata, CD_MLOOPCOL, loopstart, i); - mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i); + mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i); + mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]); mloopcol++; MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[1]); mloopcol++; @@ -1986,21 +1986,23 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[3]); mloopcol++; } } - - if (CustomData_has_layer(&me->fdata, CD_MDISPS)) { - MDisps *ld = CustomData_get(&me->ldata, loopstart, CD_MDISPS); - MDisps *fd = CustomData_get(&me->fdata, findex, CD_MDISPS); + + if (CustomData_has_layer(fdata, CD_MDISPS)) { + MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS); + MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS); float (*disps)[3] = fd->disps; int i, tot = mf->v4 ? 4 : 3; int side, corners; - if (CustomData_external_test(&me->fdata, CD_MDISPS)) { - CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, - me->totloop, me->fdata.external->filename); + if (CustomData_external_test(fdata, CD_MDISPS)) { + if (id) { + CustomData_external_add(ldata, id, CD_MDISPS, + totloop, fdata->external->filename); + } } - + corners = multires_mdisp_corners(fd); - + if (corners == 0) { /* Empty MDisp layers appear in at least one of the sintel.blend files. * Not sure why this happens, but it seems fine to just ignore them here. @@ -2009,14 +2011,14 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, } else { side = sqrt(fd->totdisp / corners); - + for (i = 0; i < tot; i++, disps += side * side, ld++) { ld->totdisp = side * side; ld->level = (int)(logf(side - 1.0f) / (float)M_LN2) + 1; - + if (ld->disps) MEM_freeN(ld->disps); - + ld->disps = MEM_callocN(sizeof(float) * 3 * side * side, "converted loop mdisps"); if (fd->disps) { memcpy(ld->disps, disps, sizeof(float) * 3 * side * side); @@ -2027,71 +2029,88 @@ static void bm_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, } void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) +{ + BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata, + mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly, + mesh->medge, mesh->mface, + &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly); + + mesh_update_customdata_pointers(mesh, TRUE); +} + +void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, + int totedge_i, int totface_i, int totloop_i, int totpoly_i, + MEdge *medge, MFace *mface, + int *totloop_r, int *totpoly_r, + MLoop **mloop_r, MPoly **mpoly_r) { MFace *mf; - MLoop *ml; - MPoly *mp; + MLoop *ml, *mloop; + MPoly *mp, *mpoly; MEdge *me; EdgeHash *eh; int numTex, numCol; - int i, j, totloop; + int i, j, totloop, totpoly, *polyindex; /* just in case some of these layers are filled in (can happen with python created meshes) */ - CustomData_free(&mesh->ldata, mesh->totloop); - CustomData_free(&mesh->pdata, mesh->totpoly); - memset(&mesh->ldata, 0, sizeof(mesh->ldata)); - memset(&mesh->pdata, 0, sizeof(mesh->pdata)); + CustomData_free(ldata, totloop_i); + CustomData_free(pdata, totpoly_i); + memset(ldata, 0, sizeof(*ldata)); + memset(pdata, 0, sizeof(*pdata)); - mesh->totpoly = mesh->totface; - mesh->mpoly = MEM_callocN(sizeof(MPoly) * mesh->totpoly, "mpoly converted"); - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_ASSIGN, mesh->mpoly, mesh->totpoly); + totpoly = totface_i; + mpoly = MEM_callocN(sizeof(MPoly) * totpoly, "mpoly converted"); + CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly); + + numTex = CustomData_number_of_layers(fdata, CD_MTFACE); + numCol = CustomData_number_of_layers(fdata, CD_MCOL); - numTex = CustomData_number_of_layers(&mesh->fdata, CD_MTFACE); - numCol = CustomData_number_of_layers(&mesh->fdata, CD_MCOL); - totloop = 0; - mf = mesh->mface; - for (i = 0; i < mesh->totface; i++, mf++) { + mf = mface; + for (i = 0; i < totface_i; i++, mf++) { totloop += mf->v4 ? 4 : 3; } - - mesh->totloop = totloop; - mesh->mloop = MEM_callocN(sizeof(MLoop) * mesh->totloop, "mloop converted"); - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_ASSIGN, mesh->mloop, totloop); - CustomData_to_bmeshpoly(&mesh->fdata, &mesh->pdata, &mesh->ldata, - mesh->totloop, mesh->totpoly); + mloop = MEM_callocN(sizeof(MLoop) * totloop, "mloop converted"); - /* ensure external data is transferred */ - CustomData_external_read(&mesh->fdata, &mesh->id, CD_MASK_MDISPS, mesh->totface); + CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop); + + CustomData_to_bmeshpoly(fdata, pdata, ldata, totloop, totpoly); + + if (id) { + /* ensure external data is transferred */ + CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i); + } eh = BLI_edgehash_new(); - /*build edge hash*/ - me = mesh->medge; - for (i = 0; i < mesh->totedge; i++, me++) { + /* build edge hash */ + me = medge; + for (i = 0; i < totedge_i; i++, me++) { BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i)); /* unrelated but avoid having the FGON flag enabled, so we can reuse it later for something else */ me->flag &= ~ME_FGON; } - j = 0; /*current loop index*/ - ml = mesh->mloop; - mf = mesh->mface; - mp = mesh->mpoly; - for (i = 0; i < mesh->totface; i++, mf++, mp++) { + polyindex = CustomData_get_layer(fdata, CD_POLYINDEX); + + j = 0; /* current loop index */ + ml = mloop; + mf = mface; + mp = mpoly; + for (i = 0; i < totface_i; i++, mf++, mp++) { mp->loopstart = j; - + mp->totloop = mf->v4 ? 4 : 3; mp->mat_nr = mf->mat_nr; mp->flag = mf->flag; - + # define ML(v1, v2) { \ ml->v = mf->v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); ml++; j++; \ } (void)0 - + ML(v1, v2); ML(v2, v3); if (mf->v4) { @@ -2101,18 +2120,26 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) else { ML(v3, v1); } - + # undef ML - bm_corners_to_loops(mesh, i, mp->loopstart, numTex, numCol); + bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol); + + if (polyindex) { + *polyindex = i; + polyindex++; + } } /* note, we don't convert FGons at all, these are not even real ngons, * they have their own UV's, colors etc - its more an editing feature. */ - mesh_update_customdata_pointers(mesh, TRUE); - BLI_edgehash_free(eh, NULL); + + *totpoly_r = totpoly; + *totloop_r = totloop; + *mpoly_r = mpoly; + *mloop_r = mloop; } float (*mesh_getVertexCos(Mesh * me, int *numVerts_r))[3] -- cgit v1.2.3 From 0259d5de41de65d59cfcf1a0023032f085e50148 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 4 Jun 2012 12:29:37 +0000 Subject: Attempted fix for borderselect crash that Jeremy (@Mango) is getting on a particular file in Pose Mode --- source/blender/editors/space_view3d/view3d_select.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 602f790c8df..646defe8569 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1870,7 +1870,6 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i for (base = vc->scene->base.first; base && hits; base = base->next) { if (BASE_SELECTABLE(vc->v3d, base)) { while (base->selcol == (*col & 0xFFFF)) { /* we got an object */ - if (*col & 0xFFFF0000) { /* we got a bone */ bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY)); if (bone) { @@ -1897,7 +1896,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i else ED_base_object_select(base, BA_DESELECT); } - + col += 4; /* next color */ hits--; if (hits == 0) break; @@ -1906,13 +1905,16 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i if (bone_selected) { Object *ob = base->object; - bArmature *arm = ob->data; - - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); - if (arm->flag & ARM_HAS_VIZ_DEPS) { - /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + if (ob && (ob->type == OB_ARMATURE)) { + bArmature *arm = ob->data; + + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); + + if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) { + /* mask modifier ('armature' mode), etc. */ + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } } } } -- cgit v1.2.3 From d27ea22953ff002952e576d13505998ec01a1254 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 4 Jun 2012 13:07:41 +0000 Subject: Removed some old cruft - commented out select_actionchannel_by_name() lines --- source/blender/editors/armature/editarmature.c | 12 +----------- source/blender/editors/space_view3d/view3d_select.c | 3 --- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index fdebddbf41d..48743c68ff5 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -2297,7 +2297,7 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d) ED_armature_deselect_all(obedit, 0); - /* Create a bone */ + /* Create a bone */ bone = ED_armature_edit_bone_add(arm, "Bone"); arm->act_edbone = bone; @@ -2308,7 +2308,6 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d) add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1 else add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z - } @@ -4528,9 +4527,6 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor ED_pose_deselectall(ob, 0); nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = nearBone; - - // XXX old cruft! use notifiers instead - //select_actionchannel_by_name(ob->action, nearBone->name, 1); } else { if (extend) { @@ -4548,17 +4544,11 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor } else { nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - - // XXX old cruft! use notifiers instead - //select_actionchannel_by_name(ob->action, nearBone->name, 0); } } else { nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = nearBone; - - // XXX old cruft! use notifiers instead - //select_actionchannel_by_name(ob->action, nearBone->name, 1); } } } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 646defe8569..d2f2fdcaa81 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1877,16 +1877,13 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i if ((bone->flag & BONE_UNSELECTABLE) == 0) { bone->flag |= BONE_SELECTED; bone_selected = 1; -// XXX select_actionchannel_by_name(base->object->action, bone->name, 1); } } else { bArmature *arm = base->object->data; bone->flag &= ~BONE_SELECTED; -// XXX select_actionchannel_by_name(base->object->action, bone->name, 0); if (arm->act_bone == bone) arm->act_bone = NULL; - } } } -- cgit v1.2.3 From f53a52ba1cc682f36551c9b96e8cd00bfb6372bc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 13:19:17 +0000 Subject: Fix #31697: Blender crashes when using several viewer nodes in tile Issue was caused by fact that viewer node might re-size ImBuf used for viewer node result, so if several viewer nodes are running for inputs with different resolutions it'll result in a crash, Now copied behavior or pre-tile compositor -- execute viewer node which has NODE_DO_OUTPUT flag, so no several nodes would be calculated at once. Should be pretty ok because calculation of several viewers doesn't actually make sense because there's only one buffer they might use and it's getting re-calculated when changing active viewer node. --- source/blender/compositor/nodes/COM_ViewerNode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index 3282929af52..db4fd115d73 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -36,8 +36,8 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * InputSocket *alphaSocket = this->getInputSocket(1); Image *image = (Image*)this->getbNode()->id; ImageUser * imageUser = (ImageUser*) this->getbNode()->storage; - if (imageSocket->isConnected()) { - bNode *editorNode = this->getbNode(); + bNode *editorNode = this->getbNode(); + if (imageSocket->isConnected() && (editorNode->flag & NODE_DO_OUTPUT)) { ViewerOperation *viewerOperation = new ViewerOperation(); viewerOperation->setColorManagement(context->getScene()->r.color_mgt_flag & R_COLOR_MANAGEMENT); viewerOperation->setColorPredivide(context->getScene()->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); -- cgit v1.2.3 From 8e01389a4e34b81c28aea7ac7fbb590b314624e3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 4 Jun 2012 15:13:36 +0000 Subject: Fix #31559: second 3D viewport does not update when paiting vertex/weight Added notification at the end of weight/vertex paint stroke so all opened viewports would be updated (same was already done for sculpt mode). --- source/blender/editors/sculpt_paint/paint_vertex.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index eb79989b90b..43981770784 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2461,6 +2461,8 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) } DAG_id_tag_update(ob->data, 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } @@ -2954,6 +2956,8 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) { ToolSettings *ts = CTX_data_tool_settings(C); struct VPaintData *vpd = paint_stroke_mode_data(stroke); + ViewContext *vc = &vpd->vc; + Object *ob = vc->obact; if (vpd->vertexcosnos) MEM_freeN(vpd->vertexcosnos); @@ -2966,6 +2970,8 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) BLI_memarena_free(vpd->polyfacemap_arena); } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + MEM_freeN(vpd); } -- cgit v1.2.3 From 115322ef08ed3cff8751a90139024c8b7f3453b1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 15:36:16 +0000 Subject: mask merge (initial copy of editor files) --- source/blender/editors/mask/CMakeLists.txt | 51 + source/blender/editors/mask/SConscript | 9 + source/blender/editors/mask/mask_add.c | 707 +++++++++++++ source/blender/editors/mask/mask_draw.c | 428 ++++++++ source/blender/editors/mask/mask_edit.c | 327 ++++++ source/blender/editors/mask/mask_intern.h | 111 ++ source/blender/editors/mask/mask_ops.c | 1171 ++++++++++++++++++++++ source/blender/editors/mask/mask_relationships.c | 183 ++++ source/blender/editors/mask/mask_select.c | 770 ++++++++++++++ source/blender/editors/mask/mask_shapekey.c | 168 ++++ 10 files changed, 3925 insertions(+) create mode 100644 source/blender/editors/mask/CMakeLists.txt create mode 100644 source/blender/editors/mask/SConscript create mode 100644 source/blender/editors/mask/mask_add.c create mode 100644 source/blender/editors/mask/mask_draw.c create mode 100644 source/blender/editors/mask/mask_edit.c create mode 100644 source/blender/editors/mask/mask_intern.h create mode 100644 source/blender/editors/mask/mask_ops.c create mode 100644 source/blender/editors/mask/mask_relationships.c create mode 100644 source/blender/editors/mask/mask_select.c create mode 100644 source/blender/editors/mask/mask_shapekey.c diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt new file mode 100644 index 00000000000..f15e9c27732 --- /dev/null +++ b/source/blender/editors/mask/CMakeLists.txt @@ -0,0 +1,51 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012 Blender Foundation. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + ../include + ../../blenkernel + ../../blenloader + ../../blenlib + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/guardedalloc + ${GLEW_INCLUDE_PATH} +) + +set(INC_SYS +) + +set(SRC + mask_add.c + mask_draw.c + mask_edit.c + mask_ops.c + mask_relationships.c + mask_select.c + mask_shapekey.c + + mask_intern.h +) + +blender_add_lib(bf_editor_mask "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/mask/SConscript b/source/blender/editors/mask/SConscript new file mode 100644 index 00000000000..4af000d038d --- /dev/null +++ b/source/blender/editors/mask/SConscript @@ -0,0 +1,9 @@ +#!/usr/bin/python +Import ('env') + +sources = env.Glob('*.c') +defs = [] +incs = '../include ../../blenkernel ../../blenloader ../../blenlib ../../windowmanager ../../makesdna' +incs += ' ../../makesrna #/extern/glew/include #/intern/guardedalloc' + +env.BlenderLib ( 'bf_editors_mask', sources, Split(incs), defs, libtype=['core'], priority=[100] ) diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c new file mode 100644 index 00000000000..c2c2ebbfe42 --- /dev/null +++ b/source/blender/editors/mask/mask_add.c @@ -0,0 +1,707 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_add.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_scene_types.h" +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" +#include "ED_keyframing.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + + +static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather, + MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + float *u_r, float tangent[2]) +{ + MaskLayer *masklay, *point_masklay; + MaskSpline *point_spline; + MaskSplinePoint *point = NULL; + float dist, co[2]; + int width, height; + float u; + float scalex, scaley, aspx, aspy; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + float *diff_points; + int tot_diff_point; + + diff_points = BKE_mask_point_segment_diff_with_resolution(spline, cur_point, width, height, + &tot_diff_point); + + if (diff_points) { + int i, tot_feather_point, tot_point; + float *feather_points = NULL, *points; + + if (feather) { + feather_points = BKE_mask_point_segment_feather_diff_with_resolution(spline, cur_point, + width, height, + &tot_feather_point); + + points = feather_points; + tot_point = tot_feather_point; + } + else { + points = diff_points; + tot_point = tot_diff_point; + } + + for (i = 0; i < tot_point - 1; i++) { + float cur_dist, a[2], b[2]; + + a[0] = points[2 * i] * scalex; + a[1] = points[2 * i + 1] * scaley; + + b[0] = points[2 * i + 2] * scalex; + b[1] = points[2 * i + 3] * scaley; + + cur_dist = dist_to_line_segment_v2(co, a, b); + + if (point == NULL || cur_dist < dist) { + if (tangent) + sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); + + point_masklay = masklay; + point_spline = spline; + point = cur_point; + dist = cur_dist; + u = (float)i / tot_point; + + } + } + + if (feather_points) + MEM_freeN(feather_points); + + MEM_freeN(diff_points); + } + } + } + } + + if (point && dist < threshold) { + if (masklay_r) + *masklay_r = point_masklay; + + if (spline_r) + *spline_r = point_spline; + + if (point_r) + *point_r = point; + + if (u_r) { + u = BKE_mask_spline_project_co(point_spline, point, u, normal_co); + + *u_r = u; + } + + return TRUE; + } + + if (masklay_r) + *masklay_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (point_r) + *point_r = NULL; + + return FALSE; +} + +/******************** add vertex *********************/ + +static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, + const float point_co[2], const float tangent[2], const float u, + MaskSplinePoint *reference_point, const short reference_adjacent) +{ + MaskSplinePoint *prev_point = NULL; + MaskSplinePoint *next_point = NULL; + BezTriple *bezt; + int width, height; + float co[3]; + const float len = 20.0; /* default length of handle in pixel space */ + + copy_v2_v2(co, point_co); + co[2] = 0.0f; + + ED_mask_size(C, &width, &height); + + /* point coordinate */ + bezt = &new_point->bezt; + + bezt->h1 = bezt->h2 = HD_ALIGN; + + if (reference_point) { + bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1); + } + else if (reference_adjacent) { + if (spline->tot_point != 1) { + int index = (int)(new_point - spline->points); + prev_point = &spline->points[(index - 1) % spline->tot_point]; + next_point = &spline->points[(index + 1) % spline->tot_point]; + + bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1); + + /* note, we may want to copy other attributes later, radius? pressure? color? */ + } + } + + copy_v3_v3(bezt->vec[0], co); + copy_v3_v3(bezt->vec[1], co); + copy_v3_v3(bezt->vec[2], co); + + /* initial offset for handles */ + if (spline->tot_point == 1) { + /* first point of splien is aligned horizontally */ + bezt->vec[0][0] -= len / width; + bezt->vec[2][0] += len / width; + } + else if (tangent) { + float vec[2]; + + copy_v2_v2(vec, tangent); + + vec[0] *= width; + vec[1] *= height; + + mul_v2_fl(vec, len / len_v2(vec)); + + vec[0] /= width; + vec[1] /= height; + + sub_v2_v2(bezt->vec[0], vec); + add_v2_v2(bezt->vec[2], vec); + + if (reference_adjacent) { + BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); + } + } + else { + + /* calculating auto handles works much nicer */ +#if 0 + /* next points are aligning in the direction of previous/next point */ + MaskSplinePoint *point; + float v1[2], v2[2], vec[2]; + float dir = 1.0f; + + if (new_point == spline->points) { + point = new_point + 1; + dir = -1.0f; + } + else + point = new_point - 1; + + if (spline->tot_point < 3) { + v1[0] = point->bezt.vec[1][0] * width; + v1[1] = point->bezt.vec[1][1] * height; + + v2[0] = new_point->bezt.vec[1][0] * width; + v2[1] = new_point->bezt.vec[1][1] * height; + } + else { + if (new_point == spline->points) { + v1[0] = spline->points[1].bezt.vec[1][0] * width; + v1[1] = spline->points[1].bezt.vec[1][1] * height; + + v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width; + v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height; + } + else { + v1[0] = spline->points[0].bezt.vec[1][0] * width; + v1[1] = spline->points[0].bezt.vec[1][1] * height; + + v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width; + v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height; + } + } + + sub_v2_v2v2(vec, v1, v2); + mul_v2_fl(vec, len * dir / len_v2(vec)); + + vec[0] /= width; + vec[1] /= height; + + add_v2_v2(bezt->vec[0], vec); + sub_v2_v2(bezt->vec[2], vec); +#else + BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); + BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); + +#endif + } + + BKE_mask_parent_init(&new_point->parent); + + /* select new point */ + MASKPOINT_SEL_ALL(new_point); + ED_mask_select_flush_all(mask); +} + + +/* **** add extrude vertex **** */ + +static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, MaskSplinePoint **point, short check_active) +{ + MaskSpline *cur_spline = masklay->splines.first; + + *spline = NULL; + *point = NULL; + + if (check_active) { + if (masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { + *spline = masklay->act_spline; + *point = masklay->act_point; + return; + } + } + + while (cur_spline) { + int i; + + for (i = 0; i < cur_spline->tot_point; i++) { + MaskSplinePoint *cur_point = &cur_spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(cur_point)) { + if (*spline != NULL && *spline != cur_spline) { + *spline = NULL; + *point = NULL; + return; + } + else if (*point) { + *point = NULL; + } + else { + *spline = cur_spline; + *point = cur_point; + } + } + } + + cur_spline = cur_spline->next; + } +} + +/* **** add subdivide vertex **** */ + +static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index) +{ + MaskSplinePoint *new_point_array; + + new_point_array = MEM_callocN(sizeof(MaskSplinePoint) * (spline->tot_point + 1), "add mask vert points"); + + memcpy(new_point_array, spline->points, sizeof(MaskSplinePoint) * (point_index + 1)); + memcpy(new_point_array + point_index + 2, spline->points + point_index + 1, + sizeof(MaskSplinePoint) * (spline->tot_point - point_index - 1)); + + MEM_freeN(spline->points); + spline->points = new_point_array; + spline->tot_point++; +} + +static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) +{ + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + const float threshold = 9; + float tangent[2]; + float u; + + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent)) { + MaskSplinePoint *new_point; + int point_index = point - spline->points; + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + mask_spline_add_point_at_index(spline, point_index); + + new_point = &spline->points[point_index + 1]; + + setup_vertex_point(C, mask, spline, new_point, co, tangent, u, NULL, TRUE); + + /* TODO - we could pass the spline! */ + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, TRUE, TRUE); + + masklay->act_point = new_point; + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; + } + + return FALSE; +} + +static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) +{ + MaskSpline *spline; + MaskSplinePoint *point; + MaskSplinePoint *new_point = NULL, *ref_point = NULL; + + /* check on which side we want to add the point */ + int point_index; + float tangent_point[2]; + float tangent_co[2]; + int do_cyclic_correct = FALSE; + int do_recalc_src = FALSE; /* when extruding from endpoints only */ + int do_prev; /* use prev point rather then next?? */ + + if (!masklay) { + return FALSE; + } + else { + finSelectedSplinePoint(masklay, &spline, &point, TRUE); + } + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + point_index = (point - spline->points); + + MASKPOINT_DESEL_ALL(point); + + if ((spline->flag & MASK_SPLINE_CYCLIC) || + (point_index > 0 && point_index != spline->tot_point - 1)) + { + BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point); + sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]); + + if (dot_v2v2(tangent_point, tangent_co) < 0.0f) { + do_prev = TRUE; + } + else { + do_prev = FALSE; + } + } + else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) { + do_prev = TRUE; + do_recalc_src = TRUE; + } + else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) { + do_prev = FALSE; + do_recalc_src = TRUE; + } + else { + /* should never get here */ + BLI_assert(0); + } + + /* use the point before the active one */ + if (do_prev) { + point_index--; + if (point_index < 0) { + point_index += spline->tot_point; /* wrap index */ + if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) { + do_cyclic_correct = TRUE; + point_index = 0; + } + } + } + +// print_v2("", tangent_point); +// printf("%d\n", point_index); + + mask_spline_add_point_at_index(spline, point_index); + + if (do_cyclic_correct) { + ref_point = &spline->points[point_index + 1]; + new_point = &spline->points[point_index]; + *ref_point = *new_point; + memset(new_point, 0, sizeof(*new_point)); + } + else { + ref_point = &spline->points[point_index]; + new_point = &spline->points[point_index + 1]; + } + + masklay->act_point = new_point; + + setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); + + if (masklay->splines_shapes.first) { + point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); + } + + if (do_recalc_src) { + /* TODO, update keyframes in time */ + BKE_mask_calc_handle_point_auto(mask, spline, ref_point, FALSE); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; +} + +static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2]) +{ + MaskSpline *spline; + MaskSplinePoint *point; + MaskSplinePoint *new_point = NULL, *ref_point = NULL; + + if (!masklay) { + /* if there's no masklay currently operationg on, create new one */ + masklay = BKE_mask_layer_new(mask, ""); + mask->masklay_act = mask->masklay_tot - 1; + spline = NULL; + point = NULL; + } + else { + finSelectedSplinePoint(masklay, &spline, &point, TRUE); + } + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + if (!spline) { + /* no selected splines in active masklay, create new spline */ + spline = BKE_mask_spline_add(masklay); + } + + masklay->act_spline = spline; + new_point = spline->points; + + masklay->act_point = new_point; + + setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE); + + { + int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point); + BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return TRUE; +} + +static int add_vertex_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + float co[2]; + + masklay = BKE_mask_layer_active(mask); + + if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + masklay = NULL; + } + + RNA_float_get_array(op->ptr, "location", co); + + if (masklay && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { + + /* cheap trick - double click for cyclic */ + MaskSpline *spline = masklay->act_spline; + MaskSplinePoint *point = masklay->act_point; + + int is_sta = (point == spline->points); + int is_end = (point == &spline->points[spline->tot_point - 1]); + + /* then check are we overlapping the mouse */ + if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + /* nothing to do */ + return OPERATOR_CANCELLED; + } + else { + /* recalc the connecting point as well to make a nice even curve */ + MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1]; + spline->flag |= MASK_SPLINE_CYCLIC; + + /* TODO, update keyframes in time */ + BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE); + BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE); + + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + return OPERATOR_FINISHED; + } + } + + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_extrude(C, mask, masklay, co)) { + return OPERATOR_CANCELLED; + } + } + } + else { + if (!add_vertex_subdivide(C, mask, co)) { + if (!add_vertex_new(C, mask, masklay, co)) { + return OPERATOR_CANCELLED; + } + } + } + + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + return OPERATOR_FINISHED; +} + +static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return add_vertex_exec(C, op); +} + +void MASK_OT_add_vertex(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Vertex"; + ot->description = "Add vertex to active spline"; + ot->idname = "MASK_OT_add_vertex"; + + /* api callbacks */ + ot->exec = add_vertex_exec; + ot->invoke = add_vertex_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} + +/******************** add feather vertex *********************/ + +static int add_feather_vertex_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + const float threshold = 9; + float co[2], u; + + RNA_float_get_array(op->ptr, "location", co); + + point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL); + if (point) + return OPERATOR_FINISHED; + + if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) { + Scene *scene = CTX_data_scene(C); + float w = BKE_mask_point_weight(spline, point, u); + + BKE_mask_point_add_uw(point, u, w); + + BKE_mask_update_display(mask, scene->r.cfra); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return add_feather_vertex_exec(C, op); +} + +void MASK_OT_add_feather_vertex(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add feather Vertex"; + ot->description = "Add vertex to feather"; + ot->idname = "MASK_OT_add_feather_vertex"; + + /* api callbacks */ + ot->exec = add_feather_vertex_exec; + ot->invoke = add_feather_vertex_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c new file mode 100644 index 00000000000..e580088e25b --- /dev/null +++ b/source/blender/editors/mask/mask_draw.c @@ -0,0 +1,428 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_draw.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "ED_mask.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_resources.h" + +#include "mask_intern.h" /* own include */ + +static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const int is_sel, + unsigned char r_rgb[4]) +{ + if (is_sel) { + if (masklay->act_spline == spline) { + r_rgb[0] = r_rgb[1] = r_rgb[2] = 255; + } + else { + r_rgb[0] = 255; + r_rgb[1] = r_rgb[2] = 0; + } + } + else { + r_rgb[0] = 128; + r_rgb[1] = r_rgb[2] = 0; + } + + r_rgb[3] = 255; +} + +static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const int is_sel, + unsigned char r_rgb[4]) +{ + if (is_sel) { + r_rgb[1] = 255; + r_rgb[0] = r_rgb[2] = 0; + } + else { + r_rgb[1] = 128; + r_rgb[0] = r_rgb[2] = 0; + } + + r_rgb[3] = 255; +} + +#if 0 +static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline) +{ + int i; + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + if (!spline->tot_point) + return; + + glColor3ub(0, 0, 0); + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, 0xAAAA); + + glBegin(GL_LINES); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + BezTriple *bezt = &point->bezt; + + if (point->parent.flag & MASK_PARENT_ACTIVE) { + glVertex2f(bezt->vec[1][0], + bezt->vec[1][1]); + + glVertex2f(bezt->vec[1][0] - point->parent.offset[0], + bezt->vec[1][1] - point->parent.offset[1]); + } + } + + glEnd(); + + glDisable(GL_LINE_STIPPLE); +} +#endif + +/* return non-zero if spline is selected */ +static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline) +{ + const int is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; + unsigned char rgb_spline[4]; + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i, hsize, tot_feather_point; + float (*feather_points)[2], (*fp)[2]; + + if (!spline->tot_point) + return; + + hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); + + glPointSize(hsize); + + mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline); + + /* feather points */ + feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); + for (i = 0; i < spline->tot_point; i++) { + + /* watch it! this is intentionally not the deform array, only check for sel */ + MaskSplinePoint *point = &spline->points[i]; + + int j; + + for (j = 0; j < point->tot_uw + 1; j++) { + int sel = FALSE; + + if (j == 0) { + sel = MASKPOINT_ISSEL_ANY(point); + } + else { + sel = point->uw[j - 1].flag & SELECT; + } + + if (sel) { + if (point == masklay->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } + else { + glColor3f(0.5f, 0.5f, 0.0f); + } + + glBegin(GL_POINTS); + glVertex2fv(*fp); + glEnd(); + + fp++; + } + } + MEM_freeN(feather_points); + + /* control points */ + for (i = 0; i < spline->tot_point; i++) { + + /* watch it! this is intentionally not the deform array, only check for sel */ + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; + BezTriple *bezt = &point_deform->bezt; + + float handle[2]; + float *vert = bezt->vec[1]; + int has_handle = BKE_mask_point_has_handle(point); + + BKE_mask_point_handle(point_deform, handle); + + /* draw handle segment */ + if (has_handle) { + glColor3ubv(rgb_spline); + + glBegin(GL_LINES); + glVertex3fv(vert); + glVertex3fv(handle); + glEnd(); + } + + /* draw CV point */ + if (MASKPOINT_ISSEL_KNOT(point)) { + if (point == masklay->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } + else + glColor3f(0.5f, 0.5f, 0.0f); + + glBegin(GL_POINTS); + glVertex3fv(vert); + glEnd(); + + /* draw handle points */ + if (has_handle) { + if (MASKPOINT_ISSEL_HANDLE(point)) { + if (point == masklay->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } + else { + glColor3f(0.5f, 0.5f, 0.0f); + } + + glBegin(GL_POINTS); + glVertex3fv(handle); + glEnd(); + } + } + + glPointSize(1.0f); +} + +/* #define USE_XOR */ + +static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot_point, + const short is_feather, const short is_smooth, + const unsigned char rgb_spline[4], const char draw_type) +{ + const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP; + unsigned char rgb_tmp[4]; + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + + switch (draw_type) { + + case MASK_DT_OUTLINE: + glLineWidth(3); + cpack(0x0); + + glDrawArrays(draw_method, 0, tot_point); + + glLineWidth(1); + glColor4ubv(rgb_spline); + glDrawArrays(draw_method, 0, tot_point); + + break; + + case MASK_DT_DASH: + default: + glEnable(GL_LINE_STIPPLE); + +#ifdef USE_XOR + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_OR); +#endif + glColor4ubv(rgb_spline); + glLineStipple(3, 0xaaaa); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + glDrawArrays(draw_method, 0, tot_point); + +#ifdef USE_XOR + glDisable(GL_COLOR_LOGIC_OP); +#endif + glColor4ub(0, 0, 0, 255); + glLineStipple(3, 0x5555); + glDrawArrays(draw_method, 0, tot_point); + + glDisable(GL_LINE_STIPPLE); + break; + + + case MASK_DT_BLACK: + case MASK_DT_WHITE: + if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; } + else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; } + /* alpha values seem too low but gl draws many points that compensate for it */ + if (is_feather) { rgb_tmp[3] = 64; } + else { rgb_tmp[3] = 128; } + + if (is_feather) { + rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2); + rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2); + rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2); + } + + if (is_smooth == FALSE && is_feather) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + glColor4ubv(rgb_tmp); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, points); + glDrawArrays(draw_method, 0, tot_point); + + glDrawArrays(draw_method, 0, tot_point); + + if (is_smooth == FALSE && is_feather) { + glDisable(GL_BLEND); + } + + break; + } + + glDisableClientState(GL_VERTEX_ARRAY); + +} + +static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, + const char draw_flag, const char draw_type, + int width, int height) +{ + unsigned char rgb_tmp[4]; + + const short is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; + const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH); + + int tot_diff_point; + float (*diff_points)[2]; + + int tot_feather_point; + float (*feather_points)[2]; + + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point); + + if (!diff_points) + return; + + if (is_smooth) { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, &tot_feather_point); + + /* draw feather */ + mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp); + mask_draw_curve_type(spline, feather_points, tot_feather_point, + TRUE, is_smooth, + rgb_tmp, draw_type); + MEM_freeN(feather_points); + + /* draw main curve */ + mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp); + mask_draw_curve_type(spline, diff_points, tot_diff_point, + FALSE, is_smooth, + rgb_tmp, draw_type); + MEM_freeN(diff_points); + + if (draw_flag & MASK_DRAWFLAG_SMOOTH) { + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + } + + (void)draw_type; +} + +static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type, + int width, int height) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + + /* draw curve itself first... */ + draw_spline_curve(masklay, spline, draw_flag, draw_type, width, height); + +// draw_spline_parents(masklay, spline); + + if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) { + /* ...and then handles over the curve so they're nicely visible */ + draw_spline_points(masklay, spline); + } + + /* show undeform for testing */ + if (0) { + void *back = spline->points_deform; + + spline->points_deform = NULL; + draw_spline_curve(masklay, spline, draw_flag, draw_type, width, height); +// draw_spline_parents(masklay, spline); + draw_spline_points(masklay, spline); + spline->points_deform = back; + } + } + } +} + +void ED_mask_draw(const bContext *C, + const char draw_flag, const char draw_type) +{ + Mask *mask = CTX_data_edit_mask(C); + int width, height; + + if (!mask) + return; + + /* TODO: for now, in the future better to make sure all utility functions + * are using const specifier for non-changing pointers + */ + ED_mask_size((bContext *)C, &width, &height); + + draw_masklays(mask, draw_flag, draw_type, width, height); +} diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c new file mode 100644 index 00000000000..0b8551ddd4c --- /dev/null +++ b/source/blender/editors/mask/mask_edit.c @@ -0,0 +1,327 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_ops.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_mask.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_object.h" /* ED_keymap_proportional_maskmode only */ +#include "ED_clip.h" +#include "ED_transform.h" + +#include "RNA_access.h" + +#include "mask_intern.h" /* own include */ + +/********************** generic poll functions *********************/ + +int ED_maskediting_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + return ED_space_clip_maskediting_poll(C); + } + + return FALSE; +} + +int ED_maskediting_mask_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + return ED_space_clip_maskediting_mask_poll(C); + } + + return FALSE; +} + +/********************** registration *********************/ + +void ED_mask_mouse_pos(bContext *C, wmEvent *event, float co[2]) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ED_clip_mouse_pos(C, event, co); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); + } + else { + /* possible other spaces from which mask editing is available */ + zero_v2(co); + } +} + +/* input: x/y - mval space + * output: xr/yr - mask point space */ +void ED_mask_point_pos(bContext *C, float x, float y, float *xr, float *yr) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + float co[2]; + + if (sc) { + ED_clip_point_stable_pos(C, x, y, &co[0], &co[1]); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); + } + else { + /* possible other spaces from which mask editing is available */ + zero_v2(co); + } + + *xr = co[0]; + *yr = co[1]; +} + +void ED_mask_point_pos__reverse(bContext *C, float x, float y, float *xr, float *yr) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + ARegion *ar = CTX_wm_region(C); + + float co[2]; + + if (sc && ar) { + co[0] = x; + co[1] = y; + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co); + ED_clip_point_stable_pos__reverse(sc, ar, co, co); + } + else { + /* possible other spaces from which mask editing is available */ + zero_v2(co); + } + + *xr = co[0]; + *yr = co[1]; +} + +void ED_mask_size(bContext *C, int *width, int *height) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ED_space_clip_mask_size(sc, width, height); + } + else { + /* possible other spaces from which mask editing is available */ + *width = 0; + *height = 0; + } +} + +void ED_mask_aspect(bContext *C, float *aspx, float *aspy) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ED_space_clip_mask_aspect(sc, aspx, aspy); + } + else { + /* possible other spaces from which mask editing is available */ + *aspx = 1.0f; + *aspy = 1.0f; + } +} + +void ED_mask_pixelspace_factor(bContext *C, float *scalex, float *scaley) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + ARegion *ar = CTX_wm_region(C); + int width, height; + float zoomx, zoomy, aspx, aspy; + + ED_space_clip_size(sc, &width, &height); + ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + ED_space_clip_aspect(sc, &aspx, &aspy); + + *scalex = ((float)width * aspx) * zoomx; + *scaley = ((float)height * aspy) * zoomy; + } + else { + /* possible other spaces from which mask editing is available */ + *scalex = 1.0f; + *scaley = 1.0f; + } +} + +/********************** registration *********************/ + +void ED_operatortypes_mask(void) +{ + WM_operatortype_append(MASK_OT_new); + + /* mask layers */ + WM_operatortype_append(MASK_OT_layer_new); + WM_operatortype_append(MASK_OT_layer_remove); + + /* add */ + WM_operatortype_append(MASK_OT_add_vertex); + WM_operatortype_append(MASK_OT_add_feather_vertex); + + /* geometry */ + WM_operatortype_append(MASK_OT_switch_direction); + WM_operatortype_append(MASK_OT_delete); + + /* select */ + WM_operatortype_append(MASK_OT_select); + WM_operatortype_append(MASK_OT_select_all); + WM_operatortype_append(MASK_OT_select_border); + WM_operatortype_append(MASK_OT_select_lasso); + WM_operatortype_append(MASK_OT_select_circle); + WM_operatortype_append(MASK_OT_select_linked_pick); + WM_operatortype_append(MASK_OT_select_linked); + + /* hide/reveal */ + WM_operatortype_append(MASK_OT_hide_view_clear); + WM_operatortype_append(MASK_OT_hide_view_set); + + /* shape */ + WM_operatortype_append(MASK_OT_slide_point); + WM_operatortype_append(MASK_OT_cyclic_toggle); + WM_operatortype_append(MASK_OT_handle_type_set); + + /* relationships */ + WM_operatortype_append(MASK_OT_parent_set); + WM_operatortype_append(MASK_OT_parent_clear); + + /* shapekeys */ + WM_operatortype_append(MASK_OT_shape_key_insert); + WM_operatortype_append(MASK_OT_shape_key_clear); +} + +void ED_keymap_mask(wmKeyConfig *keyconf) +{ + wmKeyMap *keymap; + wmKeyMapItem *kmi; + + keymap = WM_keymap_find(keyconf, "Mask Editor", 0, 0); + keymap->poll = ED_maskediting_poll; + + WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0); + + /* mask mode supports PET now */ + ED_keymap_proportional_cycle(keyconf, keymap); + ED_keymap_proportional_maskmode(keyconf, keymap); + + /* geometry */ + WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "MASK_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_delete", DELKEY, KM_PRESS, 0, 0); + + /* selection */ + kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); + + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", AKEY, KM_PRESS, 0, 0); + RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + + WM_keymap_add_item(keymap, "MASK_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "deselect", TRUE); + + WM_keymap_add_item(keymap, "MASK_OT_select_border", BKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_select_circle", CKEY, KM_PRESS, 0, 0); + + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT | KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "deselect", TRUE); + + /* hide/reveal */ + WM_keymap_add_item(keymap, "MASK_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "unselected", FALSE); + + kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "unselected", TRUE); + + /* select clip while in maker view, + * this matches View3D functionality where you can select an + * object while in editmode to allow vertex parenting */ + kmi = WM_keymap_add_item(keymap, "CLIP_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + + /* shape */ + WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); + + /* relationships */ + WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0); + + WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0); + + + transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); +} + +void ED_operatormacros_mask(void) +{ + /* XXX: just for sample */ + wmOperatorType *ot; + wmOperatorTypeMacro *otmacro; + + ot = WM_operatortype_append_macro("MASK_OT_add_vertex_slide", "Add Vertex and Slide", "Add new vertex and slide it", OPTYPE_UNDO | OPTYPE_REGISTER); + ot->description = "Add new vertex and slide it"; + WM_operatortype_macro_define(ot, "MASK_OT_add_vertex"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "release_confirm", TRUE); + + ot = WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide", "Add new vertex to feater and slide it", OPTYPE_UNDO | OPTYPE_REGISTER); + ot->description = "Add new feather vertex and slide it"; + WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex"); + otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point"); + RNA_boolean_set(otmacro->ptr, "slide_feather", TRUE); +} diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h new file mode 100644 index 00000000000..70f13abd44f --- /dev/null +++ b/source/blender/editors/mask/mask_intern.h @@ -0,0 +1,111 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_intern.h + * \ingroup spclip + */ + +#ifndef __MASK_INTERN_H__ +#define __MASK_INTERN_H__ + +struct bContext; +struct wmEvent; +struct wmOperatorType; + +/* internal exports only */ + +/* mask_add.c */ +void MASK_OT_add_vertex(struct wmOperatorType *ot); +void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); + +/* mask_ops.c */ +void MASK_OT_new(struct wmOperatorType *ot); +void MASK_OT_layer_new(struct wmOperatorType *ot); +void MASK_OT_layer_remove(struct wmOperatorType *ot); +void MASK_OT_cyclic_toggle(struct wmOperatorType *ot); + +void MASK_OT_slide_point(struct wmOperatorType *ot); + +void MASK_OT_delete(struct wmOperatorType *ot); + +void MASK_OT_hide_view_clear(struct wmOperatorType *ot); +void MASK_OT_hide_view_set(struct wmOperatorType *ot); +void MASK_OT_switch_direction(struct wmOperatorType *ot); + +void MASK_OT_handle_type_set(struct wmOperatorType *ot); + +int ED_mask_feather_find_nearest( + struct bContext *C, struct Mask *mask, float normal_co[2], int threshold, + struct MaskLayer **masklay_r, struct MaskSpline **spline_r, struct MaskSplinePoint **point_r, + struct MaskSplinePointUW **uw_r, float *score); + +struct MaskSplinePoint *ED_mask_point_find_nearest( + struct bContext *C, struct Mask *mask, float normal_co[2], int threshold, + struct MaskLayer **masklay_r, struct MaskSpline **spline_r, int *is_handle_r, + float *score); + +/* mask_relationships.c */ +void MASK_OT_parent_set(struct wmOperatorType *ot); +void MASK_OT_parent_clear(struct wmOperatorType *ot); + +/* mask_select.c */ +void MASK_OT_select(struct wmOperatorType *ot); +void MASK_OT_select_all(struct wmOperatorType *ot); + +void MASK_OT_select_border(struct wmOperatorType *ot); +void MASK_OT_select_lasso(struct wmOperatorType *ot); +void MASK_OT_select_circle(struct wmOperatorType *ot); +void MASK_OT_select_linked_pick(struct wmOperatorType *ot); +void MASK_OT_select_linked(struct wmOperatorType *ot); + +int ED_mask_spline_select_check(struct MaskSpline *spline); +int ED_mask_layer_select_check(struct MaskLayer *masklay); +int ED_mask_select_check(struct Mask *mask); + +void ED_mask_spline_select_set(struct MaskSpline *spline, const short do_select); +void ED_mask_layer_select_set(struct MaskLayer *masklay, const short do_select); +void ED_mask_select_toggle_all(struct Mask *mask, int action); +void ED_mask_select_flush_all(struct Mask *mask); + +/* mask_editor.c */ +int ED_maskediting_poll(struct bContext *C); +int ED_maskediting_mask_poll(struct bContext *C); + +void ED_mask_size(struct bContext *C, int *width, int *height); +void ED_mask_aspect(struct bContext *C, float *aspx, float *aspy); + +void ED_mask_pixelspace_factor(struct bContext *C, float *scalex, float *scaley); +void ED_mask_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]); + +void ED_mask_point_pos(struct bContext *C, float x, float y, float *xr, float *yr); +void ED_mask_point_pos__reverse(struct bContext *C, float x, float y, float *xr, float *yr); + +/* mask_shapekey.c */ +void MASK_OT_shape_key_insert(struct wmOperatorType *ot); +void MASK_OT_shape_key_clear(struct wmOperatorType *ot); + +#endif /* __MASK_INTERN_H__ */ diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c new file mode 100644 index 00000000000..cf3a72bdc78 --- /dev/null +++ b/source/blender/editors/mask/mask_ops.c @@ -0,0 +1,1171 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_ops.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_scene_types.h" +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" +#include "ED_keyframing.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +/******************** utility functions *********************/ + +MaskSplinePoint *ED_mask_point_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, + MaskLayer **masklay_r, MaskSpline **spline_r, int *is_handle_r, + float *score) +{ + MaskLayer *masklay; + MaskLayer *point_masklay = NULL; + MaskSpline *point_spline = NULL; + MaskSplinePoint *point = NULL; + float co[2], aspx, aspy; + float len = FLT_MAX, scalex, scaley; + int is_handle = FALSE, width, height; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + MaskSplinePoint *cur_point_deform = &points_array[i]; + float cur_len, vec[2], handle[2]; + + vec[0] = cur_point_deform->bezt.vec[1][0] * scalex; + vec[1] = cur_point_deform->bezt.vec[1][1] * scaley; + + if (BKE_mask_point_has_handle(cur_point)) { + BKE_mask_point_handle(cur_point_deform, handle); + handle[0] *= scalex; + handle[1] *= scaley; + + cur_len = len_v2v2(co, handle); + + if (cur_len < len) { + point_masklay = masklay; + point_spline = spline; + point = cur_point; + len = cur_len; + is_handle = TRUE; + } + } + + cur_len = len_v2v2(co, vec); + + if (cur_len < len) { + point_spline = spline; + point_masklay = masklay; + point = cur_point; + len = cur_len; + is_handle = FALSE; + } + } + } + } + + if (len < threshold) { + if (masklay_r) + *masklay_r = point_masklay; + + if (spline_r) + *spline_r = point_spline; + + if (is_handle_r) + *is_handle_r = is_handle; + + if (score) + *score = len; + + return point; + } + + if (masklay_r) + *masklay_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (is_handle_r) + *is_handle_r = FALSE; + + return NULL; +} + +int ED_mask_feather_find_nearest(bContext *C, Mask *mask, float normal_co[2], int threshold, + MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, + MaskSplinePointUW **uw_r, float *score) +{ + MaskLayer *masklay, *point_masklay = NULL; + MaskSpline *point_spline = NULL; + MaskSplinePoint *point = NULL; + MaskSplinePointUW *uw = NULL; + float len = FLT_MAX, co[2]; + float scalex, scaley, aspx, aspy; + int width, height; + + ED_mask_size(C, &width, &height); + ED_mask_aspect(C, &aspx, &aspy); + ED_mask_pixelspace_factor(C, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i, tot_feather_point; + float (*feather_points)[2], (*fp)[2]; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); + + for (i = 0; i < spline->tot_point; i++) { + int j; + MaskSplinePoint *cur_point = &spline->points[i]; + + for (j = 0; j < cur_point->tot_uw + 1; j++) { + float cur_len, vec[2]; + + vec[0] = (*fp)[0] * scalex; + vec[1] = (*fp)[1] * scaley; + + cur_len = len_v2v2(vec, co); + + if (point == NULL || cur_len < len) { + if (j == 0) + uw = NULL; + else + uw = &cur_point->uw[j - 1]; + + point_masklay = masklay; + point_spline = spline; + point = cur_point; + len = cur_len; + } + + fp++; + } + } + + MEM_freeN(feather_points); + } + } + + if (len < threshold) { + if (masklay_r) + *masklay_r = point_masklay; + + if (spline_r) + *spline_r = point_spline; + + if (point_r) + *point_r = point; + + if (uw_r) + *uw_r = uw; + + if (score) + *score = len; + + return TRUE; + } + + if (masklay_r) + *masklay_r = NULL; + + if (spline_r) + *spline_r = NULL; + + if (point_r) + *point_r = NULL; + + return FALSE; +} + + +/******************** create new mask *********************/ + +static int mask_new_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + Mask *mask; + char name[MAX_ID_NAME - 2]; + + RNA_string_get(op->ptr, "name", name); + + mask = BKE_mask_new(name); + + if (sc) + ED_space_clip_set_mask(C, sc, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "New Mask"; + ot->description = "Create new mask"; + ot->idname = "MASK_OT_new"; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = mask_new_exec; + ot->poll = ED_operator_mask; + + /* properties */ + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask"); +} + +/******************** create new masklay *********************/ + +static int masklay_new_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + char name[MAX_ID_NAME - 2]; + + RNA_string_get(op->ptr, "name", name); + + BKE_mask_layer_new(mask, name); + mask->masklay_act = mask->masklay_tot - 1; + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_layer_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Mask Layer"; + ot->description = "Add new mask layer for masking"; + ot->idname = "MASK_OT_layer_new"; + + /* api callbacks */ + ot->exec = masklay_new_exec; + ot->poll = ED_maskediting_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_string(ot->srna, "name", "", MAX_ID_NAME - 2, "Name", "Name of new mask layer"); +} + +/******************** remove mask layer *********************/ + +static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay = BKE_mask_layer_active(mask); + + if (masklay) { + BKE_mask_layer_remove(mask, masklay); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + } + + return OPERATOR_FINISHED; +} + +void MASK_OT_layer_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Mask Layer"; + ot->description = "Remove mask layer"; + ot->idname = "MASK_OT_layer_remove"; + + /* api callbacks */ + ot->exec = masklay_remove_exec; + ot->poll = ED_maskediting_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/******************** slide *********************/ + +#define SLIDE_ACTION_NONE 0 +#define SLIDE_ACTION_POINT 1 +#define SLIDE_ACTION_HANDLE 2 +#define SLIDE_ACTION_FEATHER 3 + +typedef struct SlidePointData { + int action; + + float co[2]; + float vec[3][3]; + + Mask *mask; + MaskLayer *masklay; + MaskSpline *spline, *orig_spline; + MaskSplinePoint *point; + MaskSplinePointUW *uw; + float handle[2], no[2], feather[2]; + int width, height; + float weight; + + short curvature_only, accurate; + short initial_feather, overall_feather; +} SlidePointData; + +static int slide_point_check_initial_feather(MaskSpline *spline) +{ + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + int j; + + if (point->bezt.weight != 0.0f) + return FALSE; + + for (j = 0; j < point->tot_uw; j++) { + if (point->uw[j].w != 0.0f) + return FALSE; + } + } + + return TRUE; +} + +static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) +{ + Mask *mask = CTX_data_edit_mask(C); + SlidePointData *customdata = NULL; + MaskLayer *masklay, *cv_masklay, *feather_masklay; + MaskSpline *spline, *cv_spline, *feather_spline; + MaskSplinePoint *point, *cv_point, *feather_point; + MaskSplinePointUW *uw = NULL; + int is_handle = FALSE, width, height, action = SLIDE_ACTION_NONE; + int slide_feather = RNA_boolean_get(op->ptr, "slide_feather"); + float co[2], cv_score, feather_score; + const float threshold = 19; + + ED_mask_mouse_pos(C, event, co); + ED_mask_size(C, &width, &height); + + cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score); + + if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) { + if (slide_feather || !cv_point || feather_score < cv_score) { + action = SLIDE_ACTION_FEATHER; + + masklay = feather_masklay; + spline = feather_spline; + point = feather_point; + } + } + + if (cv_point && action == SLIDE_ACTION_NONE) { + if (is_handle) + action = SLIDE_ACTION_HANDLE; + else + action = SLIDE_ACTION_POINT; + + masklay = cv_masklay; + spline = cv_spline; + point = cv_point; + } + + if (action != SLIDE_ACTION_NONE) { + customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data"); + + customdata->mask = mask; + customdata->masklay = masklay; + customdata->spline = spline; + customdata->point = point; + customdata->width = width; + customdata->height = height; + customdata->action = action; + customdata->uw = uw; + + if (uw) { + float co[2]; + + customdata->weight = point->bezt.weight; + + customdata->weight = uw->w; + BKE_mask_point_segment_co(spline, point, uw->u, co); + BKE_mask_point_normal(spline, point, uw->u, customdata->no); + + customdata->feather[0] = co[0] + customdata->no[0] * uw->w; + customdata->feather[1] = co[1] + customdata->no[1] * uw->w; + } + else { + BezTriple *bezt = &point->bezt; + + BKE_mask_point_normal(spline, point, 0.0f, customdata->no); + + customdata->feather[0] = bezt->vec[1][0] + customdata->no[0] * bezt->weight; + customdata->feather[1] = bezt->vec[1][1] + customdata->no[1] * bezt->weight; + + customdata->weight = bezt->weight; + } + + if (customdata->action == SLIDE_ACTION_FEATHER) + customdata->initial_feather = slide_point_check_initial_feather(spline); + + copy_m3_m3(customdata->vec, point->bezt.vec); + if (BKE_mask_point_has_handle(point)) + BKE_mask_point_handle(point, customdata->handle); + ED_mask_mouse_pos(C, event, customdata->co); + } + + return customdata; +} + +static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + SlidePointData *slidedata = slide_point_customdata(C, op, event); + + if (slidedata) { + Mask *mask = CTX_data_edit_mask(C); + + op->customdata = slidedata; + + WM_event_add_modal_handler(C, op); + + if (slidedata->uw) { + if ((slidedata->uw->flag & SELECT) == 0) { + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + slidedata->uw->flag |= SELECT; + + ED_mask_select_flush_all(mask); + } + } + else if (!MASKPOINT_ISSEL_ANY(slidedata->point)) { + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + BKE_mask_point_select_set(slidedata->point, TRUE); + + ED_mask_select_flush_all(mask); + } + + slidedata->masklay->act_spline = slidedata->spline; + slidedata->masklay->act_point = slidedata->point; + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_RUNNING_MODAL; + } + + return OPERATOR_PASS_THROUGH; +} + +static void slide_point_delta_all_feather(SlidePointData *data, float delta) +{ + int i; + + for (i = 0; i < data->spline->tot_point; i++) { + MaskSplinePoint *point = &data->spline->points[i]; + MaskSplinePoint *orig_point = &data->orig_spline->points[i]; + int j; + + point->bezt.weight = orig_point->bezt.weight + delta; + if (point->bezt.weight < 0.0f) + point->bezt.weight = 0.0f; + + for (j = 0; j < point->tot_uw; j++) { + point->uw[j].w = orig_point->uw[j].w + delta; + if (point->uw[j].w < 0.0f) + point->uw[j].w = 0.0f; + } + } +} + +static void slide_point_restore_spline(SlidePointData *data) +{ + int i; + + for (i = 0; i < data->spline->tot_point; i++) { + MaskSplinePoint *point = &data->spline->points[i]; + MaskSplinePoint *orig_point = &data->orig_spline->points[i]; + int j; + + point->bezt = orig_point->bezt; + + for (j = 0; j < point->tot_uw; j++) + point->uw[j] = orig_point->uw[j]; + } +} + +static void cancel_slide_point(SlidePointData *data) +{ + /* cancel sliding */ + + if (data->orig_spline) { + slide_point_restore_spline(data); + } + else { + if (data->action == SLIDE_ACTION_FEATHER) { + if (data->uw) + data->uw->w = data->weight; + else + data->point->bezt.weight = data->weight; + } + else { + copy_m3_m3(data->point->bezt.vec, data->vec); + } + } +} + +static void free_slide_point_data(SlidePointData *data) +{ + if (data->orig_spline) + BKE_mask_spline_free(data->orig_spline); + + MEM_freeN(data); +} + +static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + SlidePointData *data = (SlidePointData *)op->customdata; + BezTriple *bezt = &data->point->bezt; + float co[2], dco[2]; + + switch (event->type) { + case LEFTCTRLKEY: + case RIGHTCTRLKEY: + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) { + if (data->action == SLIDE_ACTION_FEATHER) + data->overall_feather = event->val == KM_PRESS; + else + data->curvature_only = event->val == KM_PRESS; + } + + if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) + data->accurate = event->val == KM_PRESS; + + /* no break! update CV position */ + + case MOUSEMOVE: + ED_mask_mouse_pos(C, event, co); + sub_v2_v2v2(dco, co, data->co); + + if (data->action == SLIDE_ACTION_HANDLE) { + float delta[2], offco[2]; + + sub_v2_v2v2(delta, data->handle, data->co); + + sub_v2_v2v2(offco, co, data->co); + if (data->accurate) + mul_v2_fl(offco, 0.2f); + add_v2_v2(offco, data->co); + add_v2_v2(offco, delta); + + BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec); + } + else if (data->action == SLIDE_ACTION_POINT) { + float delta[2]; + + copy_v2_v2(delta, dco); + if (data->accurate) + mul_v2_fl(delta, 0.2f); + + add_v2_v2v2(bezt->vec[0], data->vec[0], delta); + add_v2_v2v2(bezt->vec[1], data->vec[1], delta); + add_v2_v2v2(bezt->vec[2], data->vec[2], delta); + } + else if (data->action == SLIDE_ACTION_FEATHER) { + float vec[2], no[2], p[2], c[2], w, offco[2]; + float *weight = NULL; + int overall_feather = data->overall_feather || data->initial_feather; + + add_v2_v2v2(offco, data->feather, dco); + + if (data->uw) { + float u = BKE_mask_spline_project_co(data->spline, data->point, data->uw->u, offco); + + if (u > 0.0f && u < 1.0f) { + data->uw->u = u; + + data->uw = BKE_mask_point_sort_uw(data->point, data->uw); + weight = &data->uw->w; + BKE_mask_point_normal(data->spline, data->point, data->uw->u, no); + BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); + } + } + else { + weight = &bezt->weight; + copy_v2_v2(no, data->no); + copy_v2_v2(p, bezt->vec[1]); + } + + if (weight) { + sub_v2_v2v2(c, offco, p); + project_v2_v2v2(vec, c, no); + + w = len_v2(vec); + + if (overall_feather) { + float delta; + + if (dot_v2v2(no, vec) <= 0.0f) + w = -w; + + delta = w - data->weight; + + if (data->orig_spline == NULL) { + /* restore weight for currently sliding point, so orig_spline would be created + * with original weights used + */ + *weight = data->weight; + + data->orig_spline = BKE_mask_spline_copy(data->spline); + } + + slide_point_delta_all_feather(data, delta); + } + else { + if (dot_v2v2(no, vec) <= 0.0f) + w = 0.0f; + + if (data->orig_spline) { + /* restore possible overall feather changes */ + slide_point_restore_spline(data); + + BKE_mask_spline_free(data->orig_spline); + data->orig_spline = NULL; + } + + *weight = w; + } + } + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); + DAG_id_tag_update(&data->mask->id, 0); + + break; + + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + Scene *scene = CTX_data_scene(C); + + free_slide_point_data(op->customdata); + + if (IS_AUTOKEY_ON(scene)) { + ED_mask_layer_shape_auto_key_all(data->mask, CFRA); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); + DAG_id_tag_update(&data->mask->id, 0); + + return OPERATOR_FINISHED; + } + + break; + + case ESCKEY: + cancel_slide_point(op->customdata); + + free_slide_point_data(op->customdata); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); + DAG_id_tag_update(&data->mask->id, 0); + + return OPERATOR_CANCELLED; + } + + return OPERATOR_RUNNING_MODAL; +} + +void MASK_OT_slide_point(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Slide Point"; + ot->description = "Slide control points"; + ot->idname = "MASK_OT_slide_point"; + + /* api callbacks */ + ot->invoke = slide_point_invoke; + ot->modal = slide_point_modal; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide slide feather instead of vertex"); +} + +/******************** toggle cyclic *********************/ + +static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline)) { + spline->flag ^= MASK_SPLINE_CYCLIC; + } + } + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_cyclic_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Cyclic"; + ot->description = "Toggle cyclic for selected splines"; + ot->idname = "MASK_OT_cyclic_toggle"; + + /* api callbacks */ + ot->exec = cyclic_toggle_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/******************** delete *********************/ + +static void delete_feather_points(MaskSplinePoint *point) +{ + int i, count = 0; + + if (!point->tot_uw) + return; + + for (i = 0; i < point->tot_uw; i++) { + if ((point->uw[i].flag & SELECT) == 0) + count++; + } + + if (count == 0) { + MEM_freeN(point->uw); + point->uw = NULL; + point->tot_uw = 0; + } + else { + MaskSplinePointUW *new_uw; + int j = 0; + + new_uw = MEM_callocN(count * sizeof(MaskSplinePointUW), "new mask uw points"); + + for (i = 0; i < point->tot_uw; i++) { + if ((point->uw[i].flag & SELECT) == 0) { + new_uw[j++] = point->uw[i]; + } + } + + MEM_freeN(point->uw); + + point->uw = new_uw; + point->tot_uw = count; + } +} + +static int delete_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int mask_layer_shape_ofs = 0; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + spline = masklay->splines.first; + + while (spline) { + const int tot_point_orig = spline->tot_point; + int i, count = 0; + MaskSpline *next_spline = spline->next; + + /* count unselected points */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (!MASKPOINT_ISSEL_ANY(point)) + count++; + } + + if (count == 0) { + + /* delete the whole spline */ + BLI_remlink(&masklay->splines, spline); + BKE_mask_spline_free(spline); + + if (spline == masklay->act_spline) { + masklay->act_spline = NULL; + masklay->act_point = NULL; + } + + BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig); + } + else { + MaskSplinePoint *new_points; + int j; + + new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints"); + + for (i = 0, j = 0; i < tot_point_orig; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (!MASKPOINT_ISSEL_ANY(point)) { + if (point == masklay->act_point) + masklay->act_point = &new_points[j]; + + delete_feather_points(point); + + new_points[j] = *point; + j++; + } + else { + if (point == masklay->act_point) + masklay->act_point = NULL; + + BKE_mask_point_free(point); + spline->tot_point--; + + BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1); + } + } + + mask_layer_shape_ofs += spline->tot_point; + + MEM_freeN(spline->points); + spline->points = new_points; + + ED_mask_select_flush_all(mask); + } + + spline = next_spline; + } + } + + /* TODO: only update edited splines */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->description = "Delete selected control points or splines"; + ot->idname = "MASK_OT_delete"; + + /* api callbacks */ + ot->invoke = WM_operator_confirm; + ot->exec = delete_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* *** switch direction *** */ +static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + int change = FALSE; + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline)) { + BKE_mask_spline_direction_switch(masklay, spline); + change = TRUE; + } + } + } + + if (change) { + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_switch_direction(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Switch Direction"; + ot->description = "Switch direction of selected splines"; + ot->idname = "MASK_OT_switch_direction"; + + /* api callbacks */ + ot->exec = mask_switch_direction_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + +/******************** set handle type *********************/ + +static int set_handle_type_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int handle_type = RNA_enum_get(op->ptr, "type"); + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + int i; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + BezTriple *bezt = &point->bezt; + + bezt->h1 = bezt->h2 = handle_type; + } + } + } + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +void MASK_OT_handle_type_set(wmOperatorType *ot) +{ + static EnumPropertyItem editcurve_handle_type_items[] = { + {HD_AUTO, "AUTO", 0, "Auto", ""}, + {HD_VECT, "VECTOR", 0, "Vector", ""}, + {HD_ALIGN, "ALIGNED", 0, "Aligned", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Set Handle Type"; + ot->description = "Set type of handles for selected control points"; + ot->idname = "MASK_OT_handle_type_set"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = set_handle_type_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); +} + + +/* ********* clear/set restrict view *********/ +static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int changed = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + + if (masklay->restrictflag & OB_RESTRICT_VIEW) { + ED_mask_layer_select_set(masklay, TRUE); + masklay->restrictflag &= ~OB_RESTRICT_VIEW; + changed = 1; + } + } + + if (changed) { + WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_hide_view_clear(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name = "Clear Restrict View"; + ot->description = "Reveal the layer by setting the hide flag"; + ot->idname = "MASK_OT_hide_view_clear"; + + /* api callbacks */ + ot->exec = mask_hide_view_clear_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_hide_view_set_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + const int unselected = RNA_boolean_get(op->ptr, "unselected"); + int changed = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + + if (masklay->restrictflag & MASK_RESTRICT_SELECT) { + continue; + } + + if (!unselected) { + if (ED_mask_layer_select_check(masklay)) { + ED_mask_layer_select_set(masklay, FALSE); + + masklay->restrictflag |= OB_RESTRICT_VIEW; + changed = 1; + if (masklay == BKE_mask_layer_active(mask)) { + BKE_mask_layer_active_set(mask, NULL); + } + } + } + else { + if (!ED_mask_layer_select_check(masklay)) { + masklay->restrictflag |= OB_RESTRICT_VIEW; + changed = 1; + if (masklay == BKE_mask_layer_active(mask)) { + BKE_mask_layer_active_set(mask, NULL); + } + } + } + } + + if (changed) { + WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_hide_view_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Restrict View"; + ot->description = "Hide the layer by setting the hide flag"; + ot->idname = "MASK_OT_hide_view_set"; + + /* api callbacks */ + ot->exec = mask_hide_view_set_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers"); + +} diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c new file mode 100644 index 00000000000..8a8427c024b --- /dev/null +++ b/source/blender/editors/mask/mask_relationships.c @@ -0,0 +1,183 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_relationshops.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" +#include "BKE_tracking.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + int i; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + point->parent.flag &= ~MASK_PARENT_ACTIVE; + } + } + } + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +void MASK_OT_parent_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Parent"; + ot->description = "Clear the masks parenting"; + ot->idname = "MASK_OT_parent_clear"; + + /* api callbacks */ + ot->exec = mask_parent_clear_exec; + + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + /* parent info */ + SpaceClip *sc; + MovieClip *clip; + MovieTrackingTrack *track; + MovieTrackingMarker *marker; + MovieTrackingObject *tracking; + /* done */ + + float marker_pos_ofs[2]; + float parmask_pos[2]; + + if ((NULL == (sc = CTX_wm_space_clip(C))) || + (NULL == (clip = sc->clip)) || + (NULL == (track = clip->tracking.act_track)) || + (NULL == (marker = BKE_tracking_get_marker(track, sc->user.framenr))) || + (NULL == (tracking = BKE_tracking_active_object(&clip->tracking)))) + { + return OPERATOR_CANCELLED; + } + + add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); + + BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs); + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + int i; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + point->parent.id_type = ID_MC; + point->parent.id = &clip->id; + strcpy(point->parent.parent, tracking->name); + strcpy(point->parent.sub_parent, track->name); + + point->parent.flag |= MASK_PARENT_ACTIVE; + + copy_v2_v2(point->parent.parent_orig, parmask_pos); + } + } + } + } + + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; +} + +/** based on #OBJECT_OT_parent_set */ +void MASK_OT_parent_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Make Parent"; + ot->description = "Set the masks parenting"; + ot->idname = "MASK_OT_parent_set"; + + /* api callbacks */ + //ot->invoke = mask_parent_set_invoke; + ot->exec = mask_parent_set_exec; + + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c new file mode 100644 index 00000000000..18d745dcf7b --- /dev/null +++ b/source/blender/editors/mask/mask_select.c @@ -0,0 +1,770 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_select.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_rect.h" +#include "BLI_lasso.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +/* 'check' select */ +int ED_mask_spline_select_check(MaskSpline *spline) +{ + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) + return TRUE; + } + + return FALSE; +} + +int ED_mask_layer_select_check(MaskLayer *masklay) +{ + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + return FALSE; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline)) { + return TRUE; + } + } + + return FALSE; +} + +int ED_mask_select_check(Mask *mask) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + if (ED_mask_layer_select_check(masklay)) { + return TRUE; + } + } + + return FALSE; +} + +/* 'sel' select */ +void ED_mask_spline_select_set(MaskSpline *spline, const short do_select) +{ + int i; + + if (do_select) + spline->flag |= SELECT; + else + spline->flag &= ~SELECT; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + BKE_mask_point_select_set(point, do_select); + } +} + +void ED_mask_layer_select_set(MaskLayer *masklay, const short do_select) +{ + MaskSpline *spline; + + if (masklay->restrictflag & MASK_RESTRICT_SELECT) { + if (do_select == TRUE) { + return; + } + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + ED_mask_spline_select_set(spline, do_select); + } +} + +void ED_mask_select_toggle_all(Mask *mask, int action) +{ + MaskLayer *masklay; + + if (action == SEL_TOGGLE) { + if (ED_mask_select_check(mask)) + action = SEL_DESELECT; + else + action = SEL_SELECT; + } + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + + if (masklay->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + + ED_mask_layer_select_set(masklay, (action == SEL_SELECT) ? TRUE : FALSE); + } +} + +void ED_mask_select_flush_all(Mask *mask) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + spline->flag &= ~SELECT; + + /* intentionally _dont_ do this in the masklay loop + * so we clear flags on all splines */ + if (masklay->restrictflag & MASK_RESTRICT_VIEW) { + continue; + } + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *cur_point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(cur_point)) { + spline->flag |= SELECT; + } + else { + int j; + + for (j = 0; j < cur_point->tot_uw; j++) { + if (cur_point->uw[j].flag & SELECT) { + spline->flag |= SELECT; + break; + } + } + } + } + } + } +} + +/******************** toggle selection *********************/ + +static int select_all_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + int action = RNA_enum_get(op->ptr, "action"); + + ED_mask_select_toggle_all(mask, action); + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_select_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select or Deselect All"; + ot->description = "Change selection of all curve points"; + ot->idname = "MASK_OT_select_all"; + + /* api callbacks */ + ot->exec = select_all_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_select_all(ot); +} + +/******************** select *********************/ + +static int select_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + float co[2]; + short extend = RNA_boolean_get(op->ptr, "extend"); + short deselect = RNA_boolean_get(op->ptr, "deselect"); + short toggle = RNA_boolean_get(op->ptr, "toggle"); + + int is_handle = 0; + const float threshold = 19; + + RNA_float_get_array(op->ptr, "location", co); + + point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL); + + if (extend == 0 && deselect == 0 && toggle == 0) + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + if (point) { + + if (is_handle) { + if (extend) { + masklay->act_spline = spline; + masklay->act_point = point; + + BKE_mask_point_select_set_handle(point, TRUE); + } + else if (deselect) { + BKE_mask_point_select_set_handle(point, FALSE); + } + else { + masklay->act_spline = spline; + masklay->act_point = point; + + if (!MASKPOINT_ISSEL_HANDLE(point)) { + BKE_mask_point_select_set_handle(point, TRUE); + } + else if (toggle) { + BKE_mask_point_select_set_handle(point, FALSE); + } + } + } + else { + if (extend) { + masklay->act_spline = spline; + masklay->act_point = point; + + BKE_mask_point_select_set(point, TRUE); + } + else if (deselect) { + BKE_mask_point_select_set(point, FALSE); + } + else { + masklay->act_spline = spline; + masklay->act_point = point; + + if (!MASKPOINT_ISSEL_ANY(point)) { + BKE_mask_point_select_set(point, TRUE); + } + else if (toggle) { + BKE_mask_point_select_set(point, FALSE); + } + } + } + + masklay->act_spline = spline; + masklay->act_point = point; + + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + else { + MaskSplinePointUW *uw; + + if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) { + + if (extend) { + masklay->act_spline = spline; + masklay->act_point = point; + + if (uw) uw->flag |= SELECT; + } + else if (deselect) { + if (uw) uw->flag &= ~SELECT; + } + else { + masklay->act_spline = spline; + masklay->act_point = point; + + if (uw) { + if (!(uw->flag & SELECT)) { + uw->flag |= SELECT; + } + else if (toggle) { + uw->flag &= ~SELECT; + } + } + } + + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + } + + return OPERATOR_PASS_THROUGH; +} + +static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + float co[2]; + + ED_mask_mouse_pos(C, event, co); + + RNA_float_set_array(op->ptr, "location", co); + + return select_exec(C, op); +} + +void MASK_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->description = "Select spline points"; + ot->idname = "MASK_OT_select"; + + /* api callbacks */ + ot->exec = select_exec; + ot->invoke = select_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_mouse_select(ot); + + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + "Location", "Location of vertex in normalized space", -1.0f, 1.0f); +} + + + +/********************** border select operator *********************/ + +static int border_select_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int i; + + rcti rect; + rctf rectf; + int change = FALSE, mode, extend; + + /* get rectangle from operator */ + rect.xmin = RNA_int_get(op->ptr, "xmin"); + rect.ymin = RNA_int_get(op->ptr, "ymin"); + rect.xmax = RNA_int_get(op->ptr, "xmax"); + rect.ymax = RNA_int_get(op->ptr, "ymax"); + + ED_mask_point_pos(C, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); + ED_mask_point_pos(C, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); + + mode = RNA_int_get(op->ptr, "gesture_mode"); + extend = RNA_boolean_get(op->ptr, "extend"); + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; + + /* TODO: handles? */ + /* TODO: uw? */ + + if (BLI_in_rctf(&rectf, point_deform->bezt.vec[1][0], point_deform->bezt.vec[1][1])) { + BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); + BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); + } + else if (!extend) { + BKE_mask_point_select_set(point, FALSE); + BKE_mask_point_select_set_handle(point, FALSE); + } + + change = TRUE; + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Border Select"; + ot->description = "Select markers using border selection"; + ot->idname = "MASK_OT_select_border"; + + /* api callbacks */ + ot->invoke = WM_border_select_invoke; + ot->exec = border_select_exec; + ot->modal = WM_border_select_modal; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_border(ot, TRUE); +} + +static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short select) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int i; + + rcti rect; + int change = FALSE; + + /* get rectangle from operator */ + BLI_lasso_boundbox(&rect, mcords, moves); + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; + + /* TODO: handles? */ + /* TODO: uw? */ + + float screen_co[2]; + + /* marker in screen coords */ + ED_mask_point_pos__reverse(C, + point_deform->bezt.vec[1][0], point_deform->bezt.vec[1][1], + &screen_co[0], &screen_co[1]); + + if (BLI_in_rcti(&rect, screen_co[0], screen_co[1]) && + BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) + { + BKE_mask_point_select_set(point, select); + BKE_mask_point_select_set_handle(point, select); + } + + change = TRUE; + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + } + + return change; +} + +static int clip_lasso_select_exec(bContext *C, wmOperator *op) +{ + int mcords_tot; + int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + + if (mcords) { + short select; + + select = !RNA_boolean_get(op->ptr, "deselect"); + do_lasso_select_mask(C, mcords, mcords_tot, select); + + MEM_freeN(mcords); + + return OPERATOR_FINISHED; + } + return OPERATOR_PASS_THROUGH; +} + +void MASK_OT_select_lasso(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Lasso Select"; + ot->description = "Select markers using lasso selection"; + ot->idname = "MASK_OT_select_lasso"; + + /* api callbacks */ + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = clip_lasso_select_exec; + ot->poll = ED_maskediting_mask_poll; + ot->cancel = WM_gesture_lasso_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items"); + RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection instead of deselecting everything first"); +} + +/********************** circle select operator *********************/ + +static int mask_spline_point_inside_ellipse(BezTriple *bezt, float offset[2], float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + float x, y; + + x = (bezt->vec[1][0] - offset[0]) * ellipse[0]; + y = (bezt->vec[1][1] - offset[1]) * ellipse[1]; + + return x * x + y * y < 1.0f; +} + +static int circle_select_exec(bContext *C, wmOperator *op) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int i; + + SpaceClip *sc = CTX_wm_space_clip(C); + ARegion *ar = CTX_wm_region(C); + int x, y, radius, width, height, mode, change = FALSE; + float zoomx, zoomy, offset[2], ellipse[2]; + + /* get operator properties */ + x = RNA_int_get(op->ptr, "x"); + y = RNA_int_get(op->ptr, "y"); + radius = RNA_int_get(op->ptr, "radius"); + + mode = RNA_int_get(op->ptr, "gesture_mode"); + + /* TODO - make generic! - this is SpaceClip only! */ + /* compute ellipse and position in unified coordinates */ + ED_space_clip_size(sc, &width, &height); + ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + width = height = MAX2(width, height); + + ellipse[0] = width * zoomx / radius; + ellipse[1] = height * zoomy / radius; + + ED_mask_point_pos(C, x, y, &offset[0], &offset[1]); + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &points_array[i]; + + if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) { + BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT); + BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT); + + change = TRUE; + } + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_circle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Circle Select"; + ot->description = "Select markers using circle selection"; + ot->idname = "MASK_OT_select_circle"; + + /* api callbacks */ + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = circle_select_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); +} + +static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + MaskSpline *spline; + MaskSplinePoint *point = NULL; + float co[2]; + int do_select = !RNA_boolean_get(op->ptr, "deselect"); + + int is_handle = 0; + const float threshold = 19; + int change = FALSE; + + ED_mask_mouse_pos(C, event, co); + + point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL); + + if (point) { + ED_mask_spline_select_set(spline, do_select); + masklay->act_spline = spline; + masklay->act_point = point; + + change = TRUE; + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_linked_pick(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked"; + ot->idname = "MASK_OT_select_linked_pick"; + ot->description = "(De)select all points linked to the curve under the mouse cursor"; + + /* api callbacks */ + ot->invoke = mask_select_linked_pick_invoke; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); +} + +static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + int change = FALSE; + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (ED_mask_spline_select_check(spline)) { + ED_mask_spline_select_set(spline, TRUE); + change = TRUE; + } + } + } + + if (change) { + ED_mask_select_flush_all(mask); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void MASK_OT_select_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked All"; + ot->idname = "MASK_OT_select_linked"; + ot->description = "Select all vertices linked to the active mesh"; + + /* api callbacks */ + ot->exec = mask_select_linked_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c new file mode 100644 index 00000000000..94aebb9f3a1 --- /dev/null +++ b/source/blender/editors/mask/mask_shapekey.c @@ -0,0 +1,168 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_shapekey.c + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_mask.h" +#include "ED_clip.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "mask_intern.h" /* own include */ + +static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + const int frame = CFRA; + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int change = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskLayerShape *masklay_shape; + + if (!ED_mask_layer_select_check(masklay)) { + continue; + } + + masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, frame); + BKE_mask_layer_shape_from_mask(masklay, masklay_shape); + change = TRUE; + } + + if (change) { + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_shape_key_insert(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Insert Shape Key"; + ot->description = ""; + ot->idname = "MASK_OT_shape_key_insert"; + + /* api callbacks */ + ot->exec = mask_shape_key_insert_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + const int frame = CFRA; + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int change = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskLayerShape *masklay_shape; + + if (!ED_mask_layer_select_check(masklay)) { + continue; + } + + masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame); + + if (masklay_shape) { + BKE_mask_layer_shape_unlink(masklay, masklay_shape); + change = TRUE; + } + } + + if (change) { + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_shape_key_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Shape Key"; + ot->description = ""; + ot->idname = "MASK_OT_shape_key_clear"; + + /* api callbacks */ + ot->exec = mask_shape_key_clear_exec; + ot->poll = ED_maskediting_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +int ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame) +{ + MaskLayer *masklay; + int change = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskLayerShape *masklay_shape; + + masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, frame); + BKE_mask_layer_shape_from_mask(masklay, masklay_shape); + change = TRUE; + } + + return change; +} -- cgit v1.2.3 From a3f855f35d53602571236278f1f983b658a5cb6e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 15:38:55 +0000 Subject: raskter rasterizer by Pete Larabell, from tomato branch --- intern/raskter/CMakeLists.txt | 40 +++ intern/raskter/SConscript | 10 + intern/raskter/raskter.c | 753 ++++++++++++++++++++++++++++++++++++++++++ intern/raskter/raskter.h | 59 ++++ 4 files changed, 862 insertions(+) create mode 100644 intern/raskter/CMakeLists.txt create mode 100644 intern/raskter/SConscript create mode 100644 intern/raskter/raskter.c create mode 100644 intern/raskter/raskter.h diff --git a/intern/raskter/CMakeLists.txt b/intern/raskter/CMakeLists.txt new file mode 100644 index 00000000000..3e1368d8eb0 --- /dev/null +++ b/intern/raskter/CMakeLists.txt @@ -0,0 +1,40 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Peter Larabell +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS + +) + +set(SRC + raskter.c + + raskter.h +) + +blender_add_lib(bf_intern_raskter "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/raskter/SConscript b/intern/raskter/SConscript new file mode 100644 index 00000000000..7ad505d70e4 --- /dev/null +++ b/intern/raskter/SConscript @@ -0,0 +1,10 @@ +#!/usr/bin/python + +Import ('env') + +sources = ['raskter.c'] + +incs = '' +defs = '' + +env.BlenderLib ('bf_intern_raskter', sources, Split(incs), Split(defs), libtype=['intern'], priority=[100] ) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c new file mode 100644 index 00000000000..152efb05cf0 --- /dev/null +++ b/intern/raskter/raskter.c @@ -0,0 +1,753 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Peter Larabell. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** \file raskter.c + * \ingroup RASKTER + */ + +#include +#include +#include "raskter.h" + +/* from BLI_utildefines.h */ +#define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) +#define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) + + +struct e_status { + int x; + int ybeg; + int xshift; + int xdir; + int drift; + int drift_inc; + int drift_dec; + int num; + struct e_status *e_next; +}; + +struct r_buffer_stats { + float *buf; + int sizex; + int sizey; +}; + +struct r_fill_context { + struct e_status *all_edges, *possible_edges; + struct r_buffer_stats rb; +}; + +/* + * Sort all the edges of the input polygon by Y, then by X, of the "first" vertex encountered. + * This will ensure we can scan convert the entire poly in one pass. + * + * Really the poly should be clipped to the frame buffer's dimensions here for speed of drawing + * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate + * for now. + */ +static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) +{ + int i; + int xbeg; + int ybeg; + int xend; + int yend; + int dx; + int dy; + int temp_pos; + int xdist; + struct e_status *e_new; + struct e_status *next_edge; + struct e_status **next_edge_ref; + struct poly_vert *v; + /* set up pointers */ + v = verts; + ctx->all_edges = NULL; + /* loop all verts */ + for (i = 0; i < num_verts; i++) { + /* determine beginnings and endings of edges, linking last vertex to first vertex */ + xbeg = v[i].x; + ybeg = v[i].y; + if (i) { + /* we're not at the last vert, so end of the edge is the previous vertex */ + xend = v[i - 1].x; + yend = v[i - 1].y; + } + else { + /* we're at the first vertex, so the "end" of this edge is the last vertex */ + xend = v[num_verts - 1].x; + yend = v[num_verts - 1].y; + } + /* make sure our edges are facing the correct direction */ + if (ybeg > yend) { + /* flip the Xs */ + temp_pos = xbeg; + xbeg = xend; + xend = temp_pos; + /* flip the Ys */ + temp_pos = ybeg; + ybeg = yend; + yend = temp_pos; + } + + /* calculate y delta */ + dy = yend - ybeg; + /* dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) */ + if (dy) { + /* create the edge and determine it's slope (for incremental line drawing) */ + e_new = open_edge++; + + /* calculate x delta */ + dx = xend - xbeg; + if (dx > 0) { + e_new->xdir = 1; + xdist = dx; + } + else { + e_new->xdir = -1; + xdist = -dx; + } + + e_new->x = xbeg; + e_new->ybeg = ybeg; + e_new->num = dy; + e_new->drift_dec = dy; + + /* calculate deltas for incremental drawing */ + if (dx >= 0) { + e_new->drift = 0; + } + else { + e_new->drift = -dy + 1; + } + if (dy >= xdist) { + e_new->drift_inc = xdist; + e_new->xshift = 0; + } + else { + e_new->drift_inc = xdist % dy; + e_new->xshift = (xdist / dy) * e_new->xdir; + } + next_edge_ref = &ctx->all_edges; + /* link in all the edges, in sorted order */ + for (;; ) { + next_edge = *next_edge_ref; + if (!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { + e_new->e_next = next_edge; + *next_edge_ref = e_new; + break; + } + next_edge_ref = &next_edge->e_next; + } + } + } +} + +/* + * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor + * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need + * if it ends up being coupled with this function. + */ +int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) +{ + int x_curr; /* current pixel position in X */ + int y_curr; /* current scan line being drawn */ + int yp; /* y-pixel's position in frame buffer */ + int swixd = 0; /* whether or not edges switched position in X */ + float *cpxl; /* pixel pointers... */ + float *mpxl; + float *spxl; + struct e_status *e_curr; /* edge pointers... */ + struct e_status *e_temp; + struct e_status *edgbuf; + struct e_status **edgec; + + + /* + * If the number of verts specified to render as a polygon is less than 3, + * return immediately. Obviously we cant render a poly with sides < 3. The + * return for this we set to 1, simply so it can be distinguished from the + * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter.cwhich is a failure to allocate memory. + */ + if (num_verts < 3) { + return(1); + } + + /* + * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + * multiplied by the number of edges, which is always equal to the number of verts in + * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + * the preceeding error, which was a rasterization request on a 2D poly with less than + * 3 sides. + */ + if ((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { + return(0); + } + + /* + * Do some preprocessing on all edges. This constructs a table structure in memory of all + * the edge properties and can "flip" some edges so sorting works correctly. + */ + preprocess_all_edges(ctx, verts, num_verts, edgbuf); + + /* + * Set the pointer for tracking the edges currently in processing to NULL to make sure + * we don't get some crazy value after initialization. + */ + ctx->possible_edges = NULL; + + /* + * Loop through all scan lines to be drawn. Since we sorted by Y values during + * preprocess_all_edges(), we can already exact values for the lowest and + * highest Y values we could possibly need by induction. The preprocessing sorted + * out edges by Y position, we can cycle the current edge being processed once + * it runs out of Y pixels. When we have no more edges, meaning the current edge + * is NULL after setting the "current" edge to be the previous current edge's + * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + * since we can't possibly have more scan lines if we ran out of edges. :) + * + * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + * Will get changed once DEM code gets in. + */ + for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { + + /* + * Link any edges that start on the current scan line into the list of + * edges currently needed to draw at least this, if not several, scan lines. + */ + + /* + * Set the current edge to the beginning of the list of edges to be rasterized + * into this scan line. + * + * We could have lots of edge here, so iterate over all the edges needed. The + * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + * so we safely cycle edges to thier own "next" edges in order. + * + * At each iteration, make sure we still have a non-NULL edge. + */ + for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr); ) { + x_curr = ctx->all_edges->x; /* Set current X position. */ + for (;; ) { /* Start looping edges. Will break when edges run out. */ + e_curr = *edgec; /* Set up a current edge pointer. */ + if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ + e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ + *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ + ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ + edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ + ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ + break; /* Stop looping edges (since we ran out or hit empty X span. */ + } + else { + edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ + } + } + } + + /* + * Determine the current scan line's offset in the pixel buffer based on its Y position. + * Basically we just multiply the current scan line's Y value by the number of pixels in each line. + */ + yp = y_curr * ctx->rb.sizex; + /* + * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + */ + spxl = ctx->rb.buf + (yp); + /* + * Set up the current edge to the first (in X) edge. The edges which could possibly be in this + * list were determined in the preceeding edge loop above. They were already sorted in X by the + * initial processing function. + * + * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + * we will eventually hit a NULL when the list runs out. + */ + for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { + /* + * Calculate a span of pixels to fill on the current scan line. + * + * Set the current pixel pointer by adding the X offset to the scan line's start offset. + * Cycle the current edge the next edge. + * Set the max X value to draw to be one less than the next edge's first pixel. This way we are + * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + * one time because it's on a vertex connecting two edges) + * + * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + * + * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + * but for now it is done here until the DEM code comes in. + */ + + /* set up xmin and xmax bounds on this scan line */ + cpxl = spxl + MAX2(e_curr->x, 0); + e_curr = e_curr->e_next; + mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; + + if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { + /* draw the pixels. */ + for (; cpxl <= mpxl; *cpxl++ = 1.0f); + } + } + + /* + * Loop through all edges of polygon that could be hit by this scan line, + * and figure out their x-intersections with the next scan line. + * + * Either A.) we wont have any more edges to test, or B.) we just add on the + * slope delta computed in preprocessing step. Since this draws non-antialiased + * polygons, we dont have fractional positions, so we only move in x-direction + * when needed to get all the way to the next pixel over... + */ + for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) { + if (!(--(e_curr->num))) { + *edgec = e_curr->e_next; + } + else { + e_curr->x += e_curr->xshift; + if ((e_curr->drift += e_curr->drift_inc) > 0) { + e_curr->x += e_curr->xdir; + e_curr->drift -= e_curr->drift_dec; + } + edgec = &e_curr->e_next; + } + } + /* + * It's possible that some edges may have crossed during the last step, so we'll be sure + * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + * sorted by x-intersection coordinate. We'll always scan through at least once to see if + * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + * pass, then we know we need to sort by x, so then cycle through edges again and perform + * the sort.- + */ + if (ctx->possible_edges) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* set flag that we had at least one switch */ + swixd = 1; + } + } + /* if we did have a switch, look for more (there will more if there was one) */ + for (;; ) { + /* reset exchange flag so it's only set if we encounter another one */ + swixd = 0; + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* flip the exchanged flag */ + swixd = 1; + } + } + /* if we had no exchanges, we're done reshuffling the pointers */ + if (!swixd) { + break; + } + } + } + } + + free(edgbuf); + return 1; +} + +int PLX_raskterize(float (*base_verts)[2], int num_base_verts, + float *buf, int buf_x, int buf_y) +{ + int i; /* i: Loop counter. */ + struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ + struct r_fill_context ctx = {0}; + + /* + * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert + * data structure multiplied by the number of base_verts. + * + * In the event of a failure to allocate the memory, return 0, so this error can + * be distinguished as a memory allocation error. + */ + if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) { + return(0); + } + + /* + * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are + * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates + * in the buffer-space coordinates passed in inside buf_x and buf_y. + * + * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel + * drawn will be 1.0f in value, there is no anti-aliasing. + */ + for (i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */ + ply[i].x = (base_verts[i][0] * buf_x) + 0.5f; /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (base_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */ + } + + ctx.rb.buf = buf; /* Set the output buffer pointer. */ + ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ + ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ + + i = rast_scan_fill(&ctx, ply, num_base_verts); /* Call our rasterizer, passing in the integer coords for each vert. */ + free(ply); /* Free the memory allocated for the integer coordinate table. */ + return(i); /* Return the value returned by the rasterizer. */ +} + +/* + * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor + * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need + * if it ends up being coupled with this function. + */ +int rast_scan_feather(struct r_fill_context *ctx, + float (*base_verts_f)[2], int num_base_verts, + struct poly_vert *feather_verts, float (*feather_verts_f)[2], int num_feather_verts) +{ + int x_curr; /* current pixel position in X */ + int y_curr; /* current scan line being drawn */ + int yp; /* y-pixel's position in frame buffer */ + int swixd = 0; /* whether or not edges switched position in X */ + float *cpxl; /* pixel pointers... */ + float *mpxl; + float *spxl; + struct e_status *e_curr; /* edge pointers... */ + struct e_status *e_temp; + struct e_status *edgbuf; + struct e_status **edgec; + + /* from dem */ + int a; // a = temporary pixel index buffer loop counter + float fsz; // size of the frame + unsigned int rsl; // long used for finding fast 1.0/sqrt + float rsf; // float used for finding fast 1.0/sqrt + const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt + + //unsigned int gradientFillOffset; + float t; + float ud; // ud = unscaled edge distance + float dmin; // dmin = minimun edge distance + float odist; // odist = current outer edge distance + float idist; // idist = current inner edge distance + float dx; // dx = X-delta (used for distance proportion calculation) + float dy; // dy = Y-delta (used for distance proportion calculation) + float xpxw = (1.0f / (float)(ctx->rb.sizex)); // xpxw = normalized pixel width + float ypxh = (1.0f / (float)(ctx->rb.sizey)); // ypxh = normalized pixel height + + /* + * If the number of verts specified to render as a polygon is less than 3, + * return immediately. Obviously we cant render a poly with sides < 3. The + * return for this we set to 1, simply so it can be distinguished from the + * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter + * which is a failure to allocate memory. + */ + if (num_feather_verts < 3) { + return(1); + } + + /* + * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + * multiplied by the number of edges, which is always equal to the number of verts in + * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + * the preceeding error, which was a rasterization request on a 2D poly with less than + * 3 sides. + */ + if ((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_feather_verts))) == NULL) { + return(0); + } + + /* + * Do some preprocessing on all edges. This constructs a table structure in memory of all + * the edge properties and can "flip" some edges so sorting works correctly. + */ + preprocess_all_edges(ctx, feather_verts, num_feather_verts, edgbuf); + + /* + * Set the pointer for tracking the edges currently in processing to NULL to make sure + * we don't get some crazy value after initialization. + */ + ctx->possible_edges = NULL; + + /* + * Loop through all scan lines to be drawn. Since we sorted by Y values during + * preprocess_all_edges(), we can already exact values for the lowest and + * highest Y values we could possibly need by induction. The preprocessing sorted + * out edges by Y position, we can cycle the current edge being processed once + * it runs out of Y pixels. When we have no more edges, meaning the current edge + * is NULL after setting the "current" edge to be the previous current edge's + * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + * since we can't possibly have more scan lines if we ran out of edges. :) + * + * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + * Will get changed once DEM code gets in. + */ + for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { + + /* + * Link any edges that start on the current scan line into the list of + * edges currently needed to draw at least this, if not several, scan lines. + */ + + /* + * Set the current edge to the beginning of the list of edges to be rasterized + * into this scan line. + * + * We could have lots of edge here, so iterate over all the edges needed. The + * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + * so we safely cycle edges to thier own "next" edges in order. + * + * At each iteration, make sure we still have a non-NULL edge. + */ + for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr); ) { + x_curr = ctx->all_edges->x; /* Set current X position. */ + for (;; ) { /* Start looping edges. Will break when edges run out. */ + e_curr = *edgec; /* Set up a current edge pointer. */ + if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ + e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ + *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ + ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ + edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ + ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ + break; /* Stop looping edges (since we ran out or hit empty X span. */ + } + else { + edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ + } + } + } + + /* + * Determine the current scan line's offset in the pixel buffer based on its Y position. + * Basically we just multiply the current scan line's Y value by the number of pixels in each line. + */ + yp = y_curr * ctx->rb.sizex; + /* + * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + */ + spxl = ctx->rb.buf + (yp); + /* + * Set up the current edge to the first (in X) edge. The edges which could possibly be in this + * list were determined in the preceeding edge loop above. They were already sorted in X by the + * initial processing function. + * + * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + * we will eventually hit a NULL when the list runs out. + */ + for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { + /* + * Calculate a span of pixels to fill on the current scan line. + * + * Set the current pixel pointer by adding the X offset to the scan line's start offset. + * Cycle the current edge the next edge. + * Set the max X value to draw to be one less than the next edge's first pixel. This way we are + * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + * one time because it's on a vertex connecting two edges) + * + * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + * + * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + * but for now it is done here until the DEM code comes in. + */ + + /* set up xmin and xmax bounds on this scan line */ + cpxl = spxl + MAX2(e_curr->x, 0); + e_curr = e_curr->e_next; + mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; + + if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { + t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * xpxw; + fsz = ((float)(y_curr) + 0.5f) * ypxh; + /* draw the pixels. */ + for (; cpxl <= mpxl; cpxl++, t += xpxw) { + //do feather check + // first check that pixel isn't already full, and only operate if it is not + if (*cpxl < 0.9999f) { + + dmin = 2.0f; // reset min distance to edge pixel + for (a = 0; a < num_feather_verts; a++) { // loop through all outer edge buffer pixels + dy = t - feather_verts_f[a][0]; // set dx to gradient pixel column - outer edge pixel row + dx = fsz - feather_verts_f[a][1]; // set dy to gradient pixel row - outer edge pixel column + ud = dx * dx + dy * dy; // compute sum of squares + if (ud < dmin) { // if our new sum of squares is less than the current minimum + dmin = ud; // set a new minimum equal to the new lower value + } + } + odist = dmin; // cast outer min to a float + rsf = odist * 0.5f; // + rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored + rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate + odist = *(float *)&rsl; // reciprocal square root + odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** -- + odist = odist * (rsopf - (rsf * odist * odist)); + dmin = 2.0f; // reset min distance to edge pixel + for (a = 0; a < num_base_verts; a++) { // loop through all inside edge pixels + dy = t - base_verts_f[a][0]; // compute delta in Y from gradient pixel to inside edge pixel + dx = fsz - base_verts_f[a][1]; // compute delta in X from gradient pixel to inside edge pixel + ud = dx * dx + dy * dy; // compute sum of squares + if (ud < dmin) { // if our new sum of squares is less than the current minimum we've found + dmin = ud; // set a new minimum equal to the new lower value + } + } + idist = dmin; // cast inner min to a float + rsf = idist * 0.5f; // + rsl = *(unsigned int *)&idist; // + rsl = 0x5f3759df - (rsl >> 1); // see notes above + idist = *(float *)&rsl; // + idist = idist * (rsopf - (rsf * idist * idist)); // + idist = idist * (rsopf - (rsf * idist * idist)); + /* + * Note once again that since we are using reciprocals of distance values our + * proportion is already the correct intensity, and does not need to be + * subracted from 1.0 like it would have if we used real distances. + */ + + /* set intensity, do the += so overlapping gradients are additive */ + *cpxl = (idist / (idist + odist)); + } + } + } + } + + /* + * Loop through all edges of polygon that could be hit by this scan line, + * and figure out their x-intersections with the next scan line. + * + * Either A.) we wont have any more edges to test, or B.) we just add on the + * slope delta computed in preprocessing step. Since this draws non-antialiased + * polygons, we dont have fractional positions, so we only move in x-direction + * when needed to get all the way to the next pixel over... + */ + for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) { + if (!(--(e_curr->num))) { + *edgec = e_curr->e_next; + } + else { + e_curr->x += e_curr->xshift; + if ((e_curr->drift += e_curr->drift_inc) > 0) { + e_curr->x += e_curr->xdir; + e_curr->drift -= e_curr->drift_dec; + } + edgec = &e_curr->e_next; + } + } + /* + * It's possible that some edges may have crossed during the last step, so we'll be sure + * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + * sorted by x-intersection coordinate. We'll always scan through at least once to see if + * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + * pass, then we know we need to sort by x, so then cycle through edges again and perform + * the sort.- + */ + if (ctx->possible_edges) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* set flag that we had at least one switch */ + swixd = 1; + } + } + /* if we did have a switch, look for more (there will more if there was one) */ + for (;; ) { + /* reset exchange flag so it's only set if we encounter another one */ + swixd = 0; + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* again, if current edge hits scan line at higher X than next edge, + * exchange the edges and set flag */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* flip the exchanged flag */ + swixd = 1; + } + } + /* if we had no exchanges, we're done reshuffling the pointers */ + if (!swixd) { + break; + } + } + } + } + + free(edgbuf); + return 1; +} + +int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, + float *buf, int buf_x, int buf_y) +{ + int i; /* i: Loop counter. */ + struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */ + struct r_fill_context ctx = {0}; + + /* for faster multiply */ + const float buf_x_f = (float)buf_x; + const float buf_y_f = (float)buf_y; + + /* + * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert + * data structure multiplied by the number of verts. + * + * In the event of a failure to allocate the memory, return 0, so this error can + * be distinguished as a memory allocation error. + */ + if ((fe = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_feather_verts))) == NULL) { + return(0); + } + + /* + * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are + * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates + * in the buffer-space coordinates passed in inside buf_x and buf_y. + * + * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel + * drawn will be 1.0f in value, there is no anti-aliasing. + */ + for (i = 0; i < num_feather_verts; i++) { /* Loop over all verts. */ + fe[i].x = (int)((feather_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ + fe[i].y = (int)((feather_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ + } + + ctx.rb.buf = buf; /* Set the output buffer pointer. */ + ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ + ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ + + /* Call our rasterizer, passing in the integer coords for each vert. */ + i = rast_scan_feather(&ctx, base_verts, num_base_verts, fe, feather_verts, num_feather_verts); + free(fe); + return i; /* Return the value returned by the rasterizer. */ +} diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h new file mode 100644 index 00000000000..e80ca1d41c4 --- /dev/null +++ b/intern/raskter/raskter.h @@ -0,0 +1,59 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Peter Larabell. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** \file raskter.h + * \ingroup RASKTER + */ + +struct poly_vert { + int x; + int y; +}; + +struct scan_line { + int xstart; + int xend; +}; + +struct scan_line_batch { + int num; + int ystart; + struct scan_line *slines; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int PLX_raskterize(float (*base_verts)[2], int num_base_verts, + float *buf, int buf_x, int buf_y); +int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, + float (*feather_verts)[2], int num_feather_verts, + float *buf, int buf_x, int buf_y); + +#ifdef __cplusplus +} +#endif -- cgit v1.2.3 From 8ffeca1f604879b17aa77256bed11b8586f60e4d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 15:44:42 +0000 Subject: copy mask file from tomato branch, sorry dont know how to do multiple of these at a time... --- source/blender/blenkernel/intern/mask.c | 2095 +++++++++++++++++++++++++++++++ 1 file changed, 2095 insertions(+) create mode 100644 source/blender/blenkernel/intern/mask.c diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c new file mode 100644 index 00000000000..870a84df66a --- /dev/null +++ b/source/blender/blenkernel/intern/mask.c @@ -0,0 +1,2095 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mask.c + * \ingroup bke + */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_movieclip_types.h" +#include "DNA_tracking_types.h" + +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_mask.h" +#include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_utildefines.h" + +#include "raskter.h" + +MaskSplinePoint *BKE_mask_spline_point_array(MaskSpline *spline) +{ + return spline->points_deform ? spline->points_deform : spline->points; +} + +MaskSplinePoint *BKE_mask_spline_point_array_from_point(MaskSpline *spline, MaskSplinePoint *point_ref) +{ + if ((point_ref >= spline->points) && (point_ref < &spline->points[spline->tot_point])) { + return spline->points; + } + + if ((point_ref >= spline->points_deform) && (point_ref < &spline->points_deform[spline->tot_point])) { + return spline->points_deform; + } + + BLI_assert(!"wrong array"); + return NULL; +} + +/* mask layers */ + +MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name) +{ + MaskLayer *masklay = MEM_callocN(sizeof(MaskLayer), __func__); + + if (name && name[0]) + BLI_strncpy(masklay->name, name, sizeof(masklay->name)); + else + strcpy(masklay->name, "MaskLayer"); + + BLI_addtail(&mask->masklayers, masklay); + + BKE_mask_layer_unique_name(mask, masklay); + + mask->masklay_tot++; + + masklay->alpha = 1.0f; + + return masklay; +} + +/* note: may still be hidden, caller needs to check */ +MaskLayer *BKE_mask_layer_active(Mask *mask) +{ + return BLI_findlink(&mask->masklayers, mask->masklay_act); +} + +void BKE_mask_layer_active_set(Mask *mask, MaskLayer *masklay) +{ + mask->masklay_act = BLI_findindex(&mask->masklayers, masklay); +} + +void BKE_mask_layer_remove(Mask *mask, MaskLayer *masklay) +{ + BLI_remlink(&mask->masklayers, masklay); + BKE_mask_layer_free(masklay); + + mask->masklay_tot--; + + if (mask->masklay_act >= mask->masklay_tot) + mask->masklay_act = mask->masklay_tot - 1; +} + +void BKE_mask_layer_unique_name(Mask *mask, MaskLayer *masklay) +{ + BLI_uniquename(&mask->masklayers, masklay, "MaskLayer", '.', offsetof(MaskLayer, name), sizeof(masklay->name)); +} + +/* splines */ + +MaskSpline *BKE_mask_spline_add(MaskLayer *masklay) +{ + MaskSpline *spline; + + spline = MEM_callocN(sizeof(MaskSpline), "new mask spline"); + BLI_addtail(&masklay->splines, spline); + + /* spline shall have one point at least */ + spline->points = MEM_callocN(sizeof(MaskSplinePoint), "new mask spline point"); + spline->tot_point = 1; + + /* cyclic shapes are more usually used */ + // spline->flag |= MASK_SPLINE_CYCLIC; // disable because its not so nice for drawing. could be done differently + + spline->weight_interp = MASK_SPLINE_INTERP_LINEAR; + + BKE_mask_parent_init(&spline->parent); + + return spline; +} + +static int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) +{ + float max_segment = 0.01f; + int i, resol = 1; + + if (width != 0 && height != 0) { + if (width >= height) + max_segment = 1.0f / (float) width; + else + max_segment = 1.0f / (float) height; + } + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *next_point; + BezTriple *bezt, *next_bezt; + float a, b, c, len; + int cur_resol; + + if (i == spline->tot_point - 1) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next_point = &spline->points[0]; + else + break; + } + else + next_point = &spline->points[i + 1]; + + bezt = &point->bezt; + next_bezt = &next_point->bezt; + + a = len_v3v3(bezt->vec[1], bezt->vec[2]); + b = len_v3v3(bezt->vec[2], next_bezt->vec[0]); + c = len_v3v3(next_bezt->vec[0], next_bezt->vec[1]); + + len = a + b + c; + cur_resol = len / max_segment; + + resol = MAX2(resol, cur_resol); + } + + return resol; +} + +static int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) +{ + const float max_segment = 0.005; + int resol = BKE_mask_spline_resolution(spline, width, height); + float max_jump = 0.0f; + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + float prev_u, prev_w; + int j; + + prev_u = 0.0f; + prev_w = point->bezt.weight; + + for (j = 0; j < point->tot_uw; j++) { + float jump = fabsf((point->uw[j].w - prev_w) / (point->uw[j].u - prev_u)); + + max_jump = MAX2(max_jump, jump); + + prev_u = point->uw[j].u; + prev_w = point->uw[j].w; + } + } + + resol += max_jump / max_segment; + + return resol; +} + +float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height, + int *tot_diff_point))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + MaskSplinePoint *point, *prev; + float (*diff_points)[2], (*fp)[2]; + int a, len, resol = BKE_mask_spline_resolution(spline, width, height); + + if (spline->tot_point <= 1) { + /* nothing to differentiate */ + *tot_diff_point = 0; + return NULL; + } + + /* count */ + len = (spline->tot_point - 1) * resol; + + if (spline->flag & MASK_SPLINE_CYCLIC) + len += resol; + else + len++; + + /* len+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = len; + diff_points = fp = MEM_mallocN((len + 1) * sizeof(*diff_points), "mask spline vets"); + + a = spline->tot_point - 1; + if (spline->flag & MASK_SPLINE_CYCLIC) + a++; + + prev = points_array; + point = prev + 1; + + while (a--) { + BezTriple *prevbezt; + BezTriple *bezt; + int j; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) + point = points_array; + + prevbezt = &prev->bezt; + bezt = &point->bezt; + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], prevbezt->vec[2][j], + bezt->vec[0][j], bezt->vec[1][j], + &(*fp)[j], resol, 2 * sizeof(float)); + } + + fp += resol; + + if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { + copy_v2_v2(*fp, bezt->vec[1]); + } + + prev = point; + point++; + } + + return diff_points; +} + +float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2] +{ + return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point); +} + +float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height, + int *tot_feather_point))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + float (*feather)[2], (*fp)[2]; + int i, j, tot, resol = BKE_mask_spline_feather_resolution(spline, width, height); + + tot = resol * spline->tot_point; + feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather diff points"); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + + for (j = 0; j < resol; j++, fp++) { + float u = (float) j / resol, weight; + float co[2], n[2]; + + /* TODO - these calls all calculate similar things + * could be unified for some speed */ + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + } + } + + *tot_feather_point = tot; + + return feather; +} + +float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2] +{ + return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point); +} + +float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i, tot = 0; + float (*feather)[2], (*fp)[2]; + + /* count */ + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + + tot += point->tot_uw + 1; + } + + /* create data */ + feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &points_array[i]; + BezTriple *bezt = &point->bezt; + float weight, n[2]; + int j; + + BKE_mask_point_normal(spline, point, 0.0f, n); + weight = BKE_mask_point_weight(spline, point, 0.0f); + + madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); + fp++; + + for (j = 0; j < point->tot_uw; j++) { + float u = point->uw[j].u; + float co[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + madd_v2_v2v2fl(*fp, co, n, weight); + fp++; + } + } + + *tot_feather_point = tot; + + return feather; +} + +void BKE_mask_point_direction_switch(MaskSplinePoint *point) +{ + const int tot_uw = point->tot_uw; + const int tot_uw_half = tot_uw / 2; + int i; + + if (tot_uw < 2) { + return; + } + + /* count */ + for (i = 0; i < tot_uw_half; i++) { + MaskSplinePointUW *uw_a = &point->uw[i]; + MaskSplinePointUW *uw_b = &point->uw[tot_uw - (i + 1)]; + SWAP(MaskSplinePointUW, *uw_a, *uw_b); + } + for (i = 0; i < tot_uw; i++) { + MaskSplinePointUW *uw = &point->uw[i]; + uw->u = 1.0f - uw->u; + } +} + +//typedef (float)[MASK_OBJECT_SHAPE_ELEM_SIZE] MaskLayerShapeElem; + +typedef struct MaskLayerShapeElem { + float value[MASK_OBJECT_SHAPE_ELEM_SIZE]; +} MaskLayerShapeElem; + +void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline) +{ + const int tot_point = spline->tot_point; + const int tot_point_half = tot_point / 2; + int i, i_prev; + + if (tot_point < 2) { + return; + } + + /* count */ + for (i = 0; i < tot_point_half; i++) { + MaskSplinePoint *point_a = &spline->points[i]; + MaskSplinePoint *point_b = &spline->points[tot_point - (i + 1)]; + SWAP(MaskSplinePoint, *point_a, *point_b); + } + + /* correct UW's */ + i_prev = tot_point - 1; + for (i = 0; i < tot_point; i++) { + + BKE_mask_point_direction_switch(&spline->points[i]); + + SWAP(MaskSplinePointUW *, spline->points[i].uw, spline->points[i_prev].uw); + SWAP(int, spline->points[i].tot_uw, spline->points[i_prev].tot_uw); + + i_prev = i; + } + + /* correct animation */ + if (masklay->splines_shapes.first) { + MaskLayerShape *masklay_shape; + + const int spline_index = BKE_mask_layer_shape_spline_to_index(masklay, spline); + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + MaskLayerShapeElem *fp_arr = (MaskLayerShapeElem *)masklay_shape->data; + + for (i = 0; i < tot_point_half; i++) { + MaskLayerShapeElem *fp_a = &fp_arr[spline_index + (i) ]; + MaskLayerShapeElem *fp_b = &fp_arr[spline_index + (tot_point - (i + 1))]; + SWAP(MaskLayerShapeElem, *fp_a, *fp_b); + } + } + } +} + + +float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2]) +{ + const float proj_eps = 1e-3; + const float proj_eps_squared = proj_eps * proj_eps; + const int N = 1000; + float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; + float ang = -1.0f; + + while (u1 > 0.0f || u2 < 1.0f) { + float n1[2], n2[2], co1[2], co2[2]; + float v1[2], v2[2]; + float ang1, ang2; + + if (u1 >= 0.0f) { + BKE_mask_point_segment_co(spline, point, u1, co1); + BKE_mask_point_normal(spline, point, u1, n1); + sub_v2_v2v2(v1, co, co1); + + if (len_squared_v2(v1) > proj_eps_squared) { + ang1 = angle_v2v2(v1, n1); + if (ang1 > M_PI / 2.0f) + ang1 = M_PI - ang1; + + if (ang < 0.0f || ang1 < ang) { + ang = ang1; + u = u1; + } + } + else { + u = u1; + break; + } + } + + if (u2 <= 1.0f) { + BKE_mask_point_segment_co(spline, point, u2, co2); + BKE_mask_point_normal(spline, point, u2, n2); + sub_v2_v2v2(v2, co, co2); + + if (len_squared_v2(v2) > proj_eps_squared) { + ang2 = angle_v2v2(v2, n2); + if (ang2 > M_PI / 2.0f) + ang2 = M_PI - ang2; + + if (ang2 < ang) { + ang = ang2; + u = u2; + } + } + else { + u = u2; + break; + } + } + + u1 -= du; + u2 += du; + } + + return u; +} + +/* point */ + +int BKE_mask_point_has_handle(MaskSplinePoint *point) +{ + BezTriple *bezt = &point->bezt; + + return bezt->h1 == HD_ALIGN; +} + +void BKE_mask_point_handle(MaskSplinePoint *point, float handle[2]) +{ + float vec[2]; + + sub_v2_v2v2(vec, point->bezt.vec[0], point->bezt.vec[1]); + + handle[0] = (point->bezt.vec[1][0] + vec[1]); + handle[1] = (point->bezt.vec[1][1] - vec[0]); +} + +void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], int keep_direction, + float orig_handle[2], float orig_vec[3][3]) +{ + BezTriple *bezt = &point->bezt; + float v1[2], v2[2], vec[2]; + + if (keep_direction) { + sub_v2_v2v2(v1, loc, orig_vec[1]); + sub_v2_v2v2(v2, orig_handle, orig_vec[1]); + + project_v2_v2v2(vec, v1, v2); + + if (dot_v2v2(v2, vec) > 0) { + float len = len_v2(vec); + + sub_v2_v2v2(v1, orig_vec[0], orig_vec[1]); + + mul_v2_fl(v1, len / len_v2(v1)); + + add_v2_v2v2(bezt->vec[0], bezt->vec[1], v1); + sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v1); + } + else { + copy_v3_v3(bezt->vec[0], bezt->vec[1]); + copy_v3_v3(bezt->vec[2], bezt->vec[1]); + } + } + else { + sub_v2_v2v2(v1, loc, bezt->vec[1]); + + v2[0] = -v1[1]; + v2[1] = v1[0]; + + add_v2_v2v2(bezt->vec[0], bezt->vec[1], v2); + sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v2); + } +} + +float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, + int *tot_feather_point) +{ + float *feather, *fp; + int i, resol = BKE_mask_spline_feather_resolution(spline, width, height); + + feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); + + for (i = 0; i < resol; i++, fp += 2) { + float u = (float)(i % resol) / resol, weight; + float co[2], n[2]; + + BKE_mask_point_segment_co(spline, point, u, co); + BKE_mask_point_normal(spline, point, u, n); + weight = BKE_mask_point_weight(spline, point, u); + + fp[0] = co[0] + n[0] * weight; + fp[1] = co[1] + n[1] * weight; + } + + *tot_feather_point = resol; + + return feather; +} + +float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_feather_point) +{ + return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point); +} + +float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point, + int width, int height, int *tot_diff_point) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + + BezTriple *bezt, *next; + float *diff_points, *fp; + int j, resol = BKE_mask_spline_resolution(spline, width, height); + + bezt = &point->bezt; + + if (point == &points_array[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(points_array[0].bezt); + else + next = NULL; + } + else next = &((point + 1))->bezt; + + if (!next) + return NULL; + + /* resol+1 because of 'forward_diff_bezier' function */ + *tot_diff_point = resol + 1; + diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets"); + + for (j = 0; j < 2; j++) { + BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], + next->vec[0][j], next->vec[1][j], + fp + j, resol, 2 * sizeof(float)); + } + + copy_v2_v2(fp + 2 * resol, next->vec[1]); + + return diff_points; +} + +float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int *tot_diff_point) +{ + return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point); +} + +void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2]) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + + BezTriple *bezt = &point->bezt, *next; + float q0[2], q1[2], q2[2], r0[2], r1[2]; + + if (point == &points_array[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(points_array[0].bezt); + else + next = NULL; + } + else next = &((point + 1))->bezt; + + if (!next) { + copy_v2_v2(co, bezt->vec[1]); + return; + } + + interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); + interp_v2_v2v2(q1, bezt->vec[2], next->vec[0], u); + interp_v2_v2v2(q2, next->vec[0], next->vec[1], u); + + interp_v2_v2v2(r0, q0, q1, u); + interp_v2_v2v2(r1, q1, q2, u); + + interp_v2_v2v2(co, r0, r1, u); +} + +void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2]) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + + BezTriple *bezt = &point->bezt, *next; + float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; + + if (point == &points_array[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) + next = &(points_array[0].bezt); + else + next = NULL; + } + else { + next = &((point + 1))->bezt; + } + + if (!next) { + BKE_mask_point_handle(point, vec); + + sub_v2_v2v2(n, vec, bezt->vec[1]); + normalize_v2(n); + return; + } + + interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); + interp_v2_v2v2(q1, bezt->vec[2], next->vec[0], u); + interp_v2_v2v2(q2, next->vec[0], next->vec[1], u); + + interp_v2_v2v2(r0, q0, q1, u); + interp_v2_v2v2(r1, q1, q2, u); + + sub_v2_v2v2(vec, r1, r0); + + n[0] = -vec[1]; + n[1] = vec[0]; + + normalize_v2(n); +} + +float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + + BezTriple *bezt = &point->bezt, *bezt_next; + float cur_u, cur_w, next_u, next_w, fac; + int i; + + if (point == &points_array[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + bezt_next = &(points_array[0].bezt); + } + else { + bezt_next = NULL; + } + } + else { + bezt_next = &((point + 1))->bezt; + } + + if (!bezt_next) + return bezt->weight; + + for (i = 0; i < point->tot_uw + 1; i++) { + + if (i == 0) { + cur_u = 0.0f; + cur_w = bezt->weight; + } + else { + cur_u = point->uw[i - 1].u; + cur_w = point->uw[i - 1].w; + } + + if (i == point->tot_uw) { + next_u = 1.0f; + next_w = bezt_next->weight; + } + else { + next_u = point->uw[i].u; + next_w = point->uw[i].w; + } + + if (u >= cur_u && u <= next_u) { + break; + } + } + + fac = (u - cur_u) / (next_u - cur_u); + + if (spline->weight_interp == MASK_SPLINE_INTERP_EASE) + return cur_w + (next_w - cur_w) * (3.0f * fac * fac - 2.0f * fac * fac * fac); + else + return (1.0f - fac) * cur_w + fac * next_w; +} + +MaskSplinePointUW *BKE_mask_point_sort_uw(MaskSplinePoint *point, MaskSplinePointUW *uw) +{ + if (point->tot_uw > 1) { + int idx = uw - point->uw; + + if (idx > 0 && point->uw[idx - 1].u > uw->u) { + while (idx > 0 && point->uw[idx - 1].u > point->uw[idx].u) { + SWAP(MaskSplinePointUW, point->uw[idx - 1], point->uw[idx]); + idx--; + } + } + + if (idx < point->tot_uw - 1 && point->uw[idx + 1].u < uw->u) { + while (idx < point->tot_uw - 1 && point->uw[idx + 1].u < point->uw[idx].u) { + SWAP(MaskSplinePointUW, point->uw[idx + 1], point->uw[idx]); + idx++; + } + } + + return &point->uw[idx]; + } + + return uw; +} + +void BKE_mask_point_add_uw(MaskSplinePoint *point, float u, float w) +{ + if (!point->uw) + point->uw = MEM_callocN(sizeof(*point->uw), "mask point uw"); + else + point->uw = MEM_reallocN(point->uw, (point->tot_uw + 1) * sizeof(*point->uw)); + + point->uw[point->tot_uw].u = u; + point->uw[point->tot_uw].w = w; + + point->tot_uw++; + + BKE_mask_point_sort_uw(point, &point->uw[point->tot_uw - 1]); +} + +void BKE_mask_point_select_set(MaskSplinePoint *point, const short do_select) +{ + int i; + + if (do_select) { + MASKPOINT_SEL_ALL(point); + } + else { + MASKPOINT_DESEL_ALL(point); + } + + for (i = 0; i < point->tot_uw; i++) { + if (do_select) { + point->uw[i].flag |= SELECT; + } + else { + point->uw[i].flag &= ~SELECT; + } + } +} + +void BKE_mask_point_select_set_handle(MaskSplinePoint *point, const short do_select) +{ + if (do_select) { + MASKPOINT_SEL_HANDLE(point); + } + else { + MASKPOINT_DESEL_HANDLE(point); + } +} + +/* only mask block itself */ +static Mask *mask_alloc(const char *name) +{ + Mask *mask; + + mask = BKE_libblock_alloc(&G.main->mask, ID_MSK, name); + + return mask; +} + +Mask *BKE_mask_new(const char *name) +{ + Mask *mask; + char mask_name[MAX_ID_NAME - 2]; + + if (name && name[0]) + BLI_strncpy(mask_name, name, sizeof(mask_name)); + else + strcpy(mask_name, "Mask"); + + mask = mask_alloc(mask_name); + + return mask; +} + +void BKE_mask_point_free(MaskSplinePoint *point) +{ + if (point->uw) + MEM_freeN(point->uw); +} + +void BKE_mask_spline_free(MaskSpline *spline) +{ + int i = 0; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point; + point = &spline->points[i]; + BKE_mask_point_free(point); + + if (spline->points_deform) { + point = &spline->points_deform[i]; + BKE_mask_point_free(point); + } + } + + MEM_freeN(spline->points); + + if (spline->points_deform) { + MEM_freeN(spline->points_deform); + } + + MEM_freeN(spline); +} + +MaskSpline *BKE_mask_spline_copy(MaskSpline *spline) +{ + MaskSpline *nspline = MEM_callocN(sizeof(MaskSpline), "new spline"); + int i; + + *nspline = *spline; + + nspline->points_deform = NULL; + nspline->points = MEM_dupallocN(nspline->points); + + for (i = 0; i < nspline->tot_point; i++) { + MaskSplinePoint *point = &nspline->points[i]; + + if (point->uw) + point->uw = MEM_dupallocN(point->uw); + } + + return nspline; +} + +void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape) +{ + MEM_freeN(masklay_shape->data); + + MEM_freeN(masklay_shape); +} + +void BKE_mask_layer_free(MaskLayer *masklay) +{ + MaskSpline *spline; + MaskLayerShape *masklay_shape; + + /* free splines */ + spline = masklay->splines.first; + while (spline) { + MaskSpline *next_spline = spline->next; + + BLI_remlink(&masklay->splines, spline); + BKE_mask_spline_free(spline); + + spline = next_spline; + } + + /* free animation data */ + masklay_shape = masklay->splines_shapes.first; + while (masklay_shape) { + MaskLayerShape *next_masklay_shape = masklay_shape->next; + + BLI_remlink(&masklay->splines_shapes, masklay_shape); + BKE_mask_layer_shape_free(masklay_shape); + + masklay_shape = next_masklay_shape; + } + + MEM_freeN(masklay); +} + +void BKE_mask_free(Mask *mask) +{ + MaskLayer *masklay = mask->masklayers.first; + + while (masklay) { + MaskLayer *next_masklay = masklay->next; + + BLI_remlink(&mask->masklayers, masklay); + BKE_mask_layer_free(masklay); + + masklay = next_masklay; + } +} + +void BKE_mask_unlink(Main *bmain, Mask *mask) +{ + bScreen *scr; + ScrArea *area; + SpaceLink *sl; + + for (scr = bmain->screen.first; scr; scr = scr->id.next) { + for (area = scr->areabase.first; area; area = area->next) { + for (sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sc = (SpaceClip *) sl; + + if (sc->mask == mask) + sc->mask = NULL; + } + } + } + } + + mask->id.us = 0; +} + +void BKE_mask_coord_from_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) +{ + int width, height; + + /* scaling for the clip */ + BKE_movieclip_get_size(clip, user, &width, &height); + + if (width == height) { + r_co[0] = co[0]; + r_co[1] = co[1]; + } + else if (width < height) { + r_co[0] = ((co[0] - 0.5f) * ((float)width / (float)height)) + 0.5f; + r_co[1] = co[1]; + } + else { /* (width > height) */ + r_co[0] = co[0]; + r_co[1] = ((co[1] - 0.5f) * ((float)height / (float)width)) + 0.5f; + } +} + +/* as above but divide */ +void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) +{ + int width, height; + + /* scaling for the clip */ + BKE_movieclip_get_size(clip, user, &width, &height); + + if (width == height) { + r_co[0] = co[0]; + r_co[1] = co[1]; + } + else if (width < height) { + r_co[0] = ((co[0] - 0.5f) / ((float)width / (float)height)) + 0.5f; + r_co[1] = co[1]; + } + else { /* (width > height) */ + r_co[0] = co[0]; + r_co[1] = ((co[1] - 0.5f) / ((float)height / (float)width)) + 0.5f; + } +} + +static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[2]) +{ + if (!parent) + return FALSE; + + if ((parent->flag & MASK_PARENT_ACTIVE) == 0) + return FALSE; + + if (parent->id_type == ID_MC) { + if (parent->id) { + MovieClip *clip = (MovieClip *) parent->id; + MovieTracking *tracking = (MovieTracking *) &clip->tracking; + MovieTrackingObject *ob = BKE_tracking_named_object(tracking, parent->parent); + + if (ob) { + MovieTrackingTrack *track = BKE_tracking_named_track(tracking, ob, parent->sub_parent); + + MovieClipUser user = {0}; + user.framenr = ctime; + + if (track) { + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); + float marker_pos_ofs[2]; + add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); + BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs); + + return TRUE; + } + } + } + } + + return FALSE; +} + +int BKE_mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2]) +{ + float parent_co[2]; + + if (BKE_mask_evaluate_parent(parent, ctime, parent_co)) { + sub_v2_v2v2(r_delta, parent_co, parent->parent_orig); + return TRUE; + } + else { + return FALSE; + } +} + +static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev_point, MaskSplinePoint *next_point) +{ + BezTriple *bezt = &point->bezt; + BezTriple *prev_bezt = NULL, *next_bezt = NULL; + //int handle_type = bezt->h1; + + if (prev_point) + prev_bezt = &prev_point->bezt; + + if (next_point) + next_bezt = &next_point->bezt; + +#if 1 + if (prev_bezt || next_bezt) { + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + } +#else + if (handle_type == HD_VECT) { + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + } + else if (handle_type == HD_AUTO) { + BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + } + else if (handle_type == HD_ALIGN) { + float v1[3], v2[3]; + float vec[3], h[3]; + + sub_v3_v3v3(v1, bezt->vec[0], bezt->vec[1]); + sub_v3_v3v3(v2, bezt->vec[2], bezt->vec[1]); + add_v3_v3v3(vec, v1, v2); + + if (len_v3(vec) > 1e-3) { + h[0] = vec[1]; + h[1] = -vec[0]; + h[2] = 0.0f; + } + else { + copy_v3_v3(h, v1); + } + + add_v3_v3v3(bezt->vec[0], bezt->vec[1], h); + sub_v3_v3v3(bezt->vec[2], bezt->vec[1], h); + } +#endif +} + +void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, MaskSplinePoint *point, + MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) +{ + MaskSplinePoint *prev_point, *next_point; + int i = (int)(point - spline->points); + + BLI_assert(i >= i && i < spline->tot_point); + + if (i == 0) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + prev_point = &spline->points[spline->tot_point - 1]; + } + else { + prev_point = NULL; + } + } + else { + prev_point = point - 1; + } + + if (i == spline->tot_point - 1) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + next_point = &spline->points[0]; + } + else { + next_point = NULL; + } + } + else { + next_point = point + 1; + } + + *r_point_prev = prev_point; + *r_point_next = next_point; +} + +/* calculates the tanget of a point by its previous and next + * (ignoring handles - as if its a poly line) */ +void BKE_mask_calc_tangent_polyline(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, float t[2]) +{ + float tvec_a[2], tvec_b[2]; + + MaskSplinePoint *prev_point, *next_point; + + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + if (prev_point) { + sub_v2_v2v2(tvec_a, point->bezt.vec[1], prev_point->bezt.vec[1]); + normalize_v2(tvec_a); + } + else { + zero_v2(tvec_a); + } + + if (next_point) { + sub_v2_v2v2(tvec_b, next_point->bezt.vec[1], point->bezt.vec[1]); + normalize_v2(tvec_b); + } + else { + zero_v2(tvec_b); + } + + add_v2_v2v2(t, tvec_a, tvec_b); + normalize_v2(t); +} + +void BKE_mask_calc_handle_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) +{ + MaskSplinePoint *prev_point, *next_point; + + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + mask_calc_point_handle(point, prev_point, next_point); +} + +static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist) +{ + if (!equals_v2v2(v2, v1)) { + float nor[2]; + + sub_v2_v2v2(nor, v1, v2); + normalize_v2(nor); + madd_v2_v2v2fl(v1, v2, nor, dist); + } +} + +void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, const float u) +{ + /* TODO! - make this interpolate between siblings - not always midpoint! */ + int length_tot = 0; + float length_average = 0.0f; + float weight_average = 0.0f; + + + MaskSplinePoint *prev_point, *next_point; + + BLI_assert(u >= 0.0f && u <= 1.0f); + + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + if (prev_point && next_point) { + length_average = ((len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]) * (1.0f - u)) + + (len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]) * u)); + + weight_average = (prev_point->bezt.weight * (1.0f - u) + + next_point->bezt.weight * u); + length_tot = 1; + } + else { + if (prev_point) { + length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); + weight_average += prev_point->bezt.weight; + length_tot++; + } + + if (next_point) { + length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); + weight_average += next_point->bezt.weight; + length_tot++; + } + } + + if (length_tot) { + length_average /= (float)length_tot; + weight_average /= (float)length_tot; + + enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + point->bezt.weight = weight_average; + } +} + + +/** + * \brief Resets auto handles even for non-auto bezier points + * + * Useful for giving sane defaults. + */ +void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, + const short do_recalc_length) +{ + MaskSplinePoint *prev_point, *next_point; + const char h_back[2] = {point->bezt.h1, point->bezt.h2}; + const float length_average = (do_recalc_length) ? 0.0f /* dummy value */ : + (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) + + len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) / 2.0f; + + BKE_mask_get_handle_point_adjacent(mask, spline, point, + &prev_point, &next_point); + + point->bezt.h1 = HD_AUTO; + point->bezt.h2 = HD_AUTO; + mask_calc_point_handle(point, prev_point, next_point); + + point->bezt.h1 = h_back[0]; + point->bezt.h2 = h_back[1]; + + /* preserve length by applying it back */ + if (do_recalc_length == FALSE) { + enforce_dist_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average); + enforce_dist_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average); + } +} + +void BKE_mask_calc_handles(Mask *mask) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + + /* could be done in a different function... */ + if (spline->points_deform) { + BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + } + } + } + } +} + +void BKE_mask_update_deform(Mask *mask) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + const int i_prev = (i - 1) % spline->tot_point; + const int i_next = (i + 1) % spline->tot_point; + + BezTriple *bezt_prev = &spline->points[i_prev].bezt; + BezTriple *bezt = &spline->points[i].bezt; + BezTriple *bezt_next = &spline->points[i_next].bezt; + + BezTriple *bezt_def_prev = &spline->points_deform[i_prev].bezt; + BezTriple *bezt_def = &spline->points_deform[i].bezt; + BezTriple *bezt_def_next = &spline->points_deform[i_next].bezt; + + float w_src[4]; + int j; + + for (j = 0; j <= 2; j += 2) { /* (0, 2) */ + printf("--- %d %d, %d, %d\n", i, j, i_prev, i_next); + barycentric_weights_v2(bezt_prev->vec[1], bezt->vec[1], bezt_next->vec[1], + bezt->vec[j], w_src); + interp_v3_v3v3v3(bezt_def->vec[j], + bezt_def_prev->vec[1], bezt_def->vec[1], bezt_def_next->vec[1], w_src); + } + } + } + } +} + +void BKE_mask_spline_ensure_deform(MaskSpline *spline) +{ + int allocated_points = (MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform)); + // printf("SPLINE ALLOC %p %d\n", spline->points_deform, allocated_points); + + if (spline->points_deform == NULL || allocated_points != spline->tot_point) { + printf("alloc new deform spline\n"); + + if (spline->points_deform) { + int i; + + for (i = 0; i < allocated_points; i++) { + MaskSplinePoint *point = &spline->points_deform[i]; + BKE_mask_point_free(point); + } + + MEM_freeN(spline->points_deform); + } + + spline->points_deform = MEM_callocN(sizeof(*spline->points_deform) * spline->tot_point, __func__); + } + else { + // printf("alloc spline done\n"); + } +} + +void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + + /* animation if available */ + if (do_newframe) { + MaskLayerShape *masklay_shape_a; + MaskLayerShape *masklay_shape_b; + int found; + + if ((found = BKE_mask_layer_shape_find_frame_range(masklay, (int)ctime, + &masklay_shape_a, &masklay_shape_b))) + { + if (found == 1) { +#if 0 + printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes), + masklay_shape_a->frame); +#endif + + BKE_mask_layer_shape_to_mask(masklay, masklay_shape_a); + } + else if (found == 2) { + float w = masklay_shape_b->frame - masklay_shape_a->frame; +#if 0 + printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes), + masklay_shape_a->frame, masklay_shape_b->frame); +#endif + BKE_mask_layer_shape_to_mask_interp(masklay, masklay_shape_a, masklay_shape_b, + (ctime - masklay_shape_a->frame) / w); + } + else { + /* always fail, should never happen */ + BLI_assert(found == 2); + } + } + } + /* animation done... */ + } + + BKE_mask_calc_handles(mask); + + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + int i; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + + BKE_mask_spline_ensure_deform(spline); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + MaskSplinePoint *point_deform = &spline->points_deform[i]; + float delta[2]; + + BKE_mask_point_free(point_deform); + + *point_deform = *point; + point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; + + if (BKE_mask_evaluate_parent_delta(&point->parent, ctime, delta)) { + add_v2_v2(point_deform->bezt.vec[0], delta); + add_v2_v2(point_deform->bezt.vec[1], delta); + add_v2_v2(point_deform->bezt.vec[2], delta); + } + } + } + } +} + +/* the purpose of this function is to ensure spline->points_deform is never out of date. + * for now re-evaluate all. eventually this might work differently */ +void BKE_mask_update_display(Mask *mask, float ctime) +{ +#if 0 + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (spline->points_deform) { + int i = 0; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point; + + if (spline->points_deform) { + point = &spline->points_deform[i]; + BKE_mask_point_free(point); + } + } + if (spline->points_deform) { + MEM_freeN(spline->points_deform); + } + + spline->points_deform = NULL; + } + } + } +#endif + + BKE_mask_evaluate(mask, ctime, FALSE); +} + +void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const int do_newframe) +{ + Mask *mask; + + for (mask = bmain->mask.first; mask; mask = mask->id.next) { + BKE_mask_evaluate(mask, ctime, do_newframe); + } +} + +void BKE_mask_update_scene(Main *bmain, Scene *scene, const int do_newframe) +{ + Mask *mask; + + for (mask = bmain->mask.first; mask; mask = mask->id.next) { + if (mask->id.flag & LIB_ID_RECALC) { + BKE_mask_evaluate_all_masks(bmain, CFRA, do_newframe); + } + } +} + +void BKE_mask_parent_init(MaskParent *parent) +{ + parent->id_type = ID_MC; +} + + +/* *** own animation/shapekey implimentation *** + * BKE_mask_layer_shape_XXX */ + +int BKE_mask_layer_shape_totvert(MaskLayer *masklay) +{ + int tot = 0; + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + tot += spline->tot_point; + } + + return tot; +} + +static void mask_layer_shape_from_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) +{ + copy_v2_v2(&fp[0], bezt->vec[0]); + copy_v2_v2(&fp[2], bezt->vec[1]); + copy_v2_v2(&fp[4], bezt->vec[2]); + fp[6] = bezt->weight; + fp[7] = bezt->radius; +} + +static void mask_layer_shape_to_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE]) +{ + copy_v2_v2(bezt->vec[0], &fp[0]); + copy_v2_v2(bezt->vec[1], &fp[2]); + copy_v2_v2(bezt->vec[2], &fp[4]); + bezt->weight = fp[6]; + bezt->radius = fp[7]; +} + +/* these functions match. copy is swapped */ +void BKE_mask_layer_shape_from_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape) +{ + int tot = BKE_mask_layer_shape_totvert(masklay); + + if (masklay_shape->tot_vert == tot) { + float *fp = masklay_shape->data; + + MaskSpline *spline; + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + mask_layer_shape_from_mask_point(&spline->points[i].bezt, fp); + fp += MASK_OBJECT_SHAPE_ELEM_SIZE; + } + } + } + else { + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, masklay_shape->tot_vert, tot, masklay_shape->frame); + } +} + +void BKE_mask_layer_shape_to_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape) +{ + int tot = BKE_mask_layer_shape_totvert(masklay); + + if (masklay_shape->tot_vert == tot) { + float *fp = masklay_shape->data; + + MaskSpline *spline; + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + mask_layer_shape_to_mask_point(&spline->points[i].bezt, fp); + fp += MASK_OBJECT_SHAPE_ELEM_SIZE; + } + } + } + else { + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, masklay_shape->tot_vert, tot, masklay_shape->frame); + } +} + +BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const float b[2], + const float t, const float s) +{ + target[0] = s * a[0] + t * b[0]; + target[1] = s * a[1] + t * b[1]; +} + +/* linear interpolation only */ +void BKE_mask_layer_shape_to_mask_interp(MaskLayer *masklay, + MaskLayerShape *masklay_shape_a, + MaskLayerShape *masklay_shape_b, + const float fac) +{ + int tot = BKE_mask_layer_shape_totvert(masklay); + if (masklay_shape_a->tot_vert == tot && masklay_shape_b->tot_vert == tot) { + float *fp_a = masklay_shape_a->data; + float *fp_b = masklay_shape_b->data; + const float ifac = 1.0f - fac; + + MaskSpline *spline; + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + BezTriple *bezt = &spline->points[i].bezt; + /* *** BKE_mask_layer_shape_from_mask - swapped *** */ + interp_v2_v2v2_flfl(bezt->vec[0], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; + interp_v2_v2v2_flfl(bezt->vec[1], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; + interp_v2_v2v2_flfl(bezt->vec[2], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2; + bezt->weight = (fp_a[0] * ifac) + (fp_b[0] * fac); + bezt->radius = (fp_a[1] * ifac) + (fp_b[1] * fac); fp_a += 2; fp_b += 2; + } + } + } + else { + printf("%s: vert mismatch %d != %d != %d (frame %d - %d)\n", + __func__, masklay_shape_a->tot_vert, masklay_shape_b->tot_vert, tot, + masklay_shape_a->frame, masklay_shape_b->frame); + } +} + +MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, int frame) +{ + MaskLayerShape *masklay_shape; + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + if (frame == masklay_shape->frame) { + return masklay_shape; + } + else if (frame < masklay_shape->frame) { + break; + } + } + + return NULL; +} + +/* when returning 2 - the frame isnt found but before/after frames are */ +int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, int frame, + MaskLayerShape **r_masklay_shape_a, + MaskLayerShape **r_masklay_shape_b) +{ + MaskLayerShape *masklay_shape; + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + if (frame == masklay_shape->frame) { + *r_masklay_shape_a = masklay_shape; + *r_masklay_shape_b = NULL; + return 1; + } + else if (frame < masklay_shape->frame) { + if (masklay_shape->prev) { + *r_masklay_shape_a = masklay_shape->prev; + *r_masklay_shape_b = masklay_shape; + return 2; + } + else { + *r_masklay_shape_a = masklay_shape; + *r_masklay_shape_b = NULL; + return 1; + } + } + } + + *r_masklay_shape_a = NULL; + *r_masklay_shape_b = NULL; + + return 0; +} + +MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, int frame) +{ + MaskLayerShape *masklay_shape; + + masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame); + + if (masklay_shape == NULL) { + int tot_vert = BKE_mask_layer_shape_totvert(masklay); + + masklay_shape = MEM_mallocN(sizeof(MaskLayerShape), __func__); + masklay_shape->frame = frame; + masklay_shape->tot_vert = tot_vert; + masklay_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + + BLI_addtail(&masklay->splines_shapes, masklay_shape); + + BKE_mask_layer_shape_sort(masklay); + } + +#if 0 + { + MaskLayerShape *masklay_shape; + int i = 0; + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + printf("mask %d, %d\n", i++, masklay_shape->frame); + } + } +#endif + + return masklay_shape; +} + +void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape) +{ + BLI_remlink(&masklay->splines_shapes, masklay_shape); + + BKE_mask_layer_shape_free(masklay_shape); +} + +static int mask_layer_shape_sort_cb(void *masklay_shape_a_ptr, void *masklay_shape_b_ptr) +{ + MaskLayerShape *masklay_shape_a = (MaskLayerShape *)masklay_shape_a_ptr; + MaskLayerShape *masklay_shape_b = (MaskLayerShape *)masklay_shape_b_ptr; + + if (masklay_shape_a->frame < masklay_shape_b->frame) return -1; + else if (masklay_shape_a->frame > masklay_shape_b->frame) return 1; + else return 0; +} + +void BKE_mask_layer_shape_sort(MaskLayer *masklay) +{ + BLI_sortlist(&masklay->splines_shapes, mask_layer_shape_sort_cb); +} + +int BKE_mask_layer_shape_spline_from_index(MaskLayer *masklay, int index, + MaskSpline **r_masklay_shape, int *r_index) +{ + MaskSpline *spline; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (index < spline->tot_point) { + *r_masklay_shape = spline; + *r_index = index; + return TRUE; + } + index -= spline->tot_point; + } + + return FALSE; +} + +int BKE_mask_layer_shape_spline_to_index(MaskLayer *masklay, MaskSpline *spline) +{ + MaskSpline *spline_iter; + int i_abs = 0; + for (spline_iter = masklay->splines.first; + spline_iter && spline_iter != spline; + i_abs += spline_iter->tot_point, spline_iter = spline_iter->next) + { + /* pass */ + } + + return i_abs; +} + +/* basic 2D interpolation functions, could make more comprehensive later */ +static void interp_weights_uv_v2_calc(float r_uv[2], const float pt[2], const float pt_a[2], const float pt_b[2]) +{ + float pt_on_line[2]; + r_uv[0] = closest_to_line_v2(pt_on_line, pt, pt_a, pt_b); + r_uv[1] = (len_v2v2(pt_on_line, pt) / len_v2v2(pt_a, pt_b)) * + ((line_point_side_v2(pt_a, pt_b, pt) < 0.0f) ? -1.0 : 1.0); /* this line only sets the sign */ +} + + +static void interp_weights_uv_v2_apply(const float uv[2], float r_pt[2], const float pt_a[2], const float pt_b[2]) +{ + const float dvec[2] = {pt_b[0] - pt_a[0], + pt_b[1] - pt_a[1]}; + + /* u */ + madd_v2_v2v2fl(r_pt, pt_a, dvec, uv[0]); + + /* v */ + r_pt[0] += -dvec[1] * uv[1]; + r_pt[1] += dvec[0] * uv[1]; +} + +/* when a now points added - resize all shapekey array */ +void BKE_mask_layer_shape_changed_add(MaskLayer *masklay, int index, + int do_init, int do_init_interpolate) +{ + MaskLayerShape *masklay_shape; + + /* spline index from masklay */ + MaskSpline *spline; + int spline_point_index; + + if (BKE_mask_layer_shape_spline_from_index(masklay, index, + &spline, &spline_point_index)) + { + /* sanity check */ + /* the point has already been removed in this array so subtract one when comparing with the shapes */ + int tot = BKE_mask_layer_shape_totvert(masklay) - 1; + + /* for interpolation */ + /* TODO - assumes closed curve for now */ + float uv[3][2]; /* 3x 2D handles */ + const int pi_curr = spline_point_index; + const int pi_prev = ((spline_point_index - 1) + spline->tot_point) % spline->tot_point; + const int pi_next = (spline_point_index + 1) % spline->tot_point; + + const int index_offset = index - spline_point_index; + /* const int pi_curr_abs = index; */ + const int pi_prev_abs = pi_prev + index_offset; + const int pi_next_abs = pi_next + index_offset; + + int i; + if (do_init_interpolate) { + for (i = 0; i < 3; i++) { + interp_weights_uv_v2_calc(uv[i], + spline->points[pi_curr].bezt.vec[i], + spline->points[pi_prev].bezt.vec[i], + spline->points[pi_next].bezt.vec[i]); + } + } + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + if (tot == masklay_shape->tot_vert) { + float *data_resized; + + masklay_shape->tot_vert++; + data_resized = MEM_mallocN(masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + if (index > 0) { + memcpy(data_resized, + masklay_shape->data, + index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + if (index != masklay_shape->tot_vert - 1) { + memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE], + masklay_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE), + (masklay_shape->tot_vert - (index + 1)) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + if (do_init) { + float *fp = &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE]; + + mask_layer_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp); + + if (do_init_interpolate && spline->tot_point > 2) { + for (i = 0; i < 3; i++) { + interp_weights_uv_v2_apply(uv[i], + &fp[i * 2], + &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)], + &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]); + } + } + } + else { + memset(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], + 0, + sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + MEM_freeN(masklay_shape->data); + masklay_shape->data = data_resized; + } + else { + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, masklay_shape->tot_vert, tot, masklay_shape->frame); + } + } + } +} + + +/* move array to account for removed point */ +void BKE_mask_layer_shape_changed_remove(MaskLayer *masklay, int index, int count) +{ + MaskLayerShape *masklay_shape; + + /* the point has already been removed in this array so add one when comparing with the shapes */ + int tot = BKE_mask_layer_shape_totvert(masklay); + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + if (tot == masklay_shape->tot_vert - count) { + float *data_resized; + + masklay_shape->tot_vert -= count; + data_resized = MEM_mallocN(masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + if (index > 0) { + memcpy(data_resized, + masklay_shape->data, + index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + if (index != masklay_shape->tot_vert) { + memcpy(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE], + masklay_shape->data + ((index + count) * MASK_OBJECT_SHAPE_ELEM_SIZE), + (masklay_shape->tot_vert - index) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + } + + MEM_freeN(masklay_shape->data); + masklay_shape->data = data_resized; + } + else { + printf("%s: vert mismatch %d != %d (frame %d)\n", + __func__, masklay_shape->tot_vert - count, tot, masklay_shape->frame); + } + } +} + +/* local functions */ +static void invert_vn_vn(float *array, const int size) +{ + float *arr = array + (size - 1); + int i = size; + while (i--) { + *(arr) = 1.0f - *(arr); + arr--; + } +} + +static void m_invert_vn_vn(float *array, const float f, const int size) +{ + float *arr = array + (size - 1); + int i = size; + while (i--) { + *(arr) = 1.0f - (*(arr) * f); + arr--; + } +} + +static void linear_clamp_vn_vn(float *array, const int size) +{ + float *arr = array + (size - 1); + + int i = size; + while (i--) { + if (*arr <= 0.0f) *arr = 0.0f; + else if (*arr >= 1.0f) *arr = 1.0f; + else *arr = srgb_to_linearrgb(*arr); + arr--; + } +} + +/* rasterization */ +void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) +{ + MaskLayer *masklay; + + /* temp blending buffer */ + const int buffer_size = width * height; + float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__); + float max_dseg_len = 0.0f; + + if (width >= height) { + max_dseg_len = (float)(width); + } + else { + max_dseg_len = (float)(height); + } + max_dseg_len = 1.0f / max_dseg_len; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + float alpha; + + if (masklay->restrictflag & MASK_RESTRICT_RENDER) { + continue; + } + + memset(buffer_tmp, 0, sizeof(float) * buffer_size); + + for (spline = masklay->splines.first; spline; spline = spline->next) { + float (*diff_points)[2]; + int tot_diff_point; + + float (*diff_feather_points)[2]; + int tot_diff_feather_points; + + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point); + if (tot_diff_point) { + diff_feather_points = + BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, + &tot_diff_feather_points); + } + + /* TODO, make this optional! */ + if (width != height) { + float *fp; + float *ffp; + int i; + float asp; + + if (width < height) { + fp = &diff_points[0][0]; + ffp = &diff_feather_points[0][0]; + asp = (float)width / (float)height; + } + else { + fp = &diff_points[0][1]; + ffp = &diff_feather_points[0][1]; + asp = (float)height / (float)width; + } + + for (i = 0; i < tot_diff_point; i++, fp += 2) { + (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; + } + for (i = 0; i < tot_diff_feather_points; i++, ffp += 2) { + (*ffp) = (((*ffp) - 0.5f) / asp) + 0.5f; + } + } + + if (tot_diff_point) { + PLX_raskterize((float (*)[2])diff_points, tot_diff_point, + buffer_tmp, width, height); + + if (tot_diff_feather_points) { + PLX_raskterize_feather((float (*)[2])diff_points, tot_diff_point, + (float (*)[2])diff_feather_points, tot_diff_feather_points, + buffer_tmp, width, height); + MEM_freeN(diff_feather_points); + } + + MEM_freeN(diff_points); + } + } + + /* blend with original */ + if (masklay->blend_flag & MASK_BLENDFLAG_INVERT) { + /* apply alpha multiply before inverting */ + if (masklay->alpha != 1.0f) { + m_invert_vn_vn(buffer_tmp, masklay->alpha, buffer_size); + } + else { + invert_vn_vn(buffer_tmp, buffer_size); + } + + alpha = 1.0f; + } + else { + alpha = masklay->alpha; + } + + switch (masklay->blend) { + case MASK_BLEND_SUBTRACT: + { + if (alpha == 1.0f) { + sub_vn_vn(buffer, buffer_tmp, buffer_size); + } + else { + msub_vn_vn(buffer, buffer_tmp, alpha, buffer_size); + } + break; + } + case MASK_BLEND_ADD: + default: + { + if (alpha == 1.0f) { + add_vn_vn(buffer, buffer_tmp, buffer_size); + } + else { + madd_vn_vn(buffer, buffer_tmp, alpha, buffer_size); + } + break; + } + } + + /* clamp at the end */ + linear_clamp_vn_vn(buffer, buffer_size); + } + + MEM_freeN(buffer_tmp); +} -- cgit v1.2.3 From 070d2122b00df3442c6c5b00b9be02534df680aa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 15:45:04 +0000 Subject: mask header from tomato/ --- source/blender/blenkernel/BKE_mask.h | 170 +++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 source/blender/blenkernel/BKE_mask.h diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h new file mode 100644 index 00000000000..3f837f995ce --- /dev/null +++ b/source/blender/blenkernel/BKE_mask.h @@ -0,0 +1,170 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_MASK_H__ +#define __BKE_MASK_H__ + +struct Main; +struct Mask; +struct MaskParent; +struct MaskLayer; +struct MaskLayerShape; +struct MaskSpline; +struct MaskSplinePoint; +struct MaskSplinePointUW; +struct MovieClip; +struct MovieClipUser; +struct Scene; + +struct MaskSplinePoint *BKE_mask_spline_point_array(struct MaskSpline *spline); +struct MaskSplinePoint *BKE_mask_spline_point_array_from_point(struct MaskSpline *spline, struct MaskSplinePoint *point_ref); + +/* mask layers */ +struct MaskLayer *BKE_mask_layer_new(struct Mask *mask, const char *name); +struct MaskLayer *BKE_mask_layer_active(struct Mask *mask); +void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay); +void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay); + +void BKE_mask_layer_free(struct MaskLayer *masklay); +void BKE_mask_spline_free(struct MaskSpline *spline); +struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline); +void BKE_mask_point_free(struct MaskSplinePoint *point); + +void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay); + +/* splines */ +struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay); + +float (*BKE_mask_spline_differentiate(struct MaskSpline *spline, int *tot_diff_point))[2]; +float (*BKE_mask_spline_feather_differentiated_points(struct MaskSpline *spline, int *tot_feather_point))[2]; + +float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, int width, int height, int *tot_diff_point))[2]; +float (*BKE_mask_spline_feather_differentiated_points_with_resolution(struct MaskSpline *spline, + int width, int height, int *tot_feather_point))[2]; + +float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; + +void BKE_mask_point_direction_switch(struct MaskSplinePoint *point); +void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline); +float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float start_u, const float co[2]); + +/* point */ +int BKE_mask_point_has_handle(struct MaskSplinePoint *point); +void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]); +void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], int keep_direction, + float orig_handle[2], float orig_vec[3][3]); + +float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int *tot_diff_point); +float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, + int *tot_feather_point); + +float *BKE_mask_point_segment_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point, + int width, int height, int *tot_diff_point); + +float *BKE_mask_point_segment_feather_diff_with_resolution(struct MaskSpline *spline, struct MaskSplinePoint *point, + int width, int height, + int *tot_feather_point); + +void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]); +void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, + float u, float n[2]); +float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u); +struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); +void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); + +void BKE_mask_point_select_set(struct MaskSplinePoint *point, const short do_select); +void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const short do_select); + +/* general */ +struct Mask *BKE_mask_new(const char *name); + +void BKE_mask_free(struct Mask *mask); +void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); + +void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); +void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); + +/* parenting */ + +void BKE_mask_update_display(struct Mask *mask, float ctime); + +void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); +void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); +void BKE_mask_parent_init(struct MaskParent *parent); +void BKE_mask_calc_handle_adjacent_interp(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + const float u); +void BKE_mask_calc_tangent_polyline(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); +void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); +void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + const short do_recalc_length); +void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, + struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); +void BKE_mask_calc_handles(struct Mask *mask); +void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); + +/* animation */ +int BKE_mask_layer_shape_totvert(struct MaskLayer *masklay); +void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); +void BKE_mask_layer_shape_to_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); +void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, + struct MaskLayerShape *masklay_shape_a, + struct MaskLayerShape *masklay_shape_b, + const float fac); +struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, int frame); +int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, int frame, + struct MaskLayerShape **r_masklay_shape_a, + struct MaskLayerShape **r_masklay_shape_b); +struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, int frame); +void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); +void BKE_mask_layer_shape_sort(struct MaskLayer *masklay); + +int BKE_mask_layer_shape_spline_from_index(struct MaskLayer *masklay, int index, + struct MaskSpline **r_masklay_shape, int *r_index); +int BKE_mask_layer_shape_spline_to_index(struct MaskLayer *masklay, struct MaskSpline *spline); + +int BKE_mask_layer_shape_spline_index(struct MaskLayer *masklay, int index, + struct MaskSpline **r_masklay_shape, int *r_index); +void BKE_mask_layer_shape_changed_add(struct MaskLayer *masklay, int index, + int do_init, int do_init_interpolate); + +void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, int count); + +/* rasterization */ +void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); + +#define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) +#define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT) +#define MASKPOINT_ISSEL_HANDLE_ONLY(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) +#define MASKPOINT_ISSEL_HANDLE(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) + +#define MASKPOINT_SEL_ALL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 +#define MASKPOINT_DESEL_ALL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 +#define MASKPOINT_INVSEL_ALL(p) { (p)->bezt.f1 ^= SELECT; (p)->bezt.f2 ^= SELECT; (p)->bezt.f3 ^= SELECT; } (void)0 + +#define MASKPOINT_SEL_HANDLE(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 +#define MASKPOINT_DESEL_HANDLE(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 + +#endif -- cgit v1.2.3 From 489fa2d108783e1f254a367293529b272cc53d31 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 15:49:58 +0000 Subject: remaining mask files from tomato. these wont get svn history carried over. --- source/blender/compositor/nodes/COM_MaskNode.cpp | 65 ++ source/blender/compositor/nodes/COM_MaskNode.h | 38 ++ .../compositor/operations/COM_MaskOperation.cpp | 124 ++++ .../compositor/operations/COM_MaskOperation.h | 66 +++ source/blender/editors/include/ED_mask.h | 47 ++ source/blender/makesdna/DNA_mask_types.h | 163 +++++ source/blender/makesrna/intern/rna_mask.c | 657 +++++++++++++++++++++ .../nodes/composite/nodes/node_composite_mask.c | 101 ++++ 8 files changed, 1261 insertions(+) create mode 100644 source/blender/compositor/nodes/COM_MaskNode.cpp create mode 100644 source/blender/compositor/nodes/COM_MaskNode.h create mode 100644 source/blender/compositor/operations/COM_MaskOperation.cpp create mode 100644 source/blender/compositor/operations/COM_MaskOperation.h create mode 100644 source/blender/editors/include/ED_mask.h create mode 100644 source/blender/makesdna/DNA_mask_types.h create mode 100644 source/blender/makesrna/intern/rna_mask.c create mode 100644 source/blender/nodes/composite/nodes/node_composite_mask.c diff --git a/source/blender/compositor/nodes/COM_MaskNode.cpp b/source/blender/compositor/nodes/COM_MaskNode.cpp new file mode 100644 index 00000000000..991c3f75e05 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MaskNode.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_MaskNode.h" +#include "COM_ExecutionSystem.h" +#include "COM_MaskOperation.h" + +extern "C" { + #include "DNA_mask_types.h" +} + +MaskNode::MaskNode(bNode *editorNode): Node(editorNode) +{ +} + +void MaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext * context) +{ + const RenderData *data = &context->getScene()->r; + + InputSocket *inputImage = this->getInputSocket(0); + OutputSocket *outputMask = this->getOutputSocket(0); + + bNode *editorNode = this->getbNode(); + Mask *mask = (Mask *)editorNode->id; + + // always connect the output image + MaskOperation *operation = new MaskOperation(); + + if (inputImage->isConnected()) { + inputImage->relinkConnections(operation->getInputSocket(0), 0, graph); + } + else { + operation->setMaskWidth(data->xsch * data->size / 100.0f); + operation->setMaskHeight(data->ysch * data->size / 100.0f); + } + + if (outputMask->isConnected()) { + outputMask->relinkConnections(operation->getOutputSocket()); + } + + operation->setMask(mask); + operation->setFramenumber(context->getFramenumber()); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_MaskNode.h b/source/blender/compositor/nodes/COM_MaskNode.h new file mode 100644 index 00000000000..9d2ea1889d9 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MaskNode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_Node.h" +#include "DNA_node_types.h" + +/** + * @brief MaskNode + * @ingroup Node + */ +class MaskNode : public Node { + + +public: + MaskNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); + +}; diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp new file mode 100644 index 00000000000..a742306f440 --- /dev/null +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + +#include "COM_MaskOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "DNA_scene_types.h" + +extern "C" { + #include "BKE_mask.h" +} + +MaskOperation::MaskOperation(): NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->mask = NULL; + this->maskWidth = 0; + this->maskHeight = 0; + this->framenumber = 0; + this->rasterizedMask = NULL; + setComplex(true); +} + +void MaskOperation::initExecution() +{ + initMutex(); + this->rasterizedMask = NULL; +} + +void MaskOperation::deinitExecution() +{ + if (this->rasterizedMask) { + MEM_freeN(rasterizedMask); + this->rasterizedMask = NULL; + } +} + +void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (this->rasterizedMask) + return this->rasterizedMask; + + if (!this->mask) + return NULL; + + BLI_mutex_lock(getMutex()); + if (this->rasterizedMask == NULL) { + int width = this->getWidth(); + int height = this->getHeight(); + float *buffer; + + buffer = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); + BKE_mask_rasterize(mask, width, height, buffer); + + this->rasterizedMask = buffer; + } + BLI_mutex_unlock(getMutex()); + + return this->rasterizedMask; +} + +void MaskOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[]) +{ + if (maskWidth == 0 || maskHeight == 0) { + NodeOperation::determineResolution(resolution, preferredResolution); + } + else { + unsigned int nr[2]; + + nr[0] = maskWidth; + nr[1] = maskHeight; + + NodeOperation::determineResolution(resolution, nr); + + resolution[0] = maskWidth; + resolution[1] = maskHeight; + } +} + +void MaskOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + if (!data) { + color[0] = 0; + color[1] = 0; + color[2] = 0; + color[3] = 1.0f; + } + else { + float *buffer = (float*) data; + int index = (y * this->getWidth() + x); + + color[0] = buffer[index]; + color[1] = buffer[index]; + color[2] = buffer[index]; + color[3] = 1.0f; + } +} + + diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h new file mode 100644 index 00000000000..9f2c7f53f56 --- /dev/null +++ b/source/blender/compositor/operations/COM_MaskOperation.h @@ -0,0 +1,66 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Sergey Sharybin + */ + + +#ifndef _COM_MaskOperation_h +#define _COM_MaskOperation_h + +#include "COM_NodeOperation.h" +#include "DNA_scene_types.h" +#include "DNA_mask_types.h" +#include "BLI_listbase.h" +#include "IMB_imbuf_types.h" + +/** + * Class with implementation of mask rasterization + */ +class MaskOperation : public NodeOperation { +protected: + Mask *mask; + int maskWidth; + int maskHeight; + int framenumber; + float *rasterizedMask; + + /** + * Determine the output resolution. The resolution is retrieved from the Renderer + */ + void determineResolution(unsigned int resolution[], unsigned int preferredResolution[]); + +public: + MaskOperation(); + + void initExecution(); + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + + void setMask(Mask *mask) {this->mask = mask;} + void setMaskWidth(int width) {this->maskWidth = width;} + void setMaskHeight(int height) {this->maskHeight = height;} + void setFramenumber(int framenumber) {this->framenumber = framenumber;} + + void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data); +}; + +#endif diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h new file mode 100644 index 00000000000..0c4c2f4788c --- /dev/null +++ b/source/blender/editors/include/ED_mask.h @@ -0,0 +1,47 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ED_mask.h + * \ingroup editors + */ + +#ifndef __ED_MASK_H__ +#define __ED_MASK_H__ + +struct wmKeyConfig; + +/* mask_editor.c */ +void ED_operatortypes_mask(void); +void ED_keymap_mask(struct wmKeyConfig *keyconf); +void ED_operatormacros_mask(void); + +/* mask_draw.c */ +void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type); + +/* mask_shapekey.c */ +int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame); + +#endif /* ED_TEXT_H */ diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h new file mode 100644 index 00000000000..28fc9466613 --- /dev/null +++ b/source/blender/makesdna/DNA_mask_types.h @@ -0,0 +1,163 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file DNA_mask_types.h + * \ingroup DNA + * \since march-2012 + * \author Sergey Sharybin + */ + +#ifndef __DNA_MASK_TYPES_H__ +#define __DNA_MASK_TYPES_H__ + +#include "DNA_defs.h" +#include "DNA_ID.h" +#include "DNA_listBase.h" +#include "DNA_curve_types.h" + +typedef struct Mask { + ID id; + struct AnimData *adt; + ListBase masklayers; /* mask layers */ + int masklay_act; /* index of active mask layer (-1 == None) */ + int masklay_tot; /* total number of mask layers */ +} Mask; + +typedef struct MaskParent { + int flag; /* parenting flags */ + int id_type; /* type of parenting */ + ID *id; /* ID block of entity to which mask/spline is parented to + * in case of parenting to movie tracking data set to MovieClip datablock */ + char parent[64]; /* entity of parent to which parenting happened + * in case of parenting to movie tracking data contains name of layer */ + char sub_parent[64]; /* sub-entity of parent to which parenting happened + * in case of parenting to movie tracking data contains name of track */ + float parent_orig[2]; /* track location at the moment of parenting */ +} MaskParent; + +typedef struct MaskSplinePointUW { + float u, w; /* u coordinate along spline segment and weight of this point */ + int flag; /* different flags of this point */ +} MaskSplinePointUW; + +typedef struct MaskSplinePoint { + BezTriple bezt; /* actual point coordinates and it's handles */ + int pad; + int tot_uw; /* number of uv feather values */ + MaskSplinePointUW *uw; /* feather UV values */ + MaskParent parent; /* parenting information of particular spline point */ +} MaskSplinePoint; + +typedef struct MaskSpline { + struct MaskSpline *next, *prev; + + int flag; /* defferent spline flag (closed, ...) */ + int tot_point; /* total number of points */ + MaskSplinePoint *points; /* points which defines spline itself */ + MaskParent parent; /* parenting information of the whole spline */ + + int weight_interp, pad; /* weight interpolation */ + + MaskSplinePoint *points_deform; /* deformed copy of 'points' BezTriple data - not saved */ +} MaskSpline; + +/* one per frame */ +typedef struct MaskLayerShape { + struct MaskLayerShape *next, *prev; + + float *data; /* u coordinate along spline segment and weight of this point */ + int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */ + int frame; /* different flags of this point */ + char flag; + char pad[7]; +} MaskLayerShape; + +typedef struct MaskLayer { + struct MaskLayer *next, *prev; + + char name[64]; /* name of the mask layer (64 = MAD_ID_NAME - 2) */ + + ListBase splines; /* list of splines which defines this mask layer */ + ListBase splines_shapes; + + struct MaskSpline *act_spline; /* active spline */ + struct MaskSplinePoint *act_point; /* active point */ + + /* blending options */ + float alpha; + char blend; + char blend_flag; + + //char flag; /* not used yet */ + char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */ + char pad[1]; +} MaskLayer; + +/* MaskParent->flag */ +#define MASK_PARENT_ACTIVE (1 << 0) + +/* MaskSpline->flag */ +/* reserve (1 << 0) for SELECT */ +#define MASK_SPLINE_CYCLIC (1 << 1) + +/* MaskSpline->weight_interp */ +#define MASK_SPLINE_INTERP_LINEAR 1 +#define MASK_SPLINE_INTERP_EASE 2 + +#define MASK_OBJECT_SHAPE_ELEM_SIZE 8 /* 3x 2D points + weight + radius == 8 */ + +/* ob->restrictflag */ +#define MASK_RESTRICT_VIEW 1 +#define MASK_RESTRICT_SELECT 2 +#define MASK_RESTRICT_RENDER 4 + +/* SpaceClip->mask_draw_flag */ +#define MASK_DRAWFLAG_SMOOTH 1 + +/* copy of eSpaceImage_UVDT */ +/* SpaceClip->mask_draw_type */ +enum { + MASK_DT_OUTLINE = 0, + MASK_DT_DASH, + MASK_DT_BLACK, + MASK_DT_WHITE +}; + +/* masklay->blend */ +enum { + MASK_BLEND_ADD = 0, + MASK_BLEND_SUBTRACT = 1 +}; + +/* masklay->blend_flag */ +enum { + MASK_BLENDFLAG_INVERT = (1 << 0) +}; + + +#endif // __DNA_MASK_TYPES_H__ diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c new file mode 100644 index 00000000000..c356cae81af --- /dev/null +++ b/source/blender/makesrna/intern/rna_mask.c @@ -0,0 +1,657 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_mask.c + * \ingroup RNA + */ + + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BKE_movieclip.h" +#include "BKE_tracking.h" + +#include "RNA_define.h" + +#include "rna_internal.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ +#include "DNA_scene_types.h" + +#include "WM_types.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#ifdef RNA_RUNTIME + +#include "DNA_mask_types.h" + +#include "BKE_depsgraph.h" +#include "BKE_mask.h" + +#include "RNA_access.h" + +#include "WM_api.h" + +static void rna_Mask_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Mask *mask = ptr->id.data; + + WM_main_add_notifier(NC_MASK|ND_DATA, mask); + DAG_id_tag_update( &mask->id, 0); +} + +/* note: this function exists only to avoid id refcounting */ +static void rna_MaskParent_id_set(PointerRNA *ptr, PointerRNA value) +{ + MaskParent *mpar = (MaskParent*) ptr->data; + + mpar->id = value.data; +} + +static StructRNA *rna_MaskParent_id_typef(PointerRNA *ptr) +{ + MaskParent *mpar = (MaskParent*) ptr->data; + + return ID_code_to_RNA_type(mpar->id_type); +} + +static void rna_MaskParent_id_type_set(PointerRNA *ptr, int value) +{ + MaskParent *mpar = (MaskParent*) ptr->data; + + /* change ID-type to the new type */ + mpar->id_type = value; + + /* clear the id-block if the type is invalid */ + if ((mpar->id) && (GS(mpar->id->name) != mpar->id_type)) + mpar->id = NULL; +} + +static void rna_Mask_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Mask *mask = (Mask *)ptr->id.data; + + rna_iterator_listbase_begin(iter, &mask->masklayers, NULL); +} + +static int rna_Mask_layer_active_index_get(PointerRNA *ptr) +{ + Mask *mask = (Mask *)ptr->id.data; + + return mask->masklay_act; +} + +static void rna_Mask_layer_active_index_set(PointerRNA *ptr, int value) +{ + Mask *mask = (Mask *)ptr->id.data; + + mask->masklay_act = value; +} + +static void rna_Mask_layer_active_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) +{ + Mask *mask = (Mask *)ptr->id.data; + + *min = 0; + *max = mask->masklay_tot - 1; + *max = MAX2(0, *max); + + *softmin = *min; + *softmax = *max; +} + +static char *rna_MaskLayer_path(PointerRNA *ptr) +{ + return BLI_sprintfN("layers[\"%s\"]", ((MaskLayer *)ptr->data)->name); +} + +static PointerRNA rna_Mask_layer_active_get(PointerRNA *ptr) +{ + Mask *mask = (Mask *)ptr->id.data; + MaskLayer *masklay = BKE_mask_layer_active(mask); + + return rna_pointer_inherit_refine(ptr, &RNA_MaskLayer, masklay); +} + +static void rna_Mask_layer_active_set(PointerRNA *ptr, PointerRNA value) +{ + Mask *mask = (Mask *)ptr->id.data; + MaskLayer *masklay = (MaskLayer *)value.data; + + BKE_mask_layer_active_set(mask, masklay); +} + +static void rna_MaskLayer_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + MaskLayer *masklay = (MaskLayer *)ptr->data; + + rna_iterator_listbase_begin(iter, &masklay->splines, NULL); +} + +void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value) +{ + Mask *mask = (Mask *)ptr->id.data; + MaskLayer *masklay = (MaskLayer *)ptr->data; + + BLI_strncpy(masklay->name, value, sizeof(masklay->name)); + + BKE_mask_layer_unique_name(mask, masklay); +} + +static PointerRNA rna_MaskLayer_active_spline_get(PointerRNA *ptr) +{ + MaskLayer *masklay = (MaskLayer *)ptr->data; + + return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, masklay->act_spline); +} + +static void rna_MaskLayer_active_spline_set(PointerRNA *ptr, PointerRNA value) +{ + MaskLayer *masklay = (MaskLayer *)ptr->data; + MaskSpline *spline = (MaskSpline *)value.data; + int index = BLI_findindex(&masklay->splines, spline); + + if (index >= 0) + masklay->act_spline = spline; + else + masklay->act_spline = NULL; +} + +static PointerRNA rna_MaskLayer_active_spline_point_get(PointerRNA *ptr) +{ + MaskLayer *masklay = (MaskLayer *)ptr->data; + + return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, masklay->act_point); +} + +static void rna_MaskLayer_active_spline_point_set(PointerRNA *ptr, PointerRNA value) +{ + MaskLayer *masklay = (MaskLayer *)ptr->data; + MaskSpline *spline; + MaskSplinePoint *point = (MaskSplinePoint *)value.data; + + masklay->act_point = NULL; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + if (point >= spline->points && point < spline->points + spline->tot_point) { + masklay->act_point = point; + + break; + } + } +} + +static void rna_MaskSplinePoint_handle1_get(PointerRNA *ptr, float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + values[0] = bezt->vec[0][0]; + values[1] = bezt->vec[0][1]; + values[2] = bezt->vec[0][2]; +} + +static void rna_MaskSplinePoint_handle1_set(PointerRNA *ptr, const float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->vec[0][0] = values[0]; + bezt->vec[0][1] = values[1]; + bezt->vec[0][2] = values[2]; +} + +static void rna_MaskSplinePoint_handle2_get(PointerRNA *ptr, float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + values[0] = bezt->vec[2][0]; + values[1] = bezt->vec[2][1]; + values[2] = bezt->vec[2][2]; +} + +static void rna_MaskSplinePoint_handle2_set(PointerRNA *ptr, const float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->vec[2][0] = values[0]; + bezt->vec[2][1] = values[1]; + bezt->vec[2][2] = values[2]; +} + +static void rna_MaskSplinePoint_ctrlpoint_get(PointerRNA *ptr, float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + values[0] = bezt->vec[1][0]; + values[1] = bezt->vec[1][1]; + values[2] = bezt->vec[1][2]; +} + +static void rna_MaskSplinePoint_ctrlpoint_set(PointerRNA *ptr, const float *values) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->vec[1][0] = values[0]; + bezt->vec[1][1] = values[1]; + bezt->vec[1][2] = values[2]; +} + +static int rna_MaskSplinePoint_handle_type_get(PointerRNA *ptr) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + return bezt->h1; +} + +static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value) +{ + MaskSplinePoint *point = (MaskSplinePoint*) ptr->data; + BezTriple *bezt = &point->bezt; + + bezt->h1 = bezt->h2 = value; +} + +/* ** API ** */ + +static MaskLayer *rna_Mask_layer_new(Mask *mask, const char *name) +{ + MaskLayer *masklay = BKE_mask_layer_new(mask, name); + + WM_main_add_notifier(NC_MASK|NA_EDITED, mask); + + return masklay; +} + +void rna_Mask_layer_remove(Mask *mask, MaskLayer *masklay) +{ + BKE_mask_layer_remove(mask, masklay); + + WM_main_add_notifier(NC_MASK|NA_EDITED, mask); +} + +static void rna_MaskLayer_spline_add(ID *id, MaskLayer *masklay, int number) +{ + Mask *mask = (Mask*) id; + int i; + + for (i = 0; i < number; i++) + BKE_mask_spline_add(masklay); + + WM_main_add_notifier(NC_MASK|NA_EDITED, mask); +} + +#else + +static void rna_def_maskParent(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem mask_id_type_items[] = { + {ID_MC, "MOVIECLIP", ICON_SEQUENCE, "Movie Clip", ""}, + {0, NULL, 0, NULL, NULL}}; + + srna = RNA_def_struct(brna, "MaskParent", NULL); + RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for maskign element"); + + /* use_parent */ + prop = RNA_def_property(srna, "use_parent", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_PARENT_ACTIVE); + RNA_def_property_ui_text(prop, "Use Parent", "Use parenting for this layer"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* Target Properties - ID-block to Drive */ + prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ID"); + RNA_def_property_flag(prop, PROP_EDITABLE); + // RNA_def_property_editable_func(prop, "rna_maskSpline_id_editable"); + /* note: custom set function is ONLY to avoid rna setting a user for this. */ + RNA_def_property_pointer_funcs(prop, NULL, "rna_MaskParent_id_set", "rna_MaskParent_id_typef", NULL); + RNA_def_property_ui_text(prop, "ID", "ID-block to which masking element would be parented to or to it's property"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + prop = RNA_def_property(srna, "id_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "id_type"); + RNA_def_property_enum_items(prop, mask_id_type_items); + RNA_def_property_enum_default(prop, ID_MC); + RNA_def_property_enum_funcs(prop, NULL, "rna_MaskParent_id_type_set", NULL); + //RNA_def_property_editable_func(prop, "rna_MaskParent_id_type_editable"); + RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* parent */ + prop = RNA_def_property(srna, "parent", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Parent", "Name of parent object in specified data block to which parenting happens"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* sub_parent */ + prop = RNA_def_property(srna, "sub_parent", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Sub Parent", "Name of parent sub-object in specified data block to which parenting happens"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); +} + +static void rna_def_maskSplinePointUW(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MaskSplinePointUW", NULL); + RNA_def_struct_ui_text(srna, "Mask Spline UW Point", "Single point in spline segment defining feather"); + + /* u */ + prop = RNA_def_property(srna, "u", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "u"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "U", "U coordinate of point along spline segment"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* weight */ + prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "w"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Weight", "Weight of feather point"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* select */ + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); + RNA_def_property_ui_text(prop, "Select", "Selection status"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); +} + +static void rna_def_maskSplinePoint(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem handle_type_items[] = { + {HD_AUTO, "AUTO", 0, "Auto", ""}, + {HD_VECT, "VECTOR", 0, "Vector", ""}, + {HD_ALIGN, "ALIGNED", 0, "Aligned", ""}, + {0, NULL, 0, NULL, NULL}}; + + rna_def_maskSplinePointUW(brna); + + srna = RNA_def_struct(brna, "MaskSplinePoint", NULL); + RNA_def_struct_ui_text(srna, "Mask Spline Point", "Single point in spline used for defining mask"); + + /* Vector values */ + prop = RNA_def_property(srna, "handle_left", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 3); + RNA_def_property_float_funcs(prop, "rna_MaskSplinePoint_handle1_get", "rna_MaskSplinePoint_handle1_set", NULL); + RNA_def_property_ui_text(prop, "Handle 1", "Coordinates of the first handle"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 3); + RNA_def_property_float_funcs(prop, "rna_MaskSplinePoint_ctrlpoint_get", "rna_MaskSplinePoint_ctrlpoint_set", NULL); + RNA_def_property_ui_text(prop, "Control Point", "Coordinates of the control point"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + prop = RNA_def_property(srna, "handle_right", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 3); + RNA_def_property_float_funcs(prop, "rna_MaskSplinePoint_handle2_get", "rna_MaskSplinePoint_handle2_set", NULL); + RNA_def_property_ui_text(prop, "Handle 2", "Coordinates of the second handle"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* handle_type */ + prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, "rna_MaskSplinePoint_handle_type_get", "rna_MaskSplinePoint_handle_type_set", NULL); + RNA_def_property_enum_items(prop, handle_type_items); + RNA_def_property_ui_text(prop, "Handle Type", "Handle type"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* select */ + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "bezt.f1", SELECT); + RNA_def_property_ui_text(prop, "Select", "Selection status"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* parent */ + prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskParent"); + + /* feather points */ + prop = RNA_def_property(srna, "feather_points", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskSplinePointUW"); + RNA_def_property_collection_sdna(prop, NULL, "uw", "tot_uw"); + RNA_def_property_ui_text(prop, "Feather Points", "Points defining feather"); +} + +static void rna_def_mask_splines(BlenderRNA *brna) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MaskSplines", NULL); + RNA_def_struct_sdna(srna, "MaskLayer"); + RNA_def_struct_ui_text(srna, "Mask Splines", "Collection of masking splines"); + + func = RNA_def_function(srna, "add", "rna_MaskLayer_spline_add"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Add a number of splines to mask layer"); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of splines to add to the layer", 0, INT_MAX); + + /* active spline */ + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskSpline"); + RNA_def_property_pointer_funcs(prop, "rna_MaskLayer_active_spline_get", "rna_MaskLayer_active_spline_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking layer"); + + /* active point */ + prop = RNA_def_property(srna, "active_point", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskSplinePoint"); + RNA_def_property_pointer_funcs(prop, "rna_MaskLayer_active_spline_point_get", "rna_MaskLayer_active_spline_point_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Spline", "Active spline of masking layer"); +} + +static void rna_def_maskSpline(BlenderRNA *brna) +{ + static EnumPropertyItem spline_interpolation_items[] = { + {MASK_SPLINE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, + {MASK_SPLINE_INTERP_EASE, "EASE", 0, "Ease", ""}, + {0, NULL, 0, NULL, NULL} + }; + + StructRNA *srna; + PropertyRNA *prop; + + rna_def_maskSplinePoint(brna); + + srna = RNA_def_struct(brna, "MaskSpline", NULL); + RNA_def_struct_ui_text(srna, "Mask spline", "Single spline used for defining mash shape"); + + /* weight interpolation */ + prop = RNA_def_property(srna, "weight_interpolation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "weight_interp"); + RNA_def_property_enum_items(prop, spline_interpolation_items); + RNA_def_property_ui_text(prop, "Weight Interpolation", "The type of weight interpolation for spline"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + + /* cyclic */ + prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_SPLINE_CYCLIC); + RNA_def_property_ui_text(prop, "Cyclic", "Make this spline a closed loop"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); +} + +static void rna_def_mask_layer(BlenderRNA *brna) +{ + static EnumPropertyItem masklay_blend_mode_items[] = { + {MASK_BLEND_ADD, "ADD", 0, "Add", ""}, + {MASK_BLEND_SUBTRACT, "SUBTRACT", 0, "Subtract", ""}, + {0, NULL, 0, NULL, NULL} + }; + + StructRNA *srna; + PropertyRNA *prop; + + rna_def_maskSpline(brna); + rna_def_mask_splines(brna); + + srna = RNA_def_struct(brna, "MaskLayer", NULL); + RNA_def_struct_ui_text(srna, "Mask Layer", "Single layer used for masking pixels"); + RNA_def_struct_path_func(srna, "rna_MaskLayer_path"); + + /* name */ + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Unique name of layer"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MaskLayer_name_set"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + RNA_def_struct_name_property(srna, prop); + + /* splines */ + prop = RNA_def_property(srna, "splines", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_MaskLayer_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MaskSpline"); + RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this layer"); + RNA_def_property_srna(prop, "MaskSplines"); + + /* restrict */ + prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_VIEW); + RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1); + RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_SELECT); + RNA_def_property_ui_text(prop, "Restrict Select", "Restrict selection in the viewport"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1); + RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_RENDER); + RNA_def_property_ui_text(prop, "Restrict Render", "Restrict renderability"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + + /* render settings */ + prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "alpha"); + RNA_def_property_range(prop, 0.0, 1.0f); + RNA_def_property_ui_text(prop, "Opacity", "Render Opacity"); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + + /* weight interpolation */ + prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "blend"); + RNA_def_property_enum_items(prop, masklay_blend_mode_items); + RNA_def_property_ui_text(prop, "Blend", "Method of blending mask layers"); + RNA_def_property_update(prop, 0, "rna_Mask_update_data"); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + + prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MASK_BLENDFLAG_INVERT); + RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); + RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + +} + +static void rna_def_masklayers(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MaskLayers"); + srna = RNA_def_struct(brna, "MaskLayers", NULL); + RNA_def_struct_sdna(srna, "Mask"); + RNA_def_struct_ui_text(srna, "Mask Layers", "Collection of layers used by mask"); + + func = RNA_def_function(srna, "new", "rna_Mask_layer_new"); + RNA_def_function_ui_description(func, "Add layer to this mask"); + RNA_def_string(func, "name", "", 0, "Name", "Name of new layer"); + parm = RNA_def_pointer(func, "layer", "MaskLayer", "", "New mask layer"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Mask_layer_remove"); + RNA_def_function_ui_description(func, "Remove layer from this mask"); + RNA_def_pointer(func, "layer", "MaskLayer", "", "Shape to be removed"); + + /* active layer */ + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MaskLayer"); + RNA_def_property_pointer_funcs(prop, "rna_Mask_layer_active_get", "rna_Mask_layer_active_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Shape", "Active layer in this mask"); +} + +static void rna_def_mask(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + rna_def_mask_layer(brna); + + srna = RNA_def_struct(brna, "Mask", "ID"); + RNA_def_struct_ui_text(srna, "Mask", "Mask datablock defining mask for compositing"); + RNA_def_struct_ui_icon(srna, ICON_MOD_MASK); + + /* mask layers */ + prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_Mask_layers_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MaskLayer"); + RNA_def_property_ui_text(prop, "Layers", "Collection of layers which defines this mask"); + rna_def_masklayers(brna, prop); + + /* active masklay index */ + prop = RNA_def_property(srna, "active_layer_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "masklay_act"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_funcs(prop, "rna_Mask_layer_active_index_get", "rna_Mask_layer_active_index_set", "rna_Mask_layer_active_index_range"); + RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active layer in list of all mask's layers"); + + /* pointers */ + rna_def_animdata_common(srna); +} + +void RNA_def_mask(BlenderRNA *brna) +{ + rna_def_maskParent(brna); + rna_def_mask(brna); +} + +#endif diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c new file mode 100644 index 00000000000..c90c7918660 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -0,0 +1,101 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_mask.c + * \ingroup cmpnodes + */ + +#include "BLF_translation.h" + +#include "DNA_mask_types.h" + +#include "BKE_mask.h" + +#include "node_composite_util.h" + +/* **************** Translate ******************** */ + +static bNodeSocketTemplate cmp_node_mask_in[] = { + { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate cmp_node_mask_out[] = { + { SOCK_RGBA, 0, "Image"}, + { -1, 0, "" } +}; + +static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + if (node->id) { + Mask *mask = (Mask *)node->id; + CompBuf *stackbuf; + RenderData *rd = data; + float *res; + int sx, sy; + + if (!out[0]->hasoutput) { + /* the node's output socket is not connected to anything... + * do not execute any further, just exit the node immediately + */ + return; + } + + if (in[0]->hasinput && in[0]->data) { + CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); + + sx = cbuf->x; + sy = cbuf->y; + } + else { + sx = (rd->size * rd->xsch) / 100; + sy = (rd->size * rd->ysch) / 100; + } + + /* allocate the output buffer */ + stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); + res = stackbuf->rect; + + BKE_mask_rasterize(mask, sx, sy, res); + + /* pass on output and free */ + out[0]->data = stackbuf; + } +} + +void register_node_type_cmp_mask(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_mask_in, cmp_node_mask_out); + node_type_size(&ntype, 140, 100, 320); + node_type_exec(&ntype, exec); + + nodeRegisterType(ttype, &ntype); +} -- cgit v1.2.3 From 874308ba5e5636502e7b9a8223f59e2ac2e3338c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 Jun 2012 16:09:51 +0000 Subject: Cycles: show frame number in render info. --- source/blender/editors/render/render_internal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 356ede878b5..8fa3c6f992f 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -288,11 +288,12 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str) else if (scene->r.scemode & R_SINGLE_LAYER) spos += sprintf(spos, "Single Layer | "); + spos += sprintf(spos, "Frame:%d ", (scene->r.cfra)); + if (rs->statstr) { - spos += sprintf(spos, "%s ", rs->statstr); + spos += sprintf(spos, "| %s ", rs->statstr); } else { - spos += sprintf(spos, "Fra:%d ", (scene->r.cfra)); if (rs->totvert) spos += sprintf(spos, "Ve:%d ", rs->totvert); if (rs->totface) spos += sprintf(spos, "Fa:%d ", rs->totface); if (rs->tothalo) spos += sprintf(spos, "Ha:%d ", rs->tothalo); -- cgit v1.2.3 From eae64f9a0cb2ec52b1b30aef39d819317dae43b6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 Jun 2012 16:10:20 +0000 Subject: Antoher fix for library linking issues, must change all entries in the libmap, not just the first one. --- source/blender/blenloader/intern/readfile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8e9394a886e..e41e9ba18a1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1209,7 +1209,6 @@ static void change_idid_adr_fd(FileData *fd, void *old, void *new) if (old==entry->newp && entry->nr==ID_ID) { entry->newp = new; if (new) entry->nr = GS( ((ID *)new)->name ); - break; } } } -- cgit v1.2.3 From 2230f3346e8a7ac2191690627856a1a8745bd8e9 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 4 Jun 2012 16:30:15 +0000 Subject: Cycles / OSL: * Compile option to build with OSL, disabled by default. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29a255d6c67..f50ef91c978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -236,6 +236,7 @@ endif() # Cycles option(WITH_CYCLES "Enable cycles Render Engine" ON) option(WITH_CYCLES_TEST "Build cycles test application" OFF) +option(WITH_CYCLES_OSL "Build Cycles with OSL support" OFF) option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF) set(CYCLES_CUDA_BINARIES_ARCH sm_13 sm_20 sm_21 CACHE STRING "CUDA architectures to build binaries for") mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) -- cgit v1.2.3 From 68a9dd54ec909d8e56da0da487c6ec3559551edd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 16:42:58 +0000 Subject: mask mode for clip editor developed by Sergey Sharybin, Pete Larabell and myself. see: http://wiki.blender.org/index.php/User:Nazg-gul/MaskEditor note - mask editing tools need continued development, feather option is not working 100% --- intern/CMakeLists.txt | 1 + intern/SConscript | 3 +- .../scripts/modules/bpy_extras/keyconfig_utils.py | 1 + release/scripts/startup/bl_ui/space_clip.py | 275 ++++++++++++++++++++- source/blender/CMakeLists.txt | 1 + source/blender/blenkernel/BKE_context.h | 1 + source/blender/blenkernel/BKE_library.h | 2 +- source/blender/blenkernel/BKE_main.h | 1 + source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/CMakeLists.txt | 3 + source/blender/blenkernel/SConscript | 1 + source/blender/blenkernel/intern/anim_sys.c | 12 +- source/blender/blenkernel/intern/context.c | 5 + source/blender/blenkernel/intern/depsgraph.c | 12 + source/blender/blenkernel/intern/idcode.c | 1 + source/blender/blenkernel/intern/library.c | 11 + source/blender/blenkernel/intern/node.c | 2 + source/blender/blenkernel/intern/scene.c | 6 + source/blender/blenloader/intern/readfile.c | 125 +++++++++- source/blender/blenloader/intern/writefile.c | 55 +++++ source/blender/compositor/CMakeLists.txt | 5 + source/blender/compositor/intern/COM_Converter.cpp | 4 + source/blender/editors/CMakeLists.txt | 1 + source/blender/editors/SConscript | 1 + source/blender/editors/animation/keyframes_draw.c | 68 +++++ source/blender/editors/include/ED_clip.h | 10 + source/blender/editors/include/ED_keyframes_draw.h | 4 + source/blender/editors/include/ED_object.h | 1 + source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/include/ED_transform.h | 1 + .../editors/interface/interface_templates.c | 20 +- source/blender/editors/object/object_ops.c | 8 + source/blender/editors/screen/screen_ops.c | 22 +- source/blender/editors/space_api/spacetypes.c | 4 + source/blender/editors/space_clip/clip_draw.c | 28 +++ source/blender/editors/space_clip/clip_editor.c | 127 ++++++++++ source/blender/editors/space_clip/space_clip.c | 100 +++++++- source/blender/editors/space_node/drawnode.c | 9 +- source/blender/editors/space_node/space_node.c | 7 + source/blender/editors/transform/transform.c | 96 +++++-- source/blender/editors/transform/transform.h | 1 + .../editors/transform/transform_conversions.c | 230 +++++++++++++++++ .../blender/editors/transform/transform_generics.c | 66 +++-- source/blender/makesdna/DNA_ID.h | 1 + source/blender/makesdna/DNA_scene_types.h | 3 +- source/blender/makesdna/DNA_space_types.h | 11 +- source/blender/makesdna/intern/makesdna.c | 2 + source/blender/makesrna/RNA_access.h | 3 + source/blender/makesrna/intern/CMakeLists.txt | 1 + source/blender/makesrna/intern/makesrna.c | 1 + source/blender/makesrna/intern/rna_ID.c | 2 + source/blender/makesrna/intern/rna_internal.h | 2 + source/blender/makesrna/intern/rna_main.c | 7 + source/blender/makesrna/intern/rna_main_api.c | 51 ++++ source/blender/makesrna/intern/rna_nodetree.c | 12 + .../blender/makesrna/intern/rna_nodetree_types.h | 1 + source/blender/makesrna/intern/rna_scene.c | 6 + source/blender/makesrna/intern/rna_space.c | 63 ++++- source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_composite.h | 2 + .../blender/nodes/composite/node_composite_tree.c | 4 + .../blender/nodes/composite/node_composite_util.c | 16 ++ .../blender/nodes/composite/node_composite_util.h | 1 + source/blender/windowmanager/WM_types.h | 1 + source/blender/windowmanager/intern/wm_operators.c | 2 + source/blenderplayer/CMakeLists.txt | 1 + source/blenderplayer/bad_level_call_stubs/stubs.c | 1 + source/creator/CMakeLists.txt | 2 + 68 files changed, 1448 insertions(+), 82 deletions(-) diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index c85f0fddc34..71d2ef5e410 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(memutil) add_subdirectory(iksolver) add_subdirectory(opennl) add_subdirectory(mikktspace) +add_subdirectory(raskter) if(WITH_AUDASPACE) add_subdirectory(audaspace) diff --git a/intern/SConscript b/intern/SConscript index a1e7f840800..3bfdc2c4ca7 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -14,7 +14,8 @@ SConscript(['audaspace/SConscript', 'boolop/SConscript', 'opennl/SConscript', 'mikktspace/SConscript', - 'smoke/SConscript']) + 'smoke/SConscript', + 'raskter/SConscript']) if env ['WITH_BF_REMESH']: SConscript(['dualcon/SConscript']) diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py index e652b8461b2..287cd81eff2 100644 --- a/release/scripts/modules/bpy_extras/keyconfig_utils.py +++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py @@ -95,6 +95,7 @@ KM_HIERARCHY = [ ('Clip', 'CLIP_EDITOR', 'WINDOW', [ ('Clip Editor', 'CLIP_EDITOR', 'WINDOW', []), ('Clip Graph Editor', 'CLIP_EDITOR', 'WINDOW', []), + ('Mask Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image ]), ('View3D Gesture Circle', 'EMPTY', 'WINDOW', []), diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 4ab23359fd8..988cd92a2eb 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -44,15 +44,29 @@ class CLIP_HT_header(Header): sub.menu("CLIP_MT_clip") - sub.menu("CLIP_MT_track") - sub.menu("CLIP_MT_reconstruction") + if clip: + if sc.mode == 'MASKEDITING': + sub.menu("CLIP_MT_mask") + else: + sub.menu("CLIP_MT_track") + sub.menu("CLIP_MT_reconstruction") - layout.prop(sc, "view", text="", expand=True) + if sc.mode != 'MASKEDITING': + layout.prop(sc, "view", text="", expand=True) if clip: if sc.view == 'CLIP': layout.prop(sc, "mode", text="") - if sc.view == 'GRAPH': + layout.prop(sc, "pivot_point", text="", icon_only=True) + + if sc.mode == 'MASKEDITING': + toolsettings = context.tool_settings + + row = layout.row(align=True) + row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True) + if toolsettings.use_proportional_edit_objects: + row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) + elif sc.view == 'GRAPH': row = layout.row(align=True) if sc.show_filters: @@ -71,6 +85,10 @@ class CLIP_HT_header(Header): row = layout.row() row.template_ID(sc, "clip", open='clip.open') + if sc.mode == 'MASKEDITING': + row = layout.row() + row.template_ID(sc, "mask", new="mask.new") + if clip: tracking = clip.tracking active = tracking.objects.active @@ -102,6 +120,16 @@ class CLIP_PT_clip_view_panel: return clip and sc.view == 'CLIP' +class CLIP_PT_mask_view_panel: + + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + return clip and sc.view == 'CLIP' and sc.mode == 'MASKEDITING' + + class CLIP_PT_tracking_panel: @classmethod @@ -359,11 +387,52 @@ class CLIP_PT_tools_object(CLIP_PT_reconstruction_panel, Panel): col.prop(settings, "object_distance") -class CLIP_PT_tools_grease_pencil(CLIP_PT_distortion_panel, Panel): +class CLIP_PT_tools_mask(CLIP_PT_mask_view_panel, Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'TOOLS' + bl_label = "Mask Tools" + + def draw(self, context): + layout = self.layout + + col = layout.column(align=True) + col.label(text="Transform:") + col.operator("transform.translate") + col.operator("transform.rotate") + col.operator("transform.resize", text="Scale") + + col = layout.column(align=True) + col.label(text="Spline:") + col.operator("mask.delete") + col.operator("mask.cyclic_toggle") + col.operator("mask.switch_direction") + + col = layout.column(align=True) + col.label(text="Parenting:") + col.operator("mask.parent_set") + col.operator("mask.parent_clear") + + +class CLIP_PT_tools_grease_pencil(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' bl_label = "Grease Pencil" + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + if not clip: + return False + + if sc.mode == 'DISTORTION': + return sc.view == 'CLIP' + elif sc.mode == 'MASKEDITING': + return True + + return False + def draw(self, context): layout = self.layout @@ -550,6 +619,119 @@ class CLIP_PT_tracking_camera(Panel): col.prop(clip.tracking.camera, "k3") +class CLIP_PT_mask_objects(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Mask Layers" + + @classmethod + def poll(cls, context): + sc = context.space_data + + return sc.mask and sc.mode == 'MASKEDITING' + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + + row = layout.row() + row.template_list(mask, "layers", + mask, "active_layer_index", rows=3) + + sub = row.column(align=True) + + sub.operator("mask.layer_new", icon='ZOOMIN', text="") + sub.operator("mask.layer_remove", icon='ZOOMOUT', text="") + + active = mask.layers.active + if active: + layout.prop(active, "name") + + # blending + row = layout.row(align=True) + row.prop(active, "alpha") + row.prop(active, "invert", text="", icon='IMAGE_ALPHA') + + layout.prop(active, "blend") + + +class CLIP_PT_active_mask_spline(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Active Spline" + + @classmethod + def poll(cls, context): + sc = context.space_data + mask = sc.mask + + if mask and sc.mode == 'MASKEDITING': + return mask.layers.active and mask.layers.active.splines.active + + return False + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + spline = mask.layers.active.splines.active + + col = layout.column() + col.prop(spline, "weight_interpolation") + col.prop(spline, "use_cyclic") + + +class CLIP_PT_active_mask_point(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Active Point" + + @classmethod + def poll(cls, context): + sc = context.space_data + mask = sc.mask + + if mask and sc.mode == 'MASKEDITING': + return mask.layers.active and mask.layers.active.splines.active_point + + return False + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + point = mask.layers.active.splines.active_point + parent = point.parent + + col = layout.column() + col.prop(point, "handle_type") + + col = layout.column() + col.prop(parent, "use_parent", text="Parent") + if parent.use_parent: + # Currently only parenting yo movie clip is allowed, so do not + # ver-oplicate things for now and use single template_ID + #col.template_any_ID(parent, "id", "id_type", text="") + + col.template_ID(parent, "id") + + if parent.id_type == 'MOVIECLIP' and parent.id: + clip = parent.id + tracking = clip.tracking + + col.prop_search(parent, "parent", tracking, "objects", icon='OBJECT_DATA', text="Object:") + + if parent.parent and parent.parent in tracking.objects: + object = clip.tracking.objects[parent.parent] + col.prop_search(parent, "sub_parent", object, "tracks", icon='ANIM_DATA', text="Track:") + else: + col.prop_search(parent, "sub_parent", clip.tracking, "tracks", icon='ANIM_DATA', text="Track:") + + class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' @@ -594,12 +776,23 @@ class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): row = col.row() row.prop(clip, "display_aspect", text="") + if sc.mode == 'MASKEDITING': + col = layout.column() + col.prop(sc, "mask_draw_type", text="") + col.prop(sc, "show_mask_smooth") + class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Marker Display" + @classmethod + def poll(cls, context): + sc = context.space_data + + return sc.mode != 'MASKEDITING' + def draw(self, context): layout = self.layout sc = context.space_data @@ -763,6 +956,7 @@ class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): layout.operator("clip.open", icon='FILESEL') + class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' @@ -942,16 +1136,26 @@ class CLIP_MT_select(Menu): def draw(self, context): layout = self.layout + sc = context.space_data - layout.operator("clip.select_border") - layout.operator("clip.select_circle") + if sc.mode == 'MASKEDITING': + layout.operator("mask.select_border") + layout.operator("mask.select_circle") - layout.separator() + layout.separator() + + layout.operator("mask.select_all").action = 'TOGGLE' + layout.operator("mask.select_all", text="Inverse").action = 'INVERT' + else: + layout.operator("clip.select_border") + layout.operator("clip.select_circle") + + layout.separator() - layout.operator("clip.select_all").action = 'TOGGLE' - layout.operator("clip.select_all", text="Inverse").action = 'INVERT' + layout.operator("clip.select_all").action = 'TOGGLE' + layout.operator("clip.select_all", text="Inverse").action = 'INVERT' - layout.menu("CLIP_MT_select_grouped") + layout.menu("CLIP_MT_select_grouped") class CLIP_MT_select_grouped(Menu): @@ -995,6 +1199,55 @@ class CLIP_MT_tracking_specials(Menu): props.action = 'UNLOCK' +class CLIP_MT_mask(Menu): + bl_label = "Mask" + + def draw(self, context): + layout = self.layout + + layout.operator("mask.delete") + + layout.separator() + layout.operator("mask.cyclic_toggle") + layout.operator("mask.switch_direction") + + layout.separator() + layout.operator("mask.parent_clear") + layout.operator("mask.parent_set") + + layout.separator() + layout.operator("mask.shape_key_clear") + layout.operator("mask.shape_key_insert") + + layout.separator() + layout.menu("CLIP_MT_mask_visibility") + layout.menu("CLIP_MT_mask_transform") + + +class CLIP_MT_mask_visibility(Menu): + bl_label = "Show/Hide" + + def draw(self, context): + layout = self.layout + + layout.operator("mask.hide_view_clear", text="Show Hidden") + layout.operator("mask.hide_view_set", text="Hide Selected") + + props = layout.operator("mask.hide_view_set", text="Hide Unselected") + props.unselected = True + + +class CLIP_MT_mask_transform(Menu): + bl_label = "Transform" + + def draw(self, context): + layout = self.layout + + layout.operator("transform.translate") + layout.operator("transform.rotate") + layout.operator("transform.resize") + + class CLIP_MT_camera_presets(Menu): """Predefined tracking camera intrinsics""" bl_label = "Camera Presets" diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index ed1308d41ba..a0d840b5de6 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -86,6 +86,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_movieclip_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_tracking_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_mask_types.h ) add_subdirectory(editors) diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 23df246b430..7a1172335d8 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -260,6 +260,7 @@ struct Image *CTX_data_edit_image(const bContext *C); struct Text *CTX_data_edit_text(const bContext *C); struct MovieClip *CTX_data_edit_movieclip(const bContext *C); +struct Mask *CTX_data_edit_mask(const bContext *C); int CTX_data_selected_nodes(const bContext *C, ListBase *list); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 3a19d6c9007..3248944dae8 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -66,7 +66,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id); struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 40 +#define MAX_LIBARRAY 41 int set_listbasepointers(struct Main *main, struct ListBase **lb); void BKE_libblock_free(struct ListBase *lb, void *idv); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 09c91a59ac5..3074e1c0e63 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -86,6 +86,7 @@ typedef struct Main { ListBase wm; ListBase gpencil; ListBase movieclip; + ListBase mask; char id_tag_update[256]; } Main; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d093c9108b6..b9d0076c7c8 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -658,6 +658,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); #define CMP_NODE_MOVIEDISTORTION 265 #define CMP_NODE_DOUBLEEDGEMASK 266 #define CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED 267 /* DEPRECATED multi file node has been merged into regular CMP_NODE_OUTPUT_FILE */ +#define CMP_NODE_MASK 268 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index d207a08c6cb..056a6bf5866 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -43,6 +43,7 @@ set(INC ../../../intern/memutil ../../../intern/mikktspace ../../../intern/opennl/extern + ../../../intern/raskter # XXX - BAD LEVEL CALL WM_api.h ../windowmanager @@ -100,6 +101,7 @@ set(SRC intern/lamp.c intern/lattice.c intern/library.c + intern/mask.c intern/material.c intern/mball.c intern/mesh.c @@ -187,6 +189,7 @@ set(SRC BKE_lamp.h BKE_lattice.h BKE_library.h + BKE_mask.h BKE_main.h BKE_material.h BKE_mball.h diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index ee9e6bc7739..64544adb26d 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -17,6 +17,7 @@ incs += ' #/intern/smoke/extern' incs += ' #/intern/mikktspace' incs += ' #/intern/audaspace/intern' incs += ' #/intern/ffmpeg' +incs += ' #/intern/raskter' incs += ' ' + env['BF_OPENGL_INC'] incs += ' ' + env['BF_ZLIB_INC'] diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 1358c2e34a8..7fc80529753 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -90,6 +90,7 @@ short id_type_can_have_animdata(ID *id) case ID_SPK: case ID_SCE: case ID_MC: + case ID_MSK: { return 1; } @@ -802,10 +803,13 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u /* objects */ ANIMDATA_IDS_CB(mainptr->object.first); + + /* masks */ + ANIMDATA_IDS_CB(mainptr->mask.first); /* worlds */ ANIMDATA_IDS_CB(mainptr->world.first); - + /* scenes */ ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); } @@ -886,6 +890,9 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha /* objects */ RENAMEFIX_ANIM_IDS(mainptr->object.first); + + /* masks */ + RENAMEFIX_ANIM_IDS(mainptr->mask.first); /* worlds */ RENAMEFIX_ANIM_IDS(mainptr->world.first); @@ -2350,6 +2357,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) * linked from other (not-visible) scenes will not need their data calculated. */ EVAL_ANIM_IDS(main->object.first, 0); + + /* masks */ + EVAL_ANIM_IDS(main->mask.first, ADT_RECALC_ANIM); /* worlds */ EVAL_ANIM_NODETREE_IDS(main->world.first, World, ADT_RECALC_ANIM); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 3c8f29d8440..ff2dd27e0c9 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -973,6 +973,11 @@ struct MovieClip *CTX_data_edit_movieclip(const bContext *C) return ctx_data_pointer_get(C, "edit_movieclip"); } +struct Mask *CTX_data_edit_mask(const bContext *C) +{ + return ctx_data_pointer_get(C, "edit_mask"); +} + struct EditBone *CTX_data_active_bone(const bContext *C) { return ctx_data_pointer_get(C, "active_bone"); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index a6ce5daf247..53bc9c4cb7e 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2611,6 +2611,18 @@ static void dag_id_flush_update(Scene *sce, ID *id) } } + if (idtype == ID_MSK) { + if (sce->nodetree) { + bNode *node; + + for (node = sce->nodetree->nodes.first; node; node = node->next) { + if (node->id == id) { + nodeUpdate(sce->nodetree, node); + } + } + } + } + /* camera's matrix is used to orient reconstructed stuff, * so it should happen tracking-related constraints recalculation * when camera is changing (sergey) */ diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index ca10f39246c..30427a81c4b 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -79,6 +79,7 @@ static IDType idtypes[] = { { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, { ID_WM, "WindowManager", "window_managers", 0}, { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, }; static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index de67119d850..0abeb483745 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -66,6 +66,7 @@ #include "DNA_world_types.h" #include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" @@ -108,6 +109,7 @@ #include "BKE_speaker.h" #include "BKE_utildefines.h" #include "BKE_movieclip.h" +#include "BKE_mask.h" #include "RNA_access.h" @@ -486,6 +488,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->gpencil); case ID_MC: return &(mainlib->movieclip); + case ID_MSK: + return &(mainlib->mask); } return NULL; } @@ -569,6 +573,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++] = &(main->library); lb[a++] = &(main->wm); lb[a++] = &(main->movieclip); + lb[a++] = &(main->mask); lb[a] = NULL; @@ -680,6 +685,9 @@ static ID *alloc_libblock_notest(short type) case ID_MC: id = MEM_callocN(sizeof(MovieClip), "Movie Clip"); break; + case ID_MSK: + id = MEM_callocN(sizeof(Mask), "Mask"); + break; } return id; } @@ -888,6 +896,9 @@ void BKE_libblock_free(ListBase *lb, void *idv) case ID_MC: BKE_movieclip_free((MovieClip *)id); break; + case ID_MSK: + BKE_mask_free((Mask *)id); + break; } if (id->properties) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 22286e57c0a..86a1f715c3c 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1910,6 +1910,8 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_bokehimage(ttype); register_node_type_cmp_bokehblur(ttype); register_node_type_cmp_switch(ttype); + + register_node_type_cmp_mask(ttype); } static void registerShaderNodes(bNodeTreeType *ttype) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 62d5459336b..d9f1a6372ee 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -63,6 +63,7 @@ #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_mask.h" #include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -1004,6 +1005,9 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen /* update sound system animation */ sound_update_scene(scene); + + /* update masking curves */ + BKE_mask_update_scene(bmain, scene, FALSE); } /* this is called in main loop, doing tagged updates before redraw */ @@ -1074,6 +1078,8 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * so don't call within 'scene_update_tagged_recursive' */ DAG_scene_update_flags(bmain, sce, lay, TRUE); // only stuff that moves or needs display still + BKE_mask_evaluate_all_masks(bmain, ctime, TRUE); + /* 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 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e41e9ba18a1..826d9d196b8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -95,6 +95,7 @@ #include "DNA_vfont_types.h" #include "DNA_world_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" @@ -5353,9 +5354,10 @@ static void lib_link_screen(FileData *fd, Main *main) } else if (sl->spacetype == SPACE_CLIP) { SpaceClip *sclip = (SpaceClip *)sl; - + sclip->clip = newlibadr_us(fd, sc->id.lib, sclip->clip); - + sclip->mask = newlibadr_us(fd, sc->id.lib, sclip->mask); + sclip->scopes.track_preview = NULL; sclip->draw_context = NULL; sclip->scopes.ok = 0; @@ -5616,9 +5618,10 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) } else if (sl->spacetype == SPACE_CLIP) { SpaceClip *sclip = (SpaceClip *)sl; - + sclip->clip = restore_pointer_by_name(newmain, (ID *)sclip->clip, 1); - + sclip->mask = restore_pointer_by_name(newmain, (ID *)sclip->mask, 1); + sclip->scopes.ok = 0; } } @@ -6173,6 +6176,88 @@ static void lib_link_movieclip(FileData *fd, Main *main) } } +/* ***************** READ MOVIECLIP *************** */ + +static void direct_link_mask(FileData *fd, Mask *mask) +{ + MaskLayer *masklay; + + mask->adt = newdataadr(fd, mask->adt); + + link_list(fd, &mask->masklayers); + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + MaskLayerShape *masklay_shape; + + link_list(fd, &masklay->splines); + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + spline->points = newdataadr(fd, spline->points); + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (point->tot_uw) + point->uw = newdataadr(fd, point->uw); + } + } + + link_list(fd, &masklay->splines_shapes); + + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + masklay_shape->data = newdataadr(fd, masklay_shape->data); + } + + masklay->act_spline = newdataadr(fd, masklay->act_spline); + masklay->act_point = newdataadr(fd, masklay->act_point); + } +} + +static void lib_link_mask_parent(FileData *fd, Mask *mask, MaskParent *parent) +{ + parent->id = newlibadr_us(fd, mask->id.lib, parent->id); +} + +static void lib_link_mask(FileData *fd, Main *main) +{ + Mask *mask; + + mask = main->mask.first; + while (mask) { + if(mask->id.flag & LIB_NEEDLINK) { + MaskLayer *masklay; + + if (mask->adt) + lib_link_animdata(fd, &mask->id, mask->adt); + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + spline = masklay->splines.first; + while (spline) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + lib_link_mask_parent(fd, mask, &point->parent); + } + + lib_link_mask_parent(fd, mask, &spline->parent); + + spline = spline->next; + } + } + + mask->id.flag -= LIB_NEEDLINK; + } + mask = mask->id.next; + } +} + /* ************** GENERAL & MAIN ******************** */ @@ -6378,6 +6463,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID case ID_MC: direct_link_movieclip(fd, (MovieClip *)id); break; + case ID_MSK: + direct_link_mask(fd, (Mask *)id); + break; } /*link direct data of ID properties*/ @@ -7506,7 +7594,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } - + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 8)) { /* set new deactivation values for game settings */ @@ -7533,7 +7621,29 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } - + + { + bScreen *sc; + + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + + if (sclip->around == 0) { + sclip->around = V3D_CENTROID; + } + } + } + } + } + } + /* don't forget to set version number in blender.c! */ } @@ -7576,7 +7686,8 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_brush(fd, main); lib_link_particlesettings(fd, main); lib_link_movieclip(fd, main); - + lib_link_mask(fd, main); + lib_link_mesh(fd, main); /* as last: tpage images with users at zero */ lib_link_library(fd, main); /* only init users */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 4f75e8e5fbf..655adf97b04 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -133,6 +133,7 @@ Any case: direct data is ALWAYS after the lib block #include "DNA_world_types.h" #include "DNA_windowmanager_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" // MEM_freeN #include "BLI_bitmap.h" @@ -2752,6 +2753,59 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) mywrite(wd, MYWRITE_FLUSH, 0); } +static void write_masks(WriteData *wd, ListBase *idbase) +{ + Mask *mask; + + mask = idbase->first; + while (mask) { + if (mask->id.us > 0 || wd->current) { + MaskLayer *masklay; + + writestruct(wd, ID_MSK, "Mask", 1, mask); + + if (mask->adt) + write_animdata(wd, mask->adt); + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + MaskLayerShape *masklay_shape; + + writestruct(wd, DATA, "MaskLayer", 1, masklay); + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + void *points_deform = spline->points_deform; + spline->points_deform = NULL; + + writestruct(wd, DATA, "MaskSpline", 1, spline); + writestruct(wd, DATA, "MaskSplinePoint", spline->tot_point, spline->points); + + spline->points_deform = points_deform; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (point->tot_uw) + writestruct(wd, DATA, "MaskSplinePointUW", point->tot_uw, point->uw); + } + } + + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + writestruct(wd, DATA, "MaskLayerShape", 1, masklay_shape); + writedata(wd, DATA, masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, masklay_shape->data); + } + } + } + + mask = mask->id.next; + } + + /* flush helps the compression for undo-save */ + mywrite(wd, MYWRITE_FLUSH, 0); +} + /* context is usually defined by WM, two cases where no WM is available: * - for forward compatibility, curscreen has to be saved * - for undofile, curscene needs to be saved */ @@ -2836,6 +2890,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_screens (wd, &mainvar->screen); } write_movieclips (wd, &mainvar->movieclip); + write_masks (wd, &mainvar->mask); write_scenes (wd, &mainvar->scene); write_curves (wd, &mainvar->curve); write_mballs (wd, &mainvar->mball); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index dc28328e867..27bf7df8142 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -129,6 +129,8 @@ set(SRC nodes/COM_MovieClipNode.h nodes/COM_OutputFileNode.cpp nodes/COM_OutputFileNode.h + nodes/COM_MaskNode.cpp + nodes/COM_MaskNode.h # output nodes nodes/COM_CompositorNode.cpp @@ -594,6 +596,9 @@ operations/COM_ConvertDepthToRadiusOperation.cpp operations/COM_AntiAliasOperation.cpp operations/COM_AntiAliasOperation.h + + operations/COM_MaskOperation.cpp + operations/COM_MaskOperation.h ) blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 3cb297801ca..dc6409e7b86 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -111,6 +111,7 @@ #include "COM_DefocusNode.h" #include "COM_DoubleEdgeMaskNode.h" #include "COM_CropNode.h" +#include "COM_MaskNode.h" Node *Converter::convert(bNode *bNode) { @@ -347,6 +348,9 @@ case CMP_NODE_OUTPUT_FILE: case CMP_NODE_CROP: node = new CropNode(bNode); break; + case CMP_NODE_MASK: + node = new MaskNode(bNode); + break; /* not inplemented yet */ default: node = new MuteNode(bNode); diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 088376b20ef..67ed77bcc4b 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -24,6 +24,7 @@ if(WITH_BLENDER) add_subdirectory(curve) add_subdirectory(gpencil) add_subdirectory(interface) + add_subdirectory(mask) add_subdirectory(mesh) add_subdirectory(metaball) add_subdirectory(object) diff --git a/source/blender/editors/SConscript b/source/blender/editors/SConscript index ed66a76a324..d08b496f0ef 100644 --- a/source/blender/editors/SConscript +++ b/source/blender/editors/SConscript @@ -8,6 +8,7 @@ SConscript(['datafiles/SConscript', 'interface/SConscript', 'animation/SConscript', 'armature/SConscript', + 'mask/SConscript', 'mesh/SConscript', 'metaball/SConscript', 'object/SConscript', diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index cb7dc7ac206..cee8d15a807 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -60,6 +60,7 @@ #include "DNA_speaker_types.h" #include "DNA_world_types.h" #include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" #include "BKE_key.h" #include "BKE_material.h" @@ -184,6 +185,50 @@ static void nupdate_ak_gpframe(void *node, void *data) ak->modified += 1; } +/* ......... */ + +/* Comparator callback used for ActKeyColumns and GPencil frame */ +static short compare_ak_masklayshape(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; + + if (masklay_shape->frame < ak->cfra) + return -1; + else if (masklay_shape->frame > ak->cfra) + return 1; + else + return 0; +} + +/* New node callback used for building ActKeyColumns from GPencil frames */ +static DLRBT_Node *nalloc_ak_masklayshape(void *data) +{ + ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; + + /* store settings based on state of BezTriple */ + ak->cfra = masklay_shape->frame; + ak->sel = (masklay_shape->flag & SELECT) ? SELECT : 0; + + /* set 'modified', since this is used to identify long keyframes */ + ak->modified = 1; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from GPencil frames */ +static void nupdate_ak_masklayshape(void *node, void *data) +{ + ActKeyColumn *ak = (ActKeyColumn *)node; + MaskLayerShape *masklay_shape = (MaskLayerShape *)data; + + /* set selection status and 'touched' status */ + if (masklay_shape->flag & SELECT) ak->sel = SELECT; + ak->modified += 1; +} + + /* --------------- */ /* Add the given BezTriple to the given 'list' of Keyframes */ @@ -204,6 +249,15 @@ static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); } +/* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */ +static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape) +{ + if (ELEM(NULL, keys, masklay_shape)) + return; + else + BLI_dlrbTree_add(keys, compare_ak_masklayshape, nalloc_ak_masklayshape, nupdate_ak_masklayshape, masklay_shape); +} + /* ActBeztColumns (Helpers for Long Keyframes) ------------------------------ */ /* maximum size of default buffer for BezTriple columns */ @@ -940,3 +994,17 @@ void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) } } +void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys) +{ + MaskLayerShape *masklay_shape; + + if (masklay && keys) { + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + add_masklay_to_keycolumns_list(keys, masklay_shape); + } + } +} + diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 7943a17c377..7e1505b652f 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -36,6 +36,7 @@ struct bContext; struct bScreen; struct ImBuf; struct Main; +struct Mask; struct MovieClip; struct SpaceClip; struct wmEvent; @@ -48,12 +49,19 @@ int ED_space_clip_view_clip_poll(struct bContext *C); int ED_space_clip_tracking_poll(struct bContext *C); int ED_space_clip_tracking_size_poll(struct bContext *C); int ED_space_clip_tracking_frame_poll(struct bContext *C); +int ED_space_clip_maskediting_poll(struct bContext *C); +int ED_space_clip_maskediting_mask_poll(bContext *C); void ED_space_clip_set(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip); struct MovieClip *ED_space_clip(struct SpaceClip *sc); +struct Mask *ED_space_clip_mask(struct SpaceClip *sc); void ED_space_clip_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy); void ED_space_clip_aspect(struct SpaceClip *sc, float *aspx, float *aspy); +void ED_space_clip_aspect_dimension_aware(struct SpaceClip *sc, float *aspx, float *aspy); + +void ED_space_clip_mask_size(struct SpaceClip *sc, int *width, int *height); +void ED_space_clip_mask_aspect(struct SpaceClip *sc, float *aspx, float *aspy); struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc); struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle); @@ -72,6 +80,8 @@ void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc); void ED_space_clip_free_texture_buffer(struct SpaceClip *sc); int ED_space_clip_show_trackedit(struct SpaceClip *sc); +int ED_space_clip_show_maskedit(struct SpaceClip *sc); +void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask); /* clip_ops.c */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index cd64427de78..e24c21bc133 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -42,6 +42,7 @@ struct bActionGroup; struct Object; struct ListBase; struct bGPDlayer; +struct MaskLayer; struct Scene; struct View2D; struct DLRBT_Tree; @@ -139,6 +140,9 @@ void summary_to_keylist(struct bAnimContext *ac, struct DLRBT_Tree *keys, struct /* Grease Pencil Layer */ // XXX not restored void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys); +/* Mask */ +// XXX not restored +void mask_to_keylist(struct bDopeSheet *UNUSED(ads), struct MaskLayer *masklay, struct DLRBT_Tree *keys); /* ActKeyColumn API ---------------- */ /* Comparator callback used for ActKeyColumns and cframe float-value pointer */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 8dc83df2977..9c10a270ef8 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -90,6 +90,7 @@ struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob); void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); +void ED_keymap_proportional_maskmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap); void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, const short do_connected); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 464f2db30a2..4faf82eec36 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -170,6 +170,7 @@ int ED_operator_editmball(struct bContext *C); int ED_operator_uvedit(struct bContext *C); int ED_operator_uvmap(struct bContext *C); int ED_operator_posemode(struct bContext *C); +int ED_operator_mask(struct bContext *C); /* default keymaps, bitflags */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 3bef1f56655..d867532b273 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -96,6 +96,7 @@ enum { #define CTX_BMESH 64 #define CTX_NDOF 128 #define CTX_MOVIECLIP 256 +#define CTX_MASK 512 /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 59ef0c00283..daba096696c 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -579,8 +579,10 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co row = uiLayoutRow(layout, 1); /* Label - either use the provided text, or will become "ID-Block:" */ - if (text) - uiItemL(row, text, ICON_NONE); + if (text) { + if (text[0]) + uiItemL(row, text, ICON_NONE); + } else uiItemL(row, "ID-Block:", ICON_NONE); @@ -2239,6 +2241,20 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiItemL(split, name, ICON_OBJECT_DATA); } } + else if (itemptr->type == &RNA_MaskLayer) { + split = uiLayoutSplit(sub, 0.66f, 0); + + uiItemL(split, name, icon); + + uiBlockSetEmboss(block, UI_EMBOSSN); + row = uiLayoutRow(split, 1); + // uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); // enable when used + uiItemR(row, itemptr, "hide", 0, "", 0); + uiItemR(row, itemptr, "hide_select", 0, "", 0); + uiItemR(row, itemptr, "hide_render", 0, "", 0); + + uiBlockSetEmboss(block, UI_EMBOSS); + } /* There is a last chance to display custom controls (in addition to the name/label): * If the given item property group features a string property named as prop_list, diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 6e653eff57c..d0a93302b7f 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -441,6 +441,14 @@ void ED_keymap_proportional_obmode(struct wmKeyConfig *UNUSED(keyconf), struct w RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_edit_objects"); } +void ED_keymap_proportional_maskmode(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap) +{ + wmKeyMapItem *kmi; + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_edit_mask"); +} + void ED_keymap_proportional_editmode(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap, const short do_connected) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 8baca253519..89c7896d53c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -46,6 +46,7 @@ #include "DNA_scene_types.h" #include "DNA_meta_types.h" #include "DNA_mesh_types.h" +#include "DNA_mask_types.h" #include "DNA_userdef_types.h" #include "BKE_context.h" @@ -59,6 +60,7 @@ #include "BKE_screen.h" #include "BKE_tessmesh.h" #include "BKE_sound.h" +#include "BKE_mask.h" #include "WM_api.h" #include "WM_types.h" @@ -71,6 +73,7 @@ #include "ED_screen_types.h" #include "ED_keyframes_draw.h" #include "ED_view3d.h" +#include "ED_clip.h" #include "RNA_access.h" #include "RNA_define.h" @@ -453,6 +456,13 @@ int ED_operator_editmball(bContext *C) return 0; } +int ED_operator_mask(bContext *C) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + + return ED_space_clip_show_maskedit(sc); +} + /* *************************** action zone operator ************************** */ /* operator state vars used: @@ -1937,7 +1947,17 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) if (ob) ob_to_keylist(&ads, ob, &keys, NULL); - + + { + SpaceClip *sc = CTX_wm_space_clip(C); + if (sc) { + if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { + MaskLayer *masklay = BKE_mask_layer_active(sc->mask); + mask_to_keylist(&ads, masklay, &keys); + } + } + } + /* build linked-list for searching */ BLI_dlrbTree_linkedlist_sync(&keys); diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 956aee84fd3..fa77249a7a1 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -62,6 +62,7 @@ #include "ED_mball.h" #include "ED_logic.h" #include "ED_clip.h" +#include "ED_mask.h" /* only call once on startup, storage is global in BKE kernel listbase */ void ED_spacetypes_init(void) @@ -111,6 +112,7 @@ void ED_spacetypes_init(void) ED_operatortypes_sound(); ED_operatortypes_render(); ED_operatortypes_logic(); + ED_operatortypes_mask(); UI_view2d_operatortypes(); UI_buttons_operatortypes(); @@ -133,6 +135,7 @@ void ED_spacetypes_init(void) ED_operatormacros_action(); ED_operatormacros_clip(); ED_operatormacros_curve(); + ED_operatormacros_mask(); /* register dropboxes (can use macros) */ spacetypes = BKE_spacetypes_list(); @@ -164,6 +167,7 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf) ED_keymap_physics(keyconf); ED_keymap_metaball(keyconf); ED_keymap_paint(keyconf); + ED_keymap_mask(keyconf); ED_marker_keymap(keyconf); UI_view2d_keymap(keyconf); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index c00359f0f32..6ac5ec59742 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -33,12 +33,14 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" /* SELECT */ +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" #include "BKE_context.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "BKE_mask.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -194,6 +196,32 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc glRecti(x, 0, x + framelen, 8); clip_draw_curfra_label(sc, x, 8.0f); + + /* movie clip animation */ + if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { + MaskLayer *masklay = BKE_mask_layer_active(sc->mask); + if (masklay) { + MaskLayerShape *masklay_shape; + + glColor4ub(255, 175, 0, 255); + glBegin(GL_LINES); + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + i = masklay_shape->frame; + + /* glRecti((i - sfra) * framelen, 0, (i - sfra + 1) * framelen, 4); */ + + /* use a line so we always see the keyframes */ + glVertex2i((i - sfra) * framelen, 0); + glVertex2i((i - sfra) * framelen, (i == CFRA) ? 22 : 10); + } + + glEnd(); + } + } } static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index a477a7435fd..f16ef21b707 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -34,10 +34,12 @@ #include "MEM_guardedalloc.h" #include "BKE_main.h" +#include "BKE_mask.h" #include "BKE_movieclip.h" #include "BKE_context.h" #include "BKE_tracking.h" +#include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ #include "BLI_utildefines.h" @@ -127,6 +129,32 @@ int ED_space_clip_tracking_frame_poll(bContext *C) return FALSE; } +int ED_space_clip_maskediting_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc && sc->clip) { + return ED_space_clip_show_maskedit(sc); + } + + return FALSE; +} + +int ED_space_clip_maskediting_mask_poll(bContext *C) +{ + if (ED_space_clip_maskediting_poll(C)) { + MovieClip *clip = CTX_data_edit_movieclip(C); + + if (clip) { + SpaceClip *sc= CTX_wm_space_clip(C); + + return sc->mask != NULL; + } + } + + return FALSE; +} + /* ******** editing functions ******** */ void ED_space_clip_set(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip) @@ -170,6 +198,11 @@ MovieClip *ED_space_clip(SpaceClip *sc) return sc->clip; } +Mask *ED_space_clip_mask(SpaceClip *sc) +{ + return sc->mask; +} + ImBuf *ED_space_clip_get_buffer(SpaceClip *sc) { if (sc->clip) { @@ -214,6 +247,51 @@ void ED_space_clip_size(SpaceClip *sc, int *width, int *height) } } +void ED_space_clip_mask_size(SpaceClip *sc, int *width, int *height) +{ + /* quite the same as ED_space_clip_size, but it also runs aspect correction on output resolution + * this is needed because mask should be rasterized with exactly the same resolution as + * currently displaying frame and it doesn't have access to aspect correction currently + * used for display. (sergey) + */ + + if (!sc->mask) { + *width = 0; + *height = 0; + } else { + float aspx, aspy; + + ED_space_clip_size(sc, width, height); + ED_space_clip_aspect(sc, &aspx, &aspy); + + *width *= aspx; + *height *= aspy; + } +} + +void ED_space_clip_mask_aspect(SpaceClip *sc, float *aspx, float *aspy) +{ + int w, h; + + ED_space_clip_aspect(sc, aspx, aspy); + ED_space_clip_size(sc, &w, &h); + + /* now this is not accounted for! */ +#if 0 + *aspx *= (float)w; + *aspy *= (float)h; +#endif + + if(*aspx < *aspy) { + *aspy= *aspy / *aspx; + *aspx= 1.0f; + } + else { + *aspx= *aspx / *aspy; + *aspy= 1.0f; + } +} + void ED_space_clip_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoomy) { int width, height; @@ -234,6 +312,33 @@ void ED_space_clip_aspect(SpaceClip *sc, float *aspx, float *aspy) *aspx = *aspy = 1.0f; } +void ED_space_clip_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *aspy) +{ + int w, h; + + /* most of tools does not require aspect to be returned with dimensions correction + * due to they're invariant to this stuff, but some transformation tools like rotation + * should be aware of aspect correction caused by different resolution in different + * directions. + * mainly this is sued for transformation stuff + */ + + ED_space_clip_aspect(sc, aspx, aspy); + ED_space_clip_size(sc, &w, &h); + + *aspx *= (float)w; + *aspy *= (float)h; + + if(*aspx < *aspy) { + *aspy= *aspy / *aspx; + *aspx= 1.0f; + } + else { + *aspx= *aspx / *aspy; + *aspy= 1.0f; + } +} + void ED_clip_update_frame(const Main *mainp, int cfra) { wmWindowManager *wm; @@ -562,6 +667,8 @@ void ED_space_clip_free_texture_buffer(SpaceClip *sc) } } +/* ******** masking editing related functions ******** */ + int ED_space_clip_show_trackedit(SpaceClip *sc) { if (sc) { @@ -570,3 +677,23 @@ int ED_space_clip_show_trackedit(SpaceClip *sc) return FALSE; } + +int ED_space_clip_show_maskedit(SpaceClip *sc) +{ + if (sc) { + return sc->mode == SC_MODE_MASKEDITING; + } + + return FALSE; +} + +void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask) +{ + sc->mask = mask; + + if(sc->mask && sc->mask->id.us==0) + sc->clip->id.us = 1; + + if(C) + WM_event_add_notifier(C, NC_MASK|NA_SELECTED, mask); +} diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a6fda200ff4..5e04d5c99cd 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -33,7 +33,9 @@ #include #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "DNA_movieclip_types.h" +#include "DNA_view3d_types.h" /* for pivot point */ #include "MEM_guardedalloc.h" @@ -49,6 +51,8 @@ #include "IMB_imbuf_types.h" +#include "ED_mask.h" +#include "ED_space_api.h" #include "ED_screen.h" #include "ED_clip.h" #include "ED_transform.h" @@ -237,6 +241,7 @@ static SpaceLink *clip_new(const bContext *C) sc->zoom = 1.0f; sc->path_length = 20; sc->scopes.track_preview_height = 120; + sc->around = V3D_LOCAL; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for clip"); @@ -361,6 +366,24 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) break; } break; + case NC_MASK: + switch(wmn->data) { + case ND_SELECT: + case ND_DATA: + case ND_DRAW: + ED_area_tag_redraw(sa); + break; + } + switch(wmn->action) { + case NA_SELECTED: + clip_scopes_tag_refresh(sa); + ED_area_tag_redraw(sa); + break; + case NA_EDITED: + ED_area_tag_redraw(sa); + break; + } + break; case NC_GEOM: switch (wmn->data) { case ND_SELECT: @@ -532,7 +555,7 @@ static void clip_keymap(struct wmKeyConfig *keyconf) /* ******** Hotkeys avalaible for main region only ******** */ keymap = WM_keymap_find(keyconf, "Clip Editor", SPACE_CLIP, 0); - +// keymap->poll = ED_space_clip_tracking_poll; /* ** View/navigation ** */ WM_keymap_add_item(keymap, "CLIP_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); @@ -715,7 +738,7 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "extend", TRUE); /* toggle */ } -const char *clip_context_dir[] = {"edit_movieclip", NULL}; +const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL}; static int clip_context(const bContext *C, const char *member, bContextDataResult *result) { @@ -729,7 +752,11 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul else if (CTX_data_equals(member, "edit_movieclip")) { if (sc->clip) CTX_data_id_pointer_set(result, &sc->clip->id); - + return TRUE; + } + else if (CTX_data_equals(member, "edit_mask")) { + if (sc->mask) + CTX_data_id_pointer_set(result, &sc->mask->id); return TRUE; } @@ -1020,6 +1047,9 @@ static void clip_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ + keymap= WM_keymap_find(wm->defaultconf, "Mask Editor", 0, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + keymap = WM_keymap_find(wm->defaultconf, "Clip", SPACE_CLIP, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); @@ -1067,6 +1097,49 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) /* Grease Pencil */ clip_draw_grease_pencil((bContext *)C, 1); + if(sc->mode == SC_MODE_MASKEDITING) { + int x, y; + int width, height; + float zoomx, zoomy, aspx, aspy; + + /* frame image */ + float maxdim; + float xofs, yofs; + + /* find window pixel coordinates of origin */ + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); + + ED_space_clip_size(sc, &width, &height); + ED_space_clip_zoom(sc, ar, &zoomx, &zoomy); + ED_space_clip_aspect(sc, &aspx, &aspy); + + /* frame the image */ + maxdim = maxf(width, height); + if (width == height) { + xofs = yofs = 0; + } + else if (width < height) { + xofs = ((height - width) / -2.0f) * zoomx; + yofs = 0.0f; + } + else { /* (width > height) */ + xofs = 0.0f; + yofs = ((width - height) / -2.0f) * zoomy; + } + + /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ + glPushMatrix(); + glTranslatef(x + xofs, y + yofs, 0); + glScalef(maxdim * zoomx, maxdim * zoomy, 0); + glMultMatrixf(sc->stabmat); + + ED_mask_draw((bContext *)C, sc->mask_draw_flag, sc->mask_draw_type); + + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + + glPopMatrix(); + } + /* reset view matrix */ UI_view2d_view_restore(C); @@ -1241,6 +1314,26 @@ static void clip_header_area_draw(const bContext *C, ARegion *ar) ED_region_header(C, ar); } +static void clip_header_area_listener(ARegion *ar, wmNotifier *wmn) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + /* for proportional editmode only */ + case ND_TOOLSETTINGS: + /* TODO - should do this when in mask mode only but no datas available */ + // if(sc->mode == SC_MODE_MASKEDITING) + { + ED_region_tag_redraw(ar); + } + break; + } + break; + } +} + + /****************** tools region ******************/ /* add handlers, stuff you only do once or on area/region changes */ @@ -1402,6 +1495,7 @@ void ED_spacetype_clip(void) art->init = clip_header_area_init; art->draw = clip_header_area_draw; + art->listener = clip_header_area_listener; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 73ca9097610..5a8bc5da324 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2400,6 +2400,11 @@ static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), } } +static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL); +} + /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2589,7 +2594,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) ntype->uifuncbut = node_composit_buts_viewer_but; ntype->uibackdropfunc = node_composit_backdrop_viewer; break; - + case CMP_NODE_MASK: + ntype->uifunc= node_composit_buts_mask; + break; default: ntype->uifunc = NULL; } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 520a9f1cd22..66919935d48 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -245,6 +245,13 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) break; } break; + case NC_MASK: + if (wmn->action == NA_EDITED) { + if (type==NTREE_COMPOSIT) { + ED_area_tag_refresh(sa); + } + } + break; case NC_IMAGE: if (wmn->action == NA_EDITED) { diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index e955dae0178..157fe1aa710 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -49,6 +49,7 @@ #include "DNA_constraint_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_mask_types.h" #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ @@ -162,13 +163,35 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) else if (t->spacetype==SPACE_CLIP) { View2D *v2d = t->view; float divx, divy; + float mulx, muly; + float aspx = 1.0f, aspy = 1.0f; divx = v2d->mask.xmax-v2d->mask.xmin; divy = v2d->mask.ymax-v2d->mask.ymin; - r_vec[0] = (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx; - r_vec[1] = (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy; + mulx = (v2d->cur.xmax-v2d->cur.xmin); + muly = (v2d->cur.ymax-v2d->cur.ymin); + + if (t->options & CTX_MASK) { + /* clamp w/h, mask only */ + divx = divy = maxf(divx, divy); + mulx = muly = minf(mulx, muly); + } + + r_vec[0] = mulx * (dx) / divx; + r_vec[1] = muly * (dy) / divy; r_vec[2] = 0.0f; + + if (t->options & CTX_MOVIECLIP) { + ED_space_clip_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy); + } + else if (t->options & CTX_MASK) { + /* TODO - NOT WORKING, this isnt so bad since its only display aspect */ + ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); + } + + r_vec[0] *= aspx; + r_vec[1] *= aspy; } else { printf("%s: called in an invalid context\n", __func__); @@ -226,9 +249,18 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) } else if (t->spacetype==SPACE_CLIP) { float v[2]; + float aspx = 1.0f, aspy = 1.0f; copy_v2_v2(v, vec); + if (t->options & CTX_MOVIECLIP) + ED_space_clip_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy); + else if (t->options & CTX_MASK) + ED_space_clip_mask_aspect(t->sa->spacedata.first, &aspx, &aspy); + + v[0] /= aspx; + v[1] /= aspy; + UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); } } @@ -279,16 +311,23 @@ void applyAspectRatio(TransInfo *t, float vec[2]) vec[1] /= aspy; } else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { - if (t->options & CTX_MOVIECLIP) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; float aspx, aspy; - int width, height; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); - vec[0] *= width / aspx; - vec[1] *= height / aspy; + if (t->options & CTX_MOVIECLIP) { + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); + + vec[0] /= aspx; + vec[1] /= aspy; + } + else if (t->options & CTX_MASK) { + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + + vec[0] /= aspx; + vec[1] /= aspy; + } } } } @@ -312,16 +351,19 @@ void removeAspectRatio(TransInfo *t, float vec[2]) vec[1] *= aspy; } else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { - if (t->options & CTX_MOVIECLIP) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { SpaceClip *sc = t->sa->spacedata.first; - float aspx, aspy; - int width, height; + float aspx = 1.0f, aspy = 1.0f; - ED_space_clip_size(sc, &width, &height); - ED_space_clip_aspect(sc, &aspx, &aspy); + if (t->options & CTX_MOVIECLIP) { + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); + } + else if (t->options & CTX_MASK) { + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + } - vec[0] *= aspx / width; - vec[1] *= aspy / height; + vec[0] *= aspx; + vec[1] *= aspy; } } } @@ -367,12 +409,20 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else if (t->spacetype==SPACE_CLIP) { SpaceClip *sc = (SpaceClip*)t->sa->spacedata.first; - MovieClip *clip = ED_space_clip(sc); - /* objects could be parented to tracking data, so send this for viewport refresh */ - WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); + if (ED_space_clip_show_trackedit(sc)) { + MovieClip *clip = ED_space_clip(sc); + + /* objects could be parented to tracking data, so send this for viewport refresh */ + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); + WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); + } + else if (ED_space_clip_show_maskedit(sc)) { + Mask *mask = ED_space_clip_mask(sc); + + WM_event_add_notifier(C, NC_MASK|NA_EDITED, mask); + } } } @@ -728,7 +778,7 @@ int transformEvent(TransInfo *t, wmEvent *event) t->redraw |= TREDRAW_HARD; } else if (t->mode == TFM_TRANSLATION) { - if (t->options & CTX_MOVIECLIP) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { restoreTransObjects(t); t->flag ^= T_ALT_TRANSFORM; @@ -738,7 +788,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case TFM_MODAL_ROTATE: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MOVIECLIP)) { + if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { resetTransRestrictions(t); @@ -997,7 +1047,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case RKEY: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MOVIECLIP)) { + if (!(t->options & CTX_TEXTURE)) { if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { resetTransRestrictions(t); @@ -1459,6 +1509,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) { if (t->obedit) ts->proportional = proportional; + else if (t->options & CTX_MASK) + ts->proportional_mask = (proportional != PROP_EDIT_OFF); else ts->proportional_objects = (proportional != PROP_EDIT_OFF); } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 6051fd2577b..59688f1436e 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -561,6 +561,7 @@ int clipUVTransform(TransInfo *t, float *vec, int resize); void flushTransNodes(TransInfo *t); void flushTransSeq(TransInfo *t); void flushTransTracking(TransInfo *t); +void flushTransMasking(TransInfo *t); /*********************** exported from transform_manipulator.c ********** */ int gimbal_axis(struct Object *ob, float gmat[][3]); /* return 0 when no gimbal for selection */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index a069194d868..9c6d7e49c08 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -53,6 +53,7 @@ #include "DNA_meshdata_types.h" #include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" @@ -87,6 +88,7 @@ #include "BKE_sequencer.h" #include "BKE_tessmesh.h" #include "BKE_tracking.h" +#include "BKE_mask.h" #include "ED_anim_api.h" @@ -102,6 +104,7 @@ #include "ED_types.h" #include "ED_uvedit.h" #include "ED_clip.h" +#include "ED_mask.h" #include "ED_util.h" /* for crazyspace correction */ #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */ @@ -4897,6 +4900,24 @@ void special_aftertrans_update(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); } } + else if (t->options & CTX_MASK) { + SpaceClip *sc = t->sa->spacedata.first; + Mask *mask = ED_space_clip_mask(sc); + + if (t->scene->nodetree) { + /* tracks can be used for stabilization nodes, + * flush update for such nodes */ + nodeUpdateID(t->scene->nodetree, &mask->id); + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); + } + + /* TODO - dont key all masks... */ + if (IS_AUTOKEY_ON(t->scene)) { + Scene *scene = t->scene; + + ED_mask_layer_shape_auto_key_all(mask, CFRA); + } + } } else if (t->spacetype == SPACE_ACTION) { SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; @@ -5823,6 +5844,206 @@ void flushTransTracking(TransInfo *t) } } +/* * masking * */ + +typedef struct TransDataMasking{ + int is_handle; + + float handle[2], orig_handle[2]; + float vec[3][3]; + MaskSplinePoint *point; +} TransDataMasking; + +static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, + TransData *td, TransData2D *td2d, TransDataMasking *tdm, int propmode) +{ + BezTriple *bezt = &point->bezt; + float aspx, aspy; + short is_sel_point = MASKPOINT_ISSEL_KNOT(point); + short is_sel_any = MASKPOINT_ISSEL_ANY(point); + + tdm->point = point; + copy_m3_m3(tdm->vec, bezt->vec); + + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + + if (propmode || is_sel_point) { + int i; + for (i = 0; i < 3; i++) { + /* CV coords are scaled by aspects. this is needed for rotations and + * proportional editing to be consistent with the stretched CV coords + * that are displayed. this also means that for display and numinput, + * and when the the CV coords are flushed, these are converted each time */ + td2d->loc[0] = bezt->vec[i][0]*aspx; + td2d->loc[1] = bezt->vec[i][1]*aspy; + td2d->loc[2] = 0.0f; + td2d->loc2d = bezt->vec[i]; + + td->flag = 0; + td->loc = td2d->loc; + copy_v3_v3(td->center, td->loc); + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; + td->val= NULL; + + if (is_sel_any) { + td->flag |= TD_SELECTED; + } + td->dist= 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + td++; + td2d++; + } + } + else { + tdm->is_handle = TRUE; + + BKE_mask_point_handle(point, tdm->handle); + + copy_v2_v2(tdm->orig_handle, tdm->handle); + + td2d->loc[0] = tdm->handle[0]*aspx; + td2d->loc[1] = tdm->handle[1]*aspy; + td2d->loc[2] = 0.0f; + td2d->loc2d = tdm->handle; + + td->flag = 0; + td->loc = td2d->loc; + copy_v3_v3(td->center, td->loc); + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; + td->val= NULL; + + if (is_sel_any) { + td->flag |= TD_SELECTED; + } + + td->dist= 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + td++; + td2d++; + } +} + +static void createTransMaskingData(bContext *C, TransInfo *t) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + TransData *td = NULL; + TransData2D *td2d = NULL; + TransDataMasking *tdm = NULL; + int count = 0, countsel = 0; + int propmode = t->flag & T_PROP_EDIT; + + /* count */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline = masklay->splines.first; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + if (MASKPOINT_ISSEL_KNOT(point)) + countsel += 3; + else + countsel += 1; + } + + if (propmode) + count += 3; + } + } + } + + /* note: in prop mode we need at least 1 selected */ + if (countsel == 0) return; + + t->total = (propmode) ? count: countsel; + td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransObData(Mask Editing)"); + /* for each 2d uv coord a 3d vector is allocated, so that they can be + * treated just as if they were 3d verts */ + td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(Mask Editing)"); + tdm = t->customData = MEM_callocN(t->total*sizeof(TransDataMasking), "TransDataMasking(Mask Editing)"); + + t->flag |= T_FREE_CUSTOMDATA; + + /* create data */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline = masklay->splines.first; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (propmode || MASKPOINT_ISSEL_ANY(point)) { + MaskPointToTransData(sc, point, td, td2d, tdm, propmode); + + if (propmode || MASKPOINT_ISSEL_KNOT(point)) { + td += 3; + td2d += 3; + tdm += 3; + } + else { + td++; + td2d++; + tdm++; + } + } + } + } + } +} + +void flushTransMasking(TransInfo *t) +{ + SpaceClip *sc = t->sa->spacedata.first; + TransData2D *td; + TransDataMasking *tdm; + int a; + float aspx, aspy, invx, invy; + + ED_space_clip_mask_aspect(sc, &aspx, &aspy); + invx = 1.0f/aspx; + invy = 1.0f/aspy; + + /* flush to 2d vector from internally used 3d vector */ + for(a=0, td = t->data2d, tdm = t->customData; atotal; a++, td++, tdm++) { + td->loc2d[0]= td->loc[0]*invx; + td->loc2d[1]= td->loc[1]*invy; + + if (tdm->is_handle) + BKE_mask_point_set_handle(tdm->point, td->loc2d, t->flag & T_ALT_TRANSFORM, tdm->orig_handle, tdm->vec); + } +} + void createTransData(bContext *C, TransInfo *t) { Scene *scene = t->scene; @@ -5892,6 +6113,15 @@ void createTransData(bContext *C, TransInfo *t) t->flag |= T_POINTS|T_2D_EDIT; if (t->options & CTX_MOVIECLIP) createTransTrackingData(C, t); + else if (t->options & CTX_MASK) { + createTransMaskingData(C, t); + + if (t->data && (t->flag & T_PROP_EDIT)) { + sort_trans_data(t); // makes selected become first in array + set_prop_dist(t, TRUE); + sort_trans_data_dist(t); + } + } } else if (t->obedit) { t->ext = NULL; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 0f742458ed3..3195fb0299d 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -49,6 +49,7 @@ #include "DNA_view3d_types.h" #include "DNA_modifier_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -638,33 +639,42 @@ static void recalcData_spaceclip(TransInfo *t) { SpaceClip *sc = t->sa->spacedata.first; - MovieClip *clip = ED_space_clip(sc); - ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); - MovieTrackingTrack *track; - - flushTransTracking(t); - - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { - if (t->mode == TFM_TRANSLATION) { - if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_POS); - if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); - } - else if (t->mode == TFM_RESIZE) { - if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); - if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + if (ED_space_clip_show_trackedit(sc)) { + MovieClip *clip = ED_space_clip(sc); + ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); + MovieTrackingTrack *track; + + flushTransTracking(t); + + track = tracksbase->first; + while (track) { + if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + if (t->mode == TFM_TRANSLATION) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_POS); + if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) + BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); + } + else if (t->mode == TFM_RESIZE) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) + BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + } } + + track = track->next; } - track = track->next; + DAG_id_tag_update(&clip->id, 0); } + else if (ED_space_clip_show_maskedit(sc)) { + Mask *mask = ED_space_clip_mask(sc); - DAG_id_tag_update(&clip->id, 0); + flushTransMasking(t); + + DAG_id_tag_update(&mask->id, 0); + } } /* helper for recalcData() - for 3d-view transforms */ @@ -1109,9 +1119,12 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) else if (t->spacetype==SPACE_CLIP) { SpaceClip *sclip = sa->spacedata.first; t->view = &ar->v2d; + t->around = sclip->around; if (ED_space_clip_show_trackedit(sclip)) t->options |= CTX_MOVIECLIP; + else if (ED_space_clip_show_maskedit(sclip)) + t->options |= CTX_MASK; } else { if (ar) { @@ -1174,6 +1187,15 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->flag |= T_PROP_CONNECTED; } } + else if (t->options & CTX_MASK) { + if (ts->proportional_mask) { + t->flag |= T_PROP_EDIT; + + if (ts->proportional == PROP_EDIT_CONNECTED) { + t->flag |= T_PROP_CONNECTED; + } + } + } else if (t->obedit == NULL && ts->proportional_objects) { t->flag |= T_PROP_EDIT; } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 777fcc2af0c..b6fc4f58bd7 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -206,6 +206,7 @@ typedef struct PreviewImage { #define ID_GD MAKE_ID2('G', 'D') /* GreasePencil */ #define ID_WM MAKE_ID2('W', 'M') /* WindowManager */ #define ID_MC MAKE_ID2('M', 'C') /* MovieClip */ +#define ID_MSK MAKE_ID2('M', 'S') /* Mask */ /* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ #define ID_SEQ MAKE_ID2('S', 'Q') diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 198b6a9bf80..75b0b18879d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -999,7 +999,8 @@ typedef struct ToolSettings { short snap_flag, snap_target; short proportional, prop_mode; char proportional_objects; /* proportional edit, object mode */ - char pad[5]; + char proportional_mask; /* proportional edit, object mode */ + char pad[4]; char auto_normalize; /*auto normalizing mode in wpaint*/ char multipaint; /* paint multiple bones in wpaint */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 8f3062655b7..e83f1b4495a 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -67,6 +67,7 @@ struct wmOperator; struct wmTimer; struct MovieClip; struct MovieClipScopes; +struct Mask; /* SpaceLink (Base) ==================================== */ @@ -1006,7 +1007,14 @@ typedef struct SpaceClip { short dope_sort; /* sort order in dopesheet view */ short dope_flag; /* dopsheet view flags */ - int pad3; + int around; /* pivot point for transforms */ + + /* **** mask editing **** */ + struct Mask *mask; + /* draw options */ + char mask_draw_flag; + char mask_draw_type; + char pad3[6]; } SpaceClip; /* SpaceClip->flag */ @@ -1037,6 +1045,7 @@ typedef enum eSpaceClip_Mode { SC_MODE_TRACKING = 0, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION, + SC_MODE_MASKEDITING, } eSpaceClip_Mode; /* SpaceClip->view */ diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 0191847706a..b0f8f02ae9f 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -132,6 +132,7 @@ static const char *includefiles[] = { "DNA_movieclip_types.h", "DNA_tracking_types.h", "DNA_dynamicpaint_types.h", + "DNA_mask_types.h", // empty string to indicate end of includefiles "" @@ -1241,4 +1242,5 @@ int main(int argc, char **argv) #include "DNA_movieclip_types.h" #include "DNA_tracking_types.h" #include "DNA_dynamicpaint_types.h" +#include "DNA_mask_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 821fcfb90e6..c9914a35a14 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -145,6 +145,7 @@ extern StructRNA RNA_CompositorNodeLumaMatte; extern StructRNA RNA_CompositorNodeMapUV; extern StructRNA RNA_CompositorNodeMapValue; extern StructRNA RNA_CompositorNodeMath; +extern StructRNA RNA_CompositorNodeMask; extern StructRNA RNA_CompositorNodeMixRGB; extern StructRNA RNA_CompositorNodeNormal; extern StructRNA RNA_CompositorNodeNormalize; @@ -304,6 +305,8 @@ extern StructRNA RNA_MaterialStrand; extern StructRNA RNA_MaterialSubsurfaceScattering; extern StructRNA RNA_MaterialTextureSlot; extern StructRNA RNA_MaterialVolume; +extern StructRNA RNA_Mask; +extern StructRNA RNA_MaskLayer; extern StructRNA RNA_Menu; extern StructRNA RNA_Mesh; extern StructRNA RNA_MeshColor; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 0c136a9444a..e7f9977d040 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -55,6 +55,7 @@ set(DEFSRC rna_lamp.c rna_lattice.c rna_main.c + rna_mask.c rna_material.c rna_mesh.c rna_meta.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 9661a60f779..3741d53c378 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2681,6 +2681,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_world.c", NULL, RNA_def_world}, {"rna_movieclip.c", NULL, RNA_def_movieclip}, {"rna_tracking.c", NULL, RNA_def_tracking}, + {"rna_mask.c", NULL, RNA_def_mask}, {NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 6a54c04b44d..7f851c939d2 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -147,6 +147,7 @@ short RNA_type_to_ID_code(StructRNA *type) if (RNA_struct_is_a(type, &RNA_World)) return ID_WO; if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM; if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC; + if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK; return 0; } @@ -182,6 +183,7 @@ StructRNA *ID_code_to_RNA_type(short idcode) case ID_WO: return &RNA_World; case ID_WM: return &RNA_WindowManager; case ID_MC: return &RNA_MovieClip; + case ID_MSK: return &RNA_Mask; default: return &RNA_ID; } } diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index cb90211eff9..e8e40d307fb 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -179,6 +179,7 @@ void RNA_def_wm(struct BlenderRNA *brna); void RNA_def_world(struct BlenderRNA *brna); void RNA_def_movieclip(struct BlenderRNA *brna); void RNA_def_tracking(struct BlenderRNA *brna); +void RNA_def_mask(struct BlenderRNA *brna); /* Common Define functions */ @@ -301,6 +302,7 @@ void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop); /* ID Properties */ diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index b0981c19835..6ac032e5d99 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -253,6 +253,12 @@ static void rna_Main_movieclips_begin(CollectionPropertyIterator *iter, PointerR rna_iterator_listbase_begin(iter, &bmain->movieclip, NULL); } +static void rna_Main_masks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Main *bmain= (Main*)ptr->data; + rna_iterator_listbase_begin(iter, &bmain->mask, NULL); +} + #ifdef UNIT_TEST static PointerRNA rna_Test_test_get(PointerRNA *ptr) @@ -316,6 +322,7 @@ void RNA_def_main(BlenderRNA *brna) {"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle datablocks", RNA_def_main_particles}, {"grease_pencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil datablocks", RNA_def_main_gpencil}, {"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip datablocks", RNA_def_main_movieclips}, + {"masks", "Mask", "rna_Main_masks_begin", "Masks", "Masks datablocks", RNA_def_main_masks}, {NULL, NULL, NULL, NULL, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 024265c3d18..98b3c0ab9f4 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -33,6 +33,8 @@ #include #include +#include "DNA_ID.h" + #include "RNA_define.h" #include "RNA_access.h" #include "RNA_enum_types.h" @@ -67,6 +69,7 @@ #include "BKE_depsgraph.h" #include "BKE_speaker.h" #include "BKE_movieclip.h" +#include "BKE_mask.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" @@ -87,6 +90,7 @@ #include "DNA_vfont_types.h" #include "DNA_node_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "ED_screen.h" @@ -539,6 +543,22 @@ void rna_Main_movieclips_remove(Main *bmain, MovieClip *clip) /* XXX python now has invalid pointer? */ } +Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) +{ + Mask *mask; + + mask = BKE_mask_new("Mask"); + + return mask; +} + +void rna_Main_masks_remove(Main *bmain, Mask *mask) +{ + BKE_mask_unlink(bmain, mask); + BKE_libblock_free(&bmain->mask, mask); + /* XXX python now has invalid pointer? */ +} + /* tag functions, all the same */ void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); } void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); } @@ -569,6 +589,7 @@ void rna_Main_actions_tag(Main *bmain, int value) { tag_main_lb(&bmain->action, void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain->particle, value); } void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); } void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); } +void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); } static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA); } static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE); } @@ -1520,4 +1541,34 @@ void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); } +void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "BlendDataMasks"); + srna= RNA_def_struct(brna, "BlendDataMasks", NULL); + RNA_def_struct_sdna(srna, "Main"); + RNA_def_struct_ui_text(srna, "Main Masks", "Collection of masks"); + + func= RNA_def_function(srna, "tag", "rna_Main_masks_tag"); + parm= RNA_def_boolean(func, "value", 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + + /* new func */ + func = RNA_def_function(srna, "new", "rna_Main_mask_new"); + RNA_def_function_ui_description(func, "Add a new mask with a given name to the main database"); + parm = RNA_def_string_file_path(func, "name", "", MAX_ID_NAME - 2, "Mask", "Name of new mask datablock"); + /* return type */ + parm = RNA_def_pointer(func, "mask", "Mask", "", "New mask datablock"); + RNA_def_function_return(func, parm); + + /* remove func */ + func= RNA_def_function(srna, "remove", "rna_Main_masks_remove"); + RNA_def_function_ui_description(func, "Remove a masks from the current blendfile."); + parm= RNA_def_pointer(func, "mask", "Mask", "", "Mask to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL); +} + #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 466a9b80c50..30c705fb7fa 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3030,6 +3030,18 @@ static void def_cmp_moviedistortion(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_mask(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Mask"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mask", ""); +} + + static void dev_cmd_transform(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 351c6d93514..d5b33f0d01b 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -165,6 +165,7 @@ DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIP DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE" ,BokehImage, "Bokeh image", "" ) DefNode( CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH" ,Switch, "Switch", "" ) DefNode( CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "ColorCorrection", "" ) +DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 25f2bd7132c..9eb313204f7 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1565,6 +1565,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "use_proportional_edit_mask", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proportional_mask", 0); + RNA_def_property_ui_text(prop, "Proportional Editing Objects", "Proportional editing mask mode"); + RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "proportional_edit_falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "prop_mode"); RNA_def_property_enum_items(prop, proportional_falloff_items); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 9b4dcd03c79..8fe33f3e80f 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -45,6 +45,7 @@ #include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_sequence_types.h" +#include "DNA_mask_types.h" #include "DNA_view3d_types.h" #include "WM_api.h" @@ -120,6 +121,7 @@ EnumPropertyItem viewport_shade_items[] = { #ifdef RNA_RUNTIME #include "DNA_anim_types.h" +#include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -1037,6 +1039,13 @@ static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, PointerRNA value) ED_space_clip_set(NULL, screen, sc, (MovieClip *)value.data); } +static void rna_SpaceClipEditor_mask_set(PointerRNA *ptr, PointerRNA value) +{ + SpaceClip *sc= (SpaceClip*)(ptr->data); + + ED_space_clip_set_mask(NULL, sc, (Mask*)value.data); +} + static void rna_SpaceClipEditor_clip_mode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { SpaceClip *sc = (SpaceClip *)(ptr->data); @@ -1060,6 +1069,14 @@ static void rna_SpaceClipEditor_view_type_update(Main *UNUSED(bmain), Scene *UNU #else +static EnumPropertyItem dt_uv_items[] = { + {SI_UVDT_OUTLINE, "OUTLINE", 0, "Outline", "Draw white edges with black outline"}, + {SI_UVDT_DASH, "DASH", 0, "Dash", "Draw dashed black-white edges"}, + {SI_UVDT_BLACK, "BLACK", 0, "Black", "Draw black edges"}, + {SI_UVDT_WHITE, "WHITE", 0, "White", "Draw white edges"}, + {0, NULL, 0, NULL, NULL} +}; + static void rna_def_space(BlenderRNA *brna) { StructRNA *srna; @@ -1091,14 +1108,6 @@ static void rna_def_space_image_uv(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem dt_uv_items[] = { - {SI_UVDT_OUTLINE, "OUTLINE", 0, "Outline", "Draw white edges with black outline"}, - {SI_UVDT_DASH, "DASH", 0, "Dash", "Draw dashed black-white edges"}, - {SI_UVDT_BLACK, "BLACK", 0, "Black", "Draw black edges"}, - {SI_UVDT_WHITE, "WHITE", 0, "White", "Draw white edges"}, - {0, NULL, 0, NULL, NULL} - }; - static EnumPropertyItem dt_uvstretch_items[] = { {SI_UVDT_STRETCH_ANGLE, "ANGLE", 0, "Angle", "Angular distortion between UV and 3D angles"}, {SI_UVDT_STRETCH_AREA, "AREA", 0, "Area", "Area distortion between UV and 3D faces"}, @@ -2974,6 +2983,7 @@ static void rna_def_space_clip(BlenderRNA *brna) {SC_MODE_RECONSTRUCTION, "RECONSTRUCTION", ICON_SNAP_FACE, "Reconstruction", "Show tracking/reconstruction tools"}, {SC_MODE_DISTORTION, "DISTORTION", ICON_GRID, "Distortion", "Show distortion tools"}, + {SC_MODE_MASKEDITING, "MASKEDITING", ICON_MOD_MASK, "Mask editing", "Show mask editing tools"}, {0, NULL, 0, NULL, NULL} }; @@ -2991,6 +3001,16 @@ static void rna_def_space_clip(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem pivot_items[] = { + {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", + "Pivot around bounding box center of selected object(s)"}, + {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION, + "Individual Origins", "Pivot around each object's own origin"}, + {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point", + "Pivot around the median point of selected objects"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "SpaceClipEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceClip"); RNA_def_struct_ui_text(srna, "Space Clip Editor", "Clip editor space data"); @@ -3011,6 +3031,26 @@ static void rna_def_space_clip(BlenderRNA *brna) "Parameters defining which frame of the movie clip is displayed"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); + /* mask */ + prop= RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mask", "Mask displayed and edited in this space"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceClipEditor_mask_set", NULL, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + /* mask drawing */ + prop = RNA_def_property(srna, "mask_draw_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mask_draw_type"); + RNA_def_property_enum_items(prop, dt_uv_items); + RNA_def_property_ui_text(prop, "Edge Draw Type", "Draw type for mask splines"); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + prop = RNA_def_property(srna, "show_mask_smooth", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mask_draw_flag", MASK_DRAWFLAG_SMOOTH); + RNA_def_property_ui_text(prop, "Draw Smooth Splines", ""); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + /* mode */ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); @@ -3170,6 +3210,13 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + /* pivot point */ + prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "around"); + RNA_def_property_enum_items(prop, pivot_items); + RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); + /* ** dopesheet ** */ /* dopesheet sort */ diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 6bae6cdd473..c637e3606f1 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -82,6 +82,7 @@ set(SRC composite/nodes/node_composite_mapUV.c composite/nodes/node_composite_mapValue.c composite/nodes/node_composite_math.c + composite/nodes/node_composite_mask.c composite/nodes/node_composite_mixrgb.c composite/nodes/node_composite_movieclip.c composite/nodes/node_composite_moviedistortion.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index ca925c82afd..f850ea91f12 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -50,6 +50,7 @@ void register_node_type_cmp_value(struct bNodeTreeType *ttype); void register_node_type_cmp_rgb(struct bNodeTreeType *ttype); void register_node_type_cmp_curve_time(struct bNodeTreeType *ttype); void register_node_type_cmp_movieclip(struct bNodeTreeType *ttype); +void register_node_type_cmp_usermask(struct bNodeTreeType *ttype); void register_node_type_cmp_composite(struct bNodeTreeType *ttype); void register_node_type_cmp_viewer(struct bNodeTreeType *ttype); @@ -115,6 +116,7 @@ void register_node_type_cmp_mapuv(struct bNodeTreeType *ttype); void register_node_type_cmp_transform(struct bNodeTreeType *ttype); void register_node_type_cmp_stabilize2d(struct bNodeTreeType *ttype); void register_node_type_cmp_moviedistortion(struct bNodeTreeType *ttype); +void register_node_type_cmp_mask(struct bNodeTreeType *ttype); void register_node_type_cmp_glare(struct bNodeTreeType *ttype); void register_node_type_cmp_tonemap(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 8f8f702e8ae..457322929b0 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -890,6 +890,10 @@ int ntreeCompositTagAnimated(bNodeTree *ntree) nodeUpdate(ntree, node); tagged= 1; } + else if (node->type==CMP_NODE_MASK) { + nodeUpdate(ntree, node); + tagged= 1; + } } return tagged; diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 3806cf4543a..ff223ac83cf 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -568,6 +568,22 @@ CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel) return valbuf; } +void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel) +{ + float *valf, *rectf; + int tot; + + valf= valbuf->rect; + + /* defaults to returning alpha channel */ + if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A; + + rectf = cbuf->rect + channel; + + for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4) + *rectf = *valf; +} + static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy) { CompBuf *outbuf; diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h index 8f42a9bbe47..cab60caaae7 100644 --- a/source/blender/nodes/composite/node_composite_util.h +++ b/source/blender/nodes/composite/node_composite_util.h @@ -157,6 +157,7 @@ void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, flo int src1_type, int fac1_type, int src2_type, int fac2_type); CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel); +void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel); void generate_preview(void *data, bNode *node, CompBuf *stackbuf); void do_copy_rgba(bNode *node, float *out, float *in); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 7cbeab6a02e..25abc171057 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -167,6 +167,7 @@ typedef struct wmNotifier { #define NC_ID (18<<24) #define NC_LOGIC (19<<24) #define NC_MOVIECLIP (20<<24) +#define NC_MASK (21<<24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 42787be8e02..d7d55885f37 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3853,6 +3853,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle"); WM_modalkeymap_assign(keymap, "UV_OT_circle_select"); WM_modalkeymap_assign(keymap, "CLIP_OT_select_circle"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_circle"); } @@ -3936,6 +3937,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "UV_OT_select_border"); WM_modalkeymap_assign(keymap, "CLIP_OT_select_border"); WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_border"); + WM_modalkeymap_assign(keymap, "MASK_OT_select_border"); WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 674d5540c8b..9fb0c103f1d 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -152,6 +152,7 @@ endif() bf_blenkernel # duplicate for linking bf_intern_mikktspace extern_recastnavigation + bf_intern_raskter ) if(WITH_MOD_CLOTH_ELTOPO) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 86567873256..4c45099808c 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -228,6 +228,7 @@ void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSett void ED_screen_set_scene(struct bContext *C, struct Scene *scene) {} void ED_space_clip_set(struct bContext *C, struct SpaceClip *sc, struct MovieClip *clip) {} +void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask){} void ED_area_tag_redraw_regiontype(struct ScrArea *sa, int regiontype) {} void ED_render_engine_changed(struct Main *bmain) {} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 74ccda8ce0e..ac52acc3043 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -823,6 +823,7 @@ endif() bf_editor_sound bf_editor_animation bf_editor_datafiles + bf_editor_mask bf_render bf_intern_opennl @@ -894,6 +895,7 @@ endif() cycles_subd bf_compositor #added for opencl compositor bf_opencl #added for opencl compositor + bf_intern_raskter ) if(WITH_LIBMV) -- cgit v1.2.3 From 0f1fd51c2169d45327eef4c40622551694c9dd9e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 17:13:38 +0000 Subject: picky change - rename keymap since there is no 'mask editor' --- release/scripts/modules/bpy_extras/keyconfig_utils.py | 2 +- source/blender/editors/mask/mask_edit.c | 2 +- source/blender/editors/space_clip/space_clip.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py index 287cd81eff2..f8b0abd03ea 100644 --- a/release/scripts/modules/bpy_extras/keyconfig_utils.py +++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py @@ -95,7 +95,7 @@ KM_HIERARCHY = [ ('Clip', 'CLIP_EDITOR', 'WINDOW', [ ('Clip Editor', 'CLIP_EDITOR', 'WINDOW', []), ('Clip Graph Editor', 'CLIP_EDITOR', 'WINDOW', []), - ('Mask Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image + ('Mask Editing', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image ]), ('View3D Gesture Circle', 'EMPTY', 'WINDOW', []), diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 0b8551ddd4c..d811f815bf4 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -233,7 +233,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) wmKeyMap *keymap; wmKeyMapItem *kmi; - keymap = WM_keymap_find(keyconf, "Mask Editor", 0, 0); + keymap = WM_keymap_find(keyconf, "Mask Editing", 0, 0); keymap->poll = ED_maskediting_poll; WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 5e04d5c99cd..a7fe86e0eff 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1047,7 +1047,7 @@ static void clip_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_find(wm->defaultconf, "Mask Editor", 0, 0); + keymap= WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); keymap = WM_keymap_find(wm->defaultconf, "Clip", SPACE_CLIP, 0); -- cgit v1.2.3 From 6548f7efefb2e9db25e8c6ca8b7d4ed6b9725543 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 Jun 2012 17:17:10 +0000 Subject: Cycles: spot lamp support. --- intern/cycles/blender/addon/ui.py | 27 +++++++++++++++++++++--- intern/cycles/blender/blender_object.cpp | 4 +++- intern/cycles/kernel/kernel_emission.h | 7 +------ intern/cycles/kernel/kernel_light.h | 35 ++++++++++++++++++++++++++++++++ intern/cycles/kernel/kernel_types.h | 3 ++- intern/cycles/kernel/svm/emissive.h | 15 +++++++------- intern/cycles/render/light.cpp | 14 +++++++++++++ intern/cycles/render/light.h | 3 +++ intern/cycles/util/util_math.h | 6 ++++++ 9 files changed, 95 insertions(+), 19 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 8480b0a5256..3b906bb4bdf 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -488,9 +488,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): col = split.column() col.prop(clamp, "cast_shadow") - if lamp.type == 'SPOT': - layout.label(text="Not supported, interpreted as point lamp.") - elif lamp.type == 'HEMI': + if lamp.type == 'HEMI': layout.label(text="Not supported, interpreted as sun lamp.") @@ -509,6 +507,29 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel): if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'): layout.prop(lamp, "color") +class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel): + bl_label = "Spot Shape" + bl_context = "data" + + @classmethod + def poll(cls, context): + lamp = context.lamp + return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context) + + def draw(self, context): + layout = self.layout + + lamp = context.lamp + + split = layout.split() + + col = split.column() + sub = col.column() + sub.prop(lamp, "spot_size", text="Size") + sub.prop(lamp, "spot_blend", text="Blend", slider=True) + + col = split.column() + col.prop(lamp, "show_cone") class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel): bl_label = "Surface" diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index b04e0137e37..cea3b0256bd 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -106,7 +106,9 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, case BL::Lamp::type_SPOT: { BL::SpotLamp b_spot_lamp(b_lamp); light->size = b_spot_lamp.shadow_soft_size(); - light->type = LIGHT_POINT; + light->type = LIGHT_SPOT; + light->spot_angle = b_spot_lamp.spot_size(); + light->spot_smooth = b_spot_lamp.spot_blend(); break; } case BL::Lamp::type_HEMI: { diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 0ef1425e68a..881d25ad7ba 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -104,13 +104,8 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, float mis_weight = power_heuristic(pdf, bsdf_pdf); light_eval *= mis_weight; } - /* todo: clean up these weights */ - else if(ls.shader & SHADER_AREA_LIGHT) - light_eval *= 0.25f; /* area lamp */ - else if(ls.t != FLT_MAX) - light_eval *= 0.25f*M_1_PI_F; /* point lamp */ - bsdf_eval_mul(eval, light_eval/pdf); + bsdf_eval_mul(eval, light_eval*(ls.eval_fac/pdf)); if(bsdf_eval_is_zero(eval)) return false; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index e9e7fbd4ca1..76552400f9c 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -23,6 +23,7 @@ typedef struct LightSample { float3 D; float3 Ng; float t; + float eval_fac; int object; int prim; int shader; @@ -189,6 +190,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->Ng = D; ls->D = -D; ls->t = FLT_MAX; + ls->eval_fac = 1.0f; } #ifdef __BACKGROUND_MIS__ else if(type == LIGHT_BACKGROUND) { @@ -199,6 +201,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->Ng = D; ls->D = -D; ls->t = FLT_MAX; + ls->eval_fac = 1.0f; } #endif else { @@ -212,6 +215,36 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->P += sphere_light_sample(P, ls->P, size, randu, randv); ls->Ng = normalize(P - ls->P); + ls->eval_fac = 0.25f*M_1_PI_F; + } + else if(type == LIGHT_SPOT) { + float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2); + float size = data1.y; + + /* spot light */ + if(size > 0.0f) + ls->P += sphere_light_sample(P, ls->P, size, randu, randv); + + float3 dir = make_float3(data1.z, data1.w, data2.x); + float3 I = normalize(P - ls->P); + + float spot_angle = data2.y; + float spot_smooth = data2.z; + + float eval_fac = fabsf(dot(dir, I)); + + if(eval_fac <= spot_angle) { + eval_fac = 0.0f; + } + else { + float t = eval_fac - spot_angle; + + if(t < spot_smooth && spot_smooth != 0.0f) + eval_fac *= smoothstepf(t/spot_smooth); + } + + ls->Ng = I; + ls->eval_fac = eval_fac*0.25f*M_1_PI_F; } else { /* area light */ @@ -224,6 +257,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->P += area_light_sample(axisu, axisv, randu, randv); ls->Ng = D; + ls->eval_fac = 0.25f; } ls->t = 0.0f; @@ -262,6 +296,7 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object, ls->prim = prim; ls->t = 0.0f; ls->type = LIGHT_AREA; + ls->eval_fac = 1.0f; #ifdef __INSTANCING__ /* instance transform */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index a64c850d35a..d119057ac67 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -283,7 +283,8 @@ typedef enum LightType { LIGHT_DISTANT, LIGHT_BACKGROUND, LIGHT_AREA, - LIGHT_AO + LIGHT_AO, + LIGHT_SPOT } LightType; /* Camera Type */ diff --git a/intern/cycles/kernel/svm/emissive.h b/intern/cycles/kernel/svm/emissive.h index e3f99e9b729..0b0218674b8 100644 --- a/intern/cycles/kernel/svm/emissive.h +++ b/intern/cycles/kernel/svm/emissive.h @@ -34,14 +34,6 @@ CCL_NAMESPACE_BEGIN /* EMISSION CLOSURE */ -__device float3 emissive_eval(const float3 Ng, const float3 I) -{ - float cosNO = fabsf(dot(Ng, I)); - float res = (cosNO > 0.0f)? 1.0f: 0.0f; - - return make_float3(res, res, res); -} - /// Return the probability distribution function in the direction I, /// given the parameters and the light's surface normal. This MUST match /// the PDF computed by sample(). @@ -51,6 +43,13 @@ __device float emissive_pdf(const float3 Ng, const float3 I) return (cosNO > 0.0f)? 1.0f: 0.0f; } +__device float3 emissive_eval(const float3 Ng, const float3 I) +{ + float res = emissive_pdf(Ng, I); + + return make_float3(res, res, res); +} + __device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc) { return emissive_eval(sd->Ng, sd->I); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 267cb8e6d3a..1bf1cde4a1c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -109,6 +109,9 @@ Light::Light() map_resolution = 512; + spot_angle = M_PI_F/4.0f; + spot_smooth = 0.0f; + cast_shadow = true; shader = 0; } @@ -451,6 +454,17 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z); light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z); } + else if(light->type == LIGHT_SPOT) { + shader_id &= ~SHADER_AREA_LIGHT; + + float spot_angle = cosf(light->spot_angle*0.5f); + float spot_smooth = (1.0f - spot_angle)*light->spot_smooth; + + light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); + light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, dir.x, dir.y); + light_data[i*LIGHT_SIZE + 2] = make_float4(dir.z, spot_angle, spot_smooth, 0.0f); + light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } } device->tex_alloc("__light_data", dscene->light_data); diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 0ed143f5ad1..fb8684fa59b 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -48,6 +48,9 @@ public: int map_resolution; + float spot_angle; + float spot_smooth; + bool cast_shadow; int shader; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index fee2f10085b..cd44b7e8cda 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -162,6 +162,12 @@ __device_inline float nonzerof(float f, float eps) return f; } +__device_inline float smoothstepf(float f) +{ + float ff = f*f; + return (3.0f*ff - 2.0f*ff*f); +} + /* Float2 Vector */ #ifndef __KERNEL_OPENCL__ -- cgit v1.2.3 From c517247fc67b77e451c7e920385beda02a0de524 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 17:27:22 +0000 Subject: include cleanup, also raskter wasn't building on osx --- intern/raskter/raskter.c | 3 +-- source/blender/editors/mask/mask_add.c | 8 +------- source/blender/editors/mask/mask_draw.c | 5 +---- source/blender/editors/mask/mask_edit.c | 4 +--- source/blender/editors/mask/mask_ops.c | 2 -- source/blender/editors/mask/mask_relationships.c | 11 +---------- source/blender/editors/mask/mask_select.c | 6 +----- source/blender/editors/mask/mask_shapekey.c | 13 +------------ 8 files changed, 7 insertions(+), 45 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 152efb05cf0..63d37d166a0 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -28,8 +28,7 @@ * \ingroup RASKTER */ -#include -#include +#include #include "raskter.h" /* from BLI_utildefines.h */ diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index c2c2ebbfe42..9f379039983 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -31,12 +31,9 @@ #include "MEM_guardedalloc.h" -#include "BLI_utildefines.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_mask.h" @@ -47,10 +44,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_screen.h" -#include "ED_mask.h" -#include "ED_clip.h" -#include "ED_keyframing.h" +#include "ED_mask.h" /* own include */ #include "RNA_access.h" #include "RNA_define.h" diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index e580088e25b..a26ae5ea3c0 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -32,7 +32,6 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -#include "BLI_math.h" #include "BKE_context.h" #include "BKE_mask.h" @@ -40,10 +39,8 @@ #include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ -#include "ED_mask.h" - +#include "ED_mask.h" /* own include */ #include "BIF_gl.h" -#include "BIF_glutil.h" #include "UI_resources.h" diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index d811f815bf4..7a3f759e471 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -29,9 +29,7 @@ * \ingroup edmask */ -#include "MEM_guardedalloc.h" -#include "BLI_utildefines.h" #include "BLI_math.h" #include "BKE_context.h" @@ -41,7 +39,7 @@ #include "WM_types.h" #include "ED_screen.h" -#include "ED_mask.h" +#include "ED_mask.h" /* own include */ #include "ED_object.h" /* ED_keymap_proportional_maskmode only */ #include "ED_clip.h" #include "ED_transform.h" diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index cf3a72bdc78..62450f4bc65 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -31,12 +31,10 @@ #include "MEM_guardedalloc.h" -#include "BLI_utildefines.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_mask.h" diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 8a8427c024b..eaec5ad9a8f 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -29,31 +29,22 @@ * \ingroup edmask */ -#include "MEM_guardedalloc.h" -#include "BLI_utildefines.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_mask.h" #include "BKE_tracking.h" #include "DNA_mask_types.h" -#include "DNA_scene_types.h" #include "DNA_object_types.h" /* SELECT */ #include "WM_api.h" #include "WM_types.h" #include "ED_screen.h" -#include "ED_mask.h" -#include "ED_clip.h" - -#include "RNA_access.h" -#include "RNA_define.h" +#include "ED_mask.h" /* own include */ #include "mask_intern.h" /* own include */ diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 18d745dcf7b..4fee0a218a4 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -32,14 +32,10 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -#include "BLI_listbase.h" #include "BLI_rect.h" #include "BLI_lasso.h" -#include "BLI_math.h" #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_mask.h" #include "DNA_mask_types.h" @@ -49,8 +45,8 @@ #include "WM_types.h" #include "ED_screen.h" -#include "ED_mask.h" #include "ED_clip.h" +#include "ED_mask.h" /* own include */ #include "RNA_access.h" #include "RNA_define.h" diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 94aebb9f3a1..07ce9215e26 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -29,30 +29,19 @@ * \ingroup edmask */ -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" -#include "BLI_listbase.h" -#include "BLI_math.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_mask.h" #include "DNA_mask_types.h" #include "DNA_scene_types.h" -#include "DNA_object_types.h" /* SELECT */ #include "WM_api.h" #include "WM_types.h" -#include "ED_screen.h" -#include "ED_mask.h" -#include "ED_clip.h" - -#include "RNA_access.h" -#include "RNA_define.h" +#include "ED_mask.h" /* own include */ #include "mask_intern.h" /* own include */ -- cgit v1.2.3 From d46a6dc59c76c4b5f9210aba51f5f6347c7ccd26 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 17:30:54 +0000 Subject: abbreviate mask-editing to mask-edit --- release/scripts/startup/bl_ui/space_clip.py | 26 ++++++++++++------------ source/blender/editors/include/ED_clip.h | 4 ++-- source/blender/editors/mask/mask_add.c | 4 ++-- source/blender/editors/mask/mask_edit.c | 10 ++++----- source/blender/editors/mask/mask_intern.h | 4 ++-- source/blender/editors/mask/mask_ops.c | 18 ++++++++-------- source/blender/editors/mask/mask_relationships.c | 4 ++-- source/blender/editors/mask/mask_select.c | 14 ++++++------- source/blender/editors/mask/mask_shapekey.c | 4 ++-- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/editors/space_clip/clip_draw.c | 2 +- source/blender/editors/space_clip/clip_editor.c | 8 ++++---- source/blender/editors/space_clip/space_clip.c | 4 ++-- source/blender/makesdna/DNA_space_types.h | 2 +- source/blender/makesrna/intern/rna_space.c | 2 +- 15 files changed, 54 insertions(+), 54 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 988cd92a2eb..e834712ffe9 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -45,13 +45,13 @@ class CLIP_HT_header(Header): sub.menu("CLIP_MT_clip") if clip: - if sc.mode == 'MASKEDITING': + if sc.mode == 'MASKEDIT': sub.menu("CLIP_MT_mask") else: sub.menu("CLIP_MT_track") sub.menu("CLIP_MT_reconstruction") - if sc.mode != 'MASKEDITING': + if sc.mode != 'MASKEDIT': layout.prop(sc, "view", text="", expand=True) if clip: @@ -59,7 +59,7 @@ class CLIP_HT_header(Header): layout.prop(sc, "mode", text="") layout.prop(sc, "pivot_point", text="", icon_only=True) - if sc.mode == 'MASKEDITING': + if sc.mode == 'MASKEDIT': toolsettings = context.tool_settings row = layout.row(align=True) @@ -85,7 +85,7 @@ class CLIP_HT_header(Header): row = layout.row() row.template_ID(sc, "clip", open='clip.open') - if sc.mode == 'MASKEDITING': + if sc.mode == 'MASKEDIT': row = layout.row() row.template_ID(sc, "mask", new="mask.new") @@ -127,7 +127,7 @@ class CLIP_PT_mask_view_panel: sc = context.space_data clip = sc.clip - return clip and sc.view == 'CLIP' and sc.mode == 'MASKEDITING' + return clip and sc.view == 'CLIP' and sc.mode == 'MASKEDIT' class CLIP_PT_tracking_panel: @@ -428,7 +428,7 @@ class CLIP_PT_tools_grease_pencil(Panel): if sc.mode == 'DISTORTION': return sc.view == 'CLIP' - elif sc.mode == 'MASKEDITING': + elif sc.mode == 'MASKEDIT': return True return False @@ -619,7 +619,7 @@ class CLIP_PT_tracking_camera(Panel): col.prop(clip.tracking.camera, "k3") -class CLIP_PT_mask_objects(Panel): +class CLIP_PT_mask_layers(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Mask Layers" @@ -628,7 +628,7 @@ class CLIP_PT_mask_objects(Panel): def poll(cls, context): sc = context.space_data - return sc.mask and sc.mode == 'MASKEDITING' + return sc.mask and sc.mode == 'MASKEDIT' def draw(self, context): layout = self.layout @@ -667,7 +667,7 @@ class CLIP_PT_active_mask_spline(Panel): sc = context.space_data mask = sc.mask - if mask and sc.mode == 'MASKEDITING': + if mask and sc.mode == 'MASKEDIT': return mask.layers.active and mask.layers.active.splines.active return False @@ -694,7 +694,7 @@ class CLIP_PT_active_mask_point(Panel): sc = context.space_data mask = sc.mask - if mask and sc.mode == 'MASKEDITING': + if mask and sc.mode == 'MASKEDIT': return mask.layers.active and mask.layers.active.splines.active_point return False @@ -776,7 +776,7 @@ class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): row = col.row() row.prop(clip, "display_aspect", text="") - if sc.mode == 'MASKEDITING': + if sc.mode == 'MASKEDIT': col = layout.column() col.prop(sc, "mask_draw_type", text="") col.prop(sc, "show_mask_smooth") @@ -791,7 +791,7 @@ class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): def poll(cls, context): sc = context.space_data - return sc.mode != 'MASKEDITING' + return sc.mode != 'MASKEDIT' def draw(self, context): layout = self.layout @@ -1138,7 +1138,7 @@ class CLIP_MT_select(Menu): layout = self.layout sc = context.space_data - if sc.mode == 'MASKEDITING': + if sc.mode == 'MASKEDIT': layout.operator("mask.select_border") layout.operator("mask.select_circle") diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 7e1505b652f..f7fb1709ce7 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -49,8 +49,8 @@ int ED_space_clip_view_clip_poll(struct bContext *C); int ED_space_clip_tracking_poll(struct bContext *C); int ED_space_clip_tracking_size_poll(struct bContext *C); int ED_space_clip_tracking_frame_poll(struct bContext *C); -int ED_space_clip_maskediting_poll(struct bContext *C); -int ED_space_clip_maskediting_mask_poll(bContext *C); +int ED_space_clip_maskedit_poll(struct bContext *C); +int ED_space_clip_maskedit_mask_poll(bContext *C); void ED_space_clip_set(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip); struct MovieClip *ED_space_clip(struct SpaceClip *sc); diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 9f379039983..cdfdde4ef31 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -624,7 +624,7 @@ void MASK_OT_add_vertex(wmOperatorType *ot) /* api callbacks */ ot->exec = add_vertex_exec; ot->invoke = add_vertex_invoke; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -690,7 +690,7 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) /* api callbacks */ ot->exec = add_feather_vertex_exec; ot->invoke = add_feather_vertex_invoke; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 7a3f759e471..9a32cff04c3 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -50,23 +50,23 @@ /********************** generic poll functions *********************/ -int ED_maskediting_poll(bContext *C) +int ED_maskedit_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); if (sc) { - return ED_space_clip_maskediting_poll(C); + return ED_space_clip_maskedit_poll(C); } return FALSE; } -int ED_maskediting_mask_poll(bContext *C) +int ED_maskedit_mask_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); if (sc) { - return ED_space_clip_maskediting_mask_poll(C); + return ED_space_clip_maskedit_mask_poll(C); } return FALSE; @@ -232,7 +232,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) wmKeyMapItem *kmi; keymap = WM_keymap_find(keyconf, "Mask Editing", 0, 0); - keymap->poll = ED_maskediting_poll; + keymap->poll = ED_maskedit_poll; WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 70f13abd44f..d2efab8613a 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -92,8 +92,8 @@ void ED_mask_select_toggle_all(struct Mask *mask, int action); void ED_mask_select_flush_all(struct Mask *mask); /* mask_editor.c */ -int ED_maskediting_poll(struct bContext *C); -int ED_maskediting_mask_poll(struct bContext *C); +int ED_maskedit_poll(struct bContext *C); +int ED_maskedit_mask_poll(struct bContext *C); void ED_mask_size(struct bContext *C, int *width, int *height); void ED_mask_aspect(struct bContext *C, float *aspx, float *aspy); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 62450f4bc65..a1a232c7c61 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -313,7 +313,7 @@ void MASK_OT_layer_new(wmOperatorType *ot) /* api callbacks */ ot->exec = masklay_new_exec; - ot->poll = ED_maskediting_poll; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -347,7 +347,7 @@ void MASK_OT_layer_remove(wmOperatorType *ot) /* api callbacks */ ot->exec = masklay_remove_exec; - ot->poll = ED_maskediting_poll; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -754,7 +754,7 @@ void MASK_OT_slide_point(wmOperatorType *ot) /* api callbacks */ ot->invoke = slide_point_invoke; ot->modal = slide_point_modal; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -797,7 +797,7 @@ void MASK_OT_cyclic_toggle(wmOperatorType *ot) /* api callbacks */ ot->exec = cyclic_toggle_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -941,7 +941,7 @@ void MASK_OT_delete(wmOperatorType *ot) /* api callbacks */ ot->invoke = WM_operator_confirm; ot->exec = delete_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -992,7 +992,7 @@ void MASK_OT_switch_direction(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_switch_direction_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1051,7 +1051,7 @@ void MASK_OT_handle_type_set(wmOperatorType *ot) /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = set_handle_type_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1098,7 +1098,7 @@ void MASK_OT_hide_view_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_hide_view_clear_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1159,7 +1159,7 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_hide_view_set_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index eaec5ad9a8f..226b0fa14be 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -88,7 +88,7 @@ void MASK_OT_parent_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_parent_clear_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -167,7 +167,7 @@ void MASK_OT_parent_set(wmOperatorType *ot) //ot->invoke = mask_parent_set_invoke; ot->exec = mask_parent_set_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 4fee0a218a4..143bfec0ccc 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -214,7 +214,7 @@ void MASK_OT_select_all(wmOperatorType *ot) /* api callbacks */ ot->exec = select_all_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -362,7 +362,7 @@ void MASK_OT_select(wmOperatorType *ot) /* api callbacks */ ot->exec = select_exec; ot->invoke = select_invoke; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_UNDO; @@ -454,7 +454,7 @@ void MASK_OT_select_border(wmOperatorType *ot) ot->invoke = WM_border_select_invoke; ot->exec = border_select_exec; ot->modal = WM_border_select_modal; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_UNDO; @@ -550,7 +550,7 @@ void MASK_OT_select_lasso(wmOperatorType *ot) ot->invoke = WM_gesture_lasso_invoke; ot->modal = WM_gesture_lasso_modal; ot->exec = clip_lasso_select_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; ot->cancel = WM_gesture_lasso_cancel; /* flags */ @@ -651,7 +651,7 @@ void MASK_OT_select_circle(wmOperatorType *ot) ot->invoke = WM_gesture_circle_invoke; ot->modal = WM_gesture_circle_modal; ot->exec = circle_select_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -708,7 +708,7 @@ void MASK_OT_select_linked_pick(wmOperatorType *ot) /* api callbacks */ ot->invoke = mask_select_linked_pick_invoke; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -759,7 +759,7 @@ void MASK_OT_select_linked(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_select_linked_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 07ce9215e26..0c01487b2a9 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -85,7 +85,7 @@ void MASK_OT_shape_key_insert(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_shape_key_insert_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -134,7 +134,7 @@ void MASK_OT_shape_key_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_shape_key_clear_exec; - ot->poll = ED_maskediting_mask_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 89c7896d53c..4e98d2ae967 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1951,7 +1951,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) { SpaceClip *sc = CTX_wm_space_clip(C); if (sc) { - if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { + if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask) { MaskLayer *masklay = BKE_mask_layer_active(sc->mask); mask_to_keylist(&ads, masklay, &keys); } diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 6ac5ec59742..d55d32deaa4 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -198,7 +198,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc clip_draw_curfra_label(sc, x, 8.0f); /* movie clip animation */ - if ((sc->mode == SC_MODE_MASKEDITING) && sc->mask) { + if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask) { MaskLayer *masklay = BKE_mask_layer_active(sc->mask); if (masklay) { MaskLayerShape *masklay_shape; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index f16ef21b707..8bee06854e1 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -129,7 +129,7 @@ int ED_space_clip_tracking_frame_poll(bContext *C) return FALSE; } -int ED_space_clip_maskediting_poll(bContext *C) +int ED_space_clip_maskedit_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -140,9 +140,9 @@ int ED_space_clip_maskediting_poll(bContext *C) return FALSE; } -int ED_space_clip_maskediting_mask_poll(bContext *C) +int ED_space_clip_maskedit_mask_poll(bContext *C) { - if (ED_space_clip_maskediting_poll(C)) { + if (ED_space_clip_maskedit_poll(C)) { MovieClip *clip = CTX_data_edit_movieclip(C); if (clip) { @@ -681,7 +681,7 @@ int ED_space_clip_show_trackedit(SpaceClip *sc) int ED_space_clip_show_maskedit(SpaceClip *sc) { if (sc) { - return sc->mode == SC_MODE_MASKEDITING; + return sc->mode == SC_MODE_MASKEDIT; } return FALSE; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a7fe86e0eff..aec71d095f7 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1097,7 +1097,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) /* Grease Pencil */ clip_draw_grease_pencil((bContext *)C, 1); - if(sc->mode == SC_MODE_MASKEDITING) { + if(sc->mode == SC_MODE_MASKEDIT) { int x, y; int width, height; float zoomx, zoomy, aspx, aspy; @@ -1323,7 +1323,7 @@ static void clip_header_area_listener(ARegion *ar, wmNotifier *wmn) /* for proportional editmode only */ case ND_TOOLSETTINGS: /* TODO - should do this when in mask mode only but no datas available */ - // if(sc->mode == SC_MODE_MASKEDITING) + // if(sc->mode == SC_MODE_MASKEDIT) { ED_region_tag_redraw(ar); } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index e83f1b4495a..213195eb9c8 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1045,7 +1045,7 @@ typedef enum eSpaceClip_Mode { SC_MODE_TRACKING = 0, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION, - SC_MODE_MASKEDITING, + SC_MODE_MASKEDIT, } eSpaceClip_Mode; /* SpaceClip->view */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8fe33f3e80f..bbe9595029a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2983,7 +2983,7 @@ static void rna_def_space_clip(BlenderRNA *brna) {SC_MODE_RECONSTRUCTION, "RECONSTRUCTION", ICON_SNAP_FACE, "Reconstruction", "Show tracking/reconstruction tools"}, {SC_MODE_DISTORTION, "DISTORTION", ICON_GRID, "Distortion", "Show distortion tools"}, - {SC_MODE_MASKEDITING, "MASKEDITING", ICON_MOD_MASK, "Mask editing", "Show mask editing tools"}, + {SC_MODE_MASKEDIT, "MASKEDIT", ICON_MOD_MASK, "Mask editing", "Show mask editing tools"}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3 From 5024996eea206252adc098f44c9a3a1d01ae6167 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 4 Jun 2012 18:07:29 +0000 Subject: * modified vieweroperation to not calculate based on the DO_NODE_OUTPUT flag of the editorbNode. --- source/blender/compositor/nodes/COM_ViewerNode.cpp | 2 +- .../operations/COM_BlurBaseOperation.cpp | 9 ++- .../operations/COM_FastGaussianBlurOperation.cpp | 73 ++++++++++++---------- .../operations/COM_FastGaussianBlurOperation.h | 5 +- .../operations/COM_ViewerBaseOperation.cpp | 6 +- .../operations/COM_ViewerBaseOperation.h | 2 +- 6 files changed, 55 insertions(+), 42 deletions(-) diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index db4fd115d73..679589a7ce1 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -37,7 +37,7 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * Image *image = (Image*)this->getbNode()->id; ImageUser * imageUser = (ImageUser*) this->getbNode()->storage; bNode *editorNode = this->getbNode(); - if (imageSocket->isConnected() && (editorNode->flag & NODE_DO_OUTPUT)) { + if (imageSocket->isConnected()) { ViewerOperation *viewerOperation = new ViewerOperation(); viewerOperation->setColorManagement(context->getScene()->r.color_mgt_flag & R_COLOR_MANAGEMENT); viewerOperation->setColorPredivide(context->getScene()->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index babea459d6a..2280ee3a435 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -101,7 +101,10 @@ void BlurBaseOperation::deinitExecution() void BlurBaseOperation::updateSize(MemoryBuffer **memoryBuffers) { - float result[4]; - this->getInputSocketReader(1)->read(result, 0, 0, COM_PS_NEAREST, memoryBuffers); - this->size = result[0]; + if (!this->sizeavailable) { + float result[4]; + this->getInputSocketReader(1)->read(result, 0, 0, COM_PS_NEAREST, memoryBuffers); + this->size = result[0]; + this->sizeavailable = true; + } } diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index ad8f3b12387..ad58631f2c1 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -26,13 +26,12 @@ FastGaussianBlurOperation::FastGaussianBlurOperation(): BlurBaseOperation() { - this->iirgaus = false; + this->iirgaus = NULL; } void FastGaussianBlurOperation::executePixel(float *color,int x, int y, MemoryBuffer *inputBuffers[], void *data) { MemoryBuffer *newData = (MemoryBuffer*)data; - newData->read(color, x, y); } @@ -51,10 +50,7 @@ bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti *input, Re } else { if (this->iirgaus) { - newInput.xmax = input->xmax + (sx); - newInput.xmin = input->xmin - (sx); - newInput.ymax = input->ymax + (sy); - newInput.ymin = input->ymin - (sy); + return false; } else { newInput.xmin = 0; @@ -66,38 +62,51 @@ bool FastGaussianBlurOperation::determineDependingAreaOfInterest(rcti *input, Re } } -void *FastGaussianBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +void FastGaussianBlurOperation::initExecution() { - MemoryBuffer *newBuf = (MemoryBuffer*)this->inputProgram->initializeTileData(rect, memoryBuffers); - MemoryBuffer *copy = newBuf->duplicate(); - updateSize(memoryBuffers); - - int c; - sx = data->sizex * this->size/2.0f; - sy = data->sizey * this->size/2.0f; - this->iirgaus = true; - - if ((sx == sy) && (sx > 0.f)) { - for (c=0; ciirgaus) { + delete this->iirgaus; + this->iirgaus = NULL; } - else { - if (sx > 0.f) { + BlurBaseOperation::deinitMutex(); +} + +void *FastGaussianBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + BLI_mutex_lock(this->getMutex()); + if (!iirgaus) { + MemoryBuffer *newBuf = (MemoryBuffer*)this->inputProgram->initializeTileData(rect, memoryBuffers); + MemoryBuffer *copy = newBuf->duplicate(); + updateSize(memoryBuffers); + + int c; + sx = data->sizex * this->size/2.0f; + sy = data->sizey * this->size/2.0f; + + if ((sx == sy) && (sx > 0.f)) { for (c=0; c 0.f) { - for (c=0; c 0.f) { + for (c=0; c 0.f) { + for (c=0; ciirgaus = copy; } - return copy; -} - -void FastGaussianBlurOperation::deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data) -{ - MemoryBuffer *newData = (MemoryBuffer*)data; - delete newData; + BLI_mutex_unlock(this->getMutex()); + return iirgaus; } void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, int chan, int xy) diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h index 6c3e373472b..1f71fe7f9ed 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h @@ -30,7 +30,7 @@ class FastGaussianBlurOperation: public BlurBaseOperation { private: float sx; float sy; - bool iirgaus; + MemoryBuffer* iirgaus; public: FastGaussianBlurOperation(); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); @@ -38,7 +38,8 @@ public: static void IIR_gauss(MemoryBuffer *src, float sigma, int channel, int xy); void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); - void deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data); + void deinitExecution(); + void initExecution(); }; #endif diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 44b4c26fb64..71fc53e8f8e 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -50,8 +50,9 @@ ViewerBaseOperation::ViewerBaseOperation() : NodeOperation() void ViewerBaseOperation::initExecution() { - // When initializing the tree during initial load the width and height can be zero. - initImage(); + if (isActiveViewerOutput()) { + initImage(); + } } void ViewerBaseOperation::initImage() @@ -79,7 +80,6 @@ void ViewerBaseOperation::initImage() } void ViewerBaseOperation:: updateImage(rcti *rect) { - /// @todo: introduce new event to update smaller area WM_main_add_notifier(NC_WINDOW|ND_DRAW, NULL); } diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h index 58101911550..f5f30809f65 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h @@ -42,7 +42,7 @@ protected: bool doColorPredivide; public: - bool isOutputOperation(bool rendering) const {return true;} + bool isOutputOperation(bool rendering) const {return isActiveViewerOutput();} void initExecution(); void deinitExecution(); void setImage(Image *image) {this->image = image;} -- cgit v1.2.3 From ca7197b6209b82af4b87f851bf5d6becdb7625b2 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 4 Jun 2012 19:00:13 +0000 Subject: Cycles / OSL: * __OSL__ is now defined for CPU when building with OSL. * First batch of compile fixes, remove some unneeded std namespace declarations and added missing includes. --- intern/cycles/kernel/kernel_types.h | 4 +++- intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp | 12 +++++++----- intern/cycles/kernel/osl/bsdf_diffuse.cpp | 6 ++++-- intern/cycles/kernel/osl/bsdf_oren_nayar.cpp | 3 ++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d119057ac67..4fd57a5f2b3 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -39,6 +39,9 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_CPU__ #define __KERNEL_SHADING__ #define __KERNEL_ADV_SHADING__ +#ifdef WITH_OSL +#define __OSL__ +#endif #endif #ifdef __KERNEL_CUDA__ @@ -107,7 +110,6 @@ CCL_NAMESPACE_BEGIN #endif //#define __MULTI_LIGHT__ -//#define __OSL__ //#define __SOBOL_FULL_SCREEN__ //#define __QBVH__ diff --git a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp index a38c5b55cf5..808837bf211 100644 --- a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp +++ b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp @@ -36,6 +36,8 @@ #include "osl_closures.h" +#include "util_math.h" + CCL_NAMESPACE_BEGIN using namespace OSL; @@ -50,7 +52,7 @@ public: void setup() { - m_sigma = std::max(m_sigma, 0.01f); + m_sigma = max(m_sigma, 0.01f); m_invsigma2 = 1.0f/(m_sigma * m_sigma); } @@ -89,7 +91,7 @@ public: float cosHO = fabsf(omega_out.dot(H)); float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = std::max(cosNHdivHO, 0.00001f); + cosNHdivHO = max(cosNHdivHO, 0.00001f); float fac1 = 2 * fabsf(cosNHdivHO * cosNO); float fac2 = 2 * fabsf(cosNHdivHO * cosNI); @@ -99,7 +101,7 @@ public: float cotangent2 = (cosNH * cosNH) / sinNH2; float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically + float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically float out = 0.25f * (D * G) / cosNO; @@ -133,7 +135,7 @@ public: float cosHO = fabsf(omega_out.dot(H)); float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = std::max(cosNHdivHO, 0.00001f); + cosNHdivHO = max(cosNHdivHO, 0.00001f); float fac1 = 2 * fabsf(cosNHdivHO * cosNO); float fac2 = 2 * fabsf(cosNHdivHO * cosNI); @@ -143,7 +145,7 @@ public: float cotangent2 = (cosNH * cosNH) / sinNH2; float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically + float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically float power = 0.25f * (D * G) / cosNO; diff --git a/intern/cycles/kernel/osl/bsdf_diffuse.cpp b/intern/cycles/kernel/osl/bsdf_diffuse.cpp index 0d4b3fa471f..352e75f73c9 100644 --- a/intern/cycles/kernel/osl/bsdf_diffuse.cpp +++ b/intern/cycles/kernel/osl/bsdf_diffuse.cpp @@ -36,6 +36,8 @@ #include "osl_closures.h" +#include "util_math.h" + CCL_NAMESPACE_BEGIN using namespace OSL; @@ -69,7 +71,7 @@ public: Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const { - float cos_pi = std::max(m_N.dot(omega_in),0.0f) * (float) M_1_PI; + float cos_pi = max(m_N.dot(omega_in),0.0f) * (float) M_1_PI; pdf = cos_pi; return Color3 (cos_pi, cos_pi, cos_pi); } @@ -137,7 +139,7 @@ public: Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const { - float cos_pi = std::max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI; + float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI; pdf = cos_pi; return Color3 (cos_pi, cos_pi, cos_pi); } diff --git a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp b/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp index 5d2ca909f93..dd6c59d98c2 100644 --- a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp +++ b/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp @@ -19,6 +19,7 @@ #include #include #include "osl_closures.h" +#include "util_math.h" CCL_NAMESPACE_BEGIN @@ -118,7 +119,7 @@ private: float t = l.dot(v) - nl * nv; if(t > 0.0f) { - t /= max(nl, vl) + 1e-8f; + t /= max(nl, nv) + 1e-8f; } return nl * (m_a + m_b * t); } -- cgit v1.2.3 From d9589bf0dd7a5bbaa0560704c8fbf1b11ec0166d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 Jun 2012 19:38:10 +0000 Subject: Cycles: fix spot lamp emitting light in two directions. --- intern/cycles/kernel/kernel_light.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 76552400f9c..a056cd71bb1 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -231,7 +231,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, float spot_angle = data2.y; float spot_smooth = data2.z; - float eval_fac = fabsf(dot(dir, I)); + float eval_fac = dot(dir, I); if(eval_fac <= spot_angle) { eval_fac = 0.0f; -- cgit v1.2.3 From 4e338e894f9fb0fa18e5594c2648b05c8f92d4c5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 4 Jun 2012 19:38:33 +0000 Subject: Cycles: support for image sequences in image/environment texture node. --- intern/cycles/blender/blender_shader.cpp | 18 ++--- intern/cycles/blender/blender_util.h | 8 +++ source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_image.h | 1 + source/blender/blenkernel/intern/image.c | 38 +++++++--- source/blender/blenloader/intern/readfile.c | 23 ++++++ source/blender/editors/space_node/drawnode.c | 84 +++++++++++++--------- source/blender/makesdna/DNA_node_types.h | 2 + source/blender/makesrna/intern/rna_nodetree.c | 63 ++++++++++------ .../shader/nodes/node_shader_tex_environment.c | 4 ++ .../nodes/shader/nodes/node_shader_tex_image.c | 4 ++ 11 files changed, 172 insertions(+), 75 deletions(-) diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 75cc9115531..130b73a2808 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -106,7 +106,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map mapping->max = get_float3(b_mapping.max()); } -static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNode b_node) +static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNode b_node) { ShaderNode *node = NULL; @@ -343,7 +343,7 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Shader ImageTextureNode *image = new ImageTextureNode(); /* todo: handle generated/builtin images */ if(b_image) - image->filename = blender_absolute_path(b_data, b_image, b_image.filepath()); + image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); node = image; @@ -354,7 +354,7 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Shader BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); if(b_image) - env->filename = blender_absolute_path(b_data, b_image, b_image.filepath()); + env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); @@ -530,7 +530,7 @@ static void set_default_value(ShaderInput *input, BL::NodeSocket sock) } } -static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) +static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; @@ -578,10 +578,10 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr set_default_value(proxy->inputs[0], b_output->group_socket()); } - add_nodes(b_data, graph, b_group_ntree, group_sockmap); + add_nodes(b_data, b_scene, graph, b_group_ntree, group_sockmap); } else { - ShaderNode *node = add_node(b_data, graph, BL::ShaderNode(*b_node)); + ShaderNode *node = add_node(b_data, b_scene, graph, BL::ShaderNode(*b_node)); if(node) { BL::Node::inputs_iterator b_input; @@ -671,7 +671,7 @@ void BlenderSync::sync_materials() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(b_data, graph, b_ntree, sock_to_node); + add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; @@ -712,7 +712,7 @@ void BlenderSync::sync_world() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(b_data, graph, b_ntree, sock_to_node); + add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); } else if(b_world) { ShaderNode *closure, *out; @@ -771,7 +771,7 @@ void BlenderSync::sync_lamps() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(b_data, graph, b_ntree, sock_to_node); + add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index b01fa81ee40..b9c60738b36 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -53,6 +53,7 @@ int rna_Object_is_deform_modified(void *ob, void *scene, int settings); void BLI_timestr(double _time, char *str); void rna_ColorRamp_eval(void *coba, float position, float color[4]); void rna_Scene_frame_set(void *scene, int frame, float subframe); +void BKE_image_user_file_path(void *iuser, void *ima, int cfra, char *path); } @@ -101,6 +102,13 @@ static inline bool BKE_object_is_deform_modified(BL::Object self, BL::Scene scen return rna_Object_is_deform_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false; } +static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, int cfra) +{ + char filepath[1024]; + BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, cfra, filepath); + return string(filepath); +} + static inline void scene_frame_set(BL::Scene scene, int frame) { rna_Scene_frame_set(scene.ptr.data, frame, 0.0f); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 24386730ddb..6fccf819d05 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 263 -#define BLENDER_SUBVERSION 8 +#define BLENDER_SUBVERSION 9 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index ac3daef77f7..279ec272fe8 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -157,6 +157,7 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); void BKE_image_user_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); void BKE_image_user_check_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); int BKE_image_user_frame_get(const struct ImageUser *iuser, int cfra, int fieldnr); +void BKE_image_user_file_path(struct ImageUser *iuser, struct Image *ima, int cfra, char *path); /* sets index offset for multilayer files */ struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 3748a474ddd..9dc5463edab 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2084,8 +2084,7 @@ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) { struct ImBuf *ibuf; - unsigned short numlen; - char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX]; + char name[FILE_MAX]; int flag; /* XXX temp stuff? */ @@ -2093,11 +2092,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) ima->tpageflag |= IMA_TPAGE_REFRESH; ima->lastframe = frame; - BLI_strncpy(name, ima->name, sizeof(name)); - BLI_stringdec(name, head, tail, &numlen); - BLI_stringenc(name, head, tail, numlen, frame); - - BLI_path_abs(name, ID_BLEND_PATH(G.main, &ima->id)); + BKE_image_user_file_path(iuser, ima, frame, name); flag = IB_rect | IB_multilayer; if (ima->flag & IMA_DO_PREMUL) @@ -2209,8 +2204,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) if (ima->anim == NULL) { char str[FILE_MAX]; - BLI_strncpy(str, ima->name, FILE_MAX); - BLI_path_abs(str, ID_BLEND_PATH(G.main, &ima->id)); + BKE_image_user_file_path(iuser, ima, frame, str); /* FIXME: make several stream accessible in image editor, too*/ ima->anim = openanim(str, IB_rect, 0); @@ -2273,8 +2267,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) flag |= IB_premul; /* get the right string */ - BLI_strncpy(str, ima->name, sizeof(str)); - BLI_path_abs(str, ID_BLEND_PATH(G.main, &ima->id)); + BKE_image_user_file_path(iuser, ima, cfra, str); /* read ibuf */ ibuf = IMB_loadiffname(str, flag); @@ -2748,6 +2741,29 @@ void BKE_image_user_check_frame_calc(ImageUser *iuser, int cfra, int fieldnr) } } +void BKE_image_user_file_path(ImageUser *iuser, Image *ima, int cfra, char *filepath) +{ + BLI_strncpy(filepath, ima->name, FILE_MAX); + + if (ima->source == IMA_SRC_SEQUENCE) { + char head[FILE_MAX], tail[FILE_MAX]; + unsigned short numlen; + int frame; + + if(iuser) { + BKE_image_user_frame_calc(iuser, cfra, 0); + frame = iuser->framenr; + } + else { + } + + BLI_stringdec(filepath, head, tail, &numlen); + BLI_stringenc(filepath, head, tail, numlen, frame); + } + + BLI_path_abs(filepath, ID_BLEND_PATH(G.main, &ima->id)); +} + int BKE_image_has_alpha(struct Image *image) { ImBuf *ibuf; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 826d9d196b8..a4d8457bd2d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6897,6 +6897,22 @@ static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree) } } +static void do_version_ntree_image_user_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) +{ + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) { + if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) { + NodeTexImage *tex = node->storage; + + tex->iuser.frames= 1; + tex->iuser.sfra= 1; + tex->iuser.fie_ima= 2; + tex->iuser.ok= 1; + } + } +} + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -7608,6 +7624,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) { + bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); + + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_ntree_image_user_264); + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 5a8bc5da324..aa8a68677c0 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1188,6 +1188,47 @@ static void node_common_set_butfunc(bNodeType *ntype) } /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */ + +static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *imaptr, PointerRNA *iuserptr) +{ + uiLayout *col; + int source; + + if(!imaptr->data) + return; + + col = uiLayoutColumn(layout, 0); + + uiItemR(col, imaptr, "source", 0, "", ICON_NONE); + + source = RNA_enum_get(imaptr, "source"); + + if (source == IMA_SRC_SEQUENCE) { + /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ + Scene *scene = CTX_data_scene(C); + ImageUser *iuser = iuserptr->data; + char numstr[32]; + const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0); + BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr); + uiItemL(layout, numstr, ICON_NONE); + } + + if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + col = uiLayoutColumn(layout, 1); + uiItemR(col, iuserptr, "frame_duration", 0, NULL, ICON_NONE); + uiItemR(col, iuserptr, "frame_start", 0, NULL, ICON_NONE); + uiItemR(col, iuserptr, "frame_offset", 0, NULL, ICON_NONE); + uiItemR(col, iuserptr, "use_cyclic", 0, NULL, ICON_NONE); + uiItemR(col, iuserptr, "use_auto_refresh", UI_ITEM_R_ICON_ONLY, NULL, ICON_NONE); + } + + col = uiLayoutColumn(layout, 0); + + if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER) + uiItemR(col, iuserptr, "layer", 0, NULL, ICON_NONE); + +} + static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; @@ -1259,16 +1300,25 @@ static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), Po static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr) { + PointerRNA imaptr = RNA_pointer_get(ptr, "image"); + PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); + uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); -} + node_buts_image_user(layout, C, &imaptr, &iuserptr); +} static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr) { + PointerRNA imaptr = RNA_pointer_get(ptr, "image"); + PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); + uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + + node_buts_image_user(layout, C, &imaptr, &iuserptr); } static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1391,11 +1441,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiLayout *col; bNode *node = ptr->data; PointerRNA imaptr; PropertyRNA *prop; - int source; uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); @@ -1405,35 +1453,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * if (!prop || RNA_property_type(prop) != PROP_POINTER) return; imaptr = RNA_property_pointer_get(ptr, prop); - col = uiLayoutColumn(layout, 0); - - uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE); - - source = RNA_enum_get(&imaptr, "source"); - - if (source == IMA_SRC_SEQUENCE) { - /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ - Scene *scene = CTX_data_scene(C); - ImageUser *iuser = node->storage; - char numstr[32]; - const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0); - BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr); - uiItemL(layout, numstr, ICON_NONE); - } - - if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { - col = uiLayoutColumn(layout, 1); - uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_auto_refresh", UI_ITEM_R_ICON_ONLY, NULL, ICON_NONE); - } - - col = uiLayoutColumn(layout, 0); - - if (RNA_enum_get(&imaptr, "type") == IMA_TYPE_MULTILAYER) - uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE); + node_buts_image_user(layout, C, &imaptr, ptr); } static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5b87ecc44ae..59506f31b60 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -563,6 +563,7 @@ typedef struct NodeTexSky { typedef struct NodeTexImage { NodeTexBase base; + ImageUser iuser; int color_space, pad; } NodeTexImage; @@ -572,6 +573,7 @@ typedef struct NodeTexChecker { typedef struct NodeTexEnvironment { NodeTexBase base; + ImageUser iuser; int color_space, projection; } NodeTexEnvironment; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 30c705fb7fa..562684799b4 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1429,6 +1429,12 @@ static void def_sh_tex_environment(StructRNA *srna) RNA_def_property_ui_text(prop, "Projection", "Projection of the input image"); RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "iuser"); + RNA_def_property_ui_text(prop, "Image User", + "Parameters defining which layer, pass and frame of the image is displayed"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_sh_tex_image(StructRNA *srna) @@ -1458,6 +1464,13 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_property_enum_items(prop, prop_color_space_items); RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "iuser"); + RNA_def_property_ui_text(prop, "Image User", + "Parameters defining which layer, pass and frame of the image is displayed"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_sh_tex_gradient(StructRNA *srna) @@ -1830,29 +1843,10 @@ static void def_cmp_levels(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_cmp_image(StructRNA *srna) +static void def_node_image_user(StructRNA *srna) { PropertyRNA *prop; - -#if 0 - static EnumPropertyItem type_items[] = { - {IMA_SRC_FILE, "IMAGE", 0, "Image", ""}, - {IMA_SRC_MOVIE, "MOVIE", "Movie", ""}, - {IMA_SRC_SEQUENCE, "SEQUENCE", "Sequence", ""}, - {IMA_SRC_GENERATED, "GENERATED", "Generated", ""}, - {0, NULL, 0, NULL, NULL} - }; -#endif - - prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "id"); - RNA_def_property_struct_type(prop, "Image"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Image", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - - RNA_def_struct_sdna_from(srna, "ImageUser", "storage"); - + prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "frames"); RNA_def_property_range(prop, 0, MAXFRAMEF); @@ -1893,6 +1887,31 @@ static void def_cmp_image(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_image_layer_update"); } +static void def_cmp_image(StructRNA *srna) +{ + PropertyRNA *prop; + +#if 0 + static EnumPropertyItem type_items[] = { + {IMA_SRC_FILE, "IMAGE", 0, "Image", ""}, + {IMA_SRC_MOVIE, "MOVIE", "Movie", ""}, + {IMA_SRC_SEQUENCE, "SEQUENCE", "Sequence", ""}, + {IMA_SRC_GENERATED, "GENERATED", "Generated", ""}, + {0, NULL, 0, NULL, NULL} + }; +#endif + + prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Image"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Image", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "ImageUser", "storage"); + def_node_image_user(srna); +} + static void def_cmp_render_layers(StructRNA *srna) { PropertyRNA *prop; @@ -3454,7 +3473,7 @@ static void def_tex_image(StructRNA *srna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - + /* is this supposed to be exposed? not sure.. */ #if 0 prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index e5dc64aca05..e3300c89a01 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -46,6 +46,10 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode* no default_color_mapping(&tex->base.color_mapping); tex->color_space = SHD_COLORSPACE_COLOR; tex->projection = SHD_PROJ_EQUIRECTANGULAR; + tex->iuser.frames= 1; + tex->iuser.sfra= 1; + tex->iuser.fie_ima= 2; + tex->iuser.ok= 1; node->storage = tex; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index db1c9081471..d4d43c1430c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -46,6 +46,10 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode* node, bN default_tex_mapping(&tex->base.tex_mapping); default_color_mapping(&tex->base.color_mapping); tex->color_space = SHD_COLORSPACE_COLOR; + tex->iuser.frames= 1; + tex->iuser.sfra= 1; + tex->iuser.fie_ima= 2; + tex->iuser.ok= 1; node->storage = tex; } -- cgit v1.2.3 From 6f0ad4ff0f53e4e2499d3e92c5cbad7582d36b9a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 4 Jun 2012 19:43:12 +0000 Subject: A few UI messages fixes. --- source/blender/editors/mask/mask_ops.c | 2 +- source/blender/editors/mask/mask_relationships.c | 4 ++-- source/blender/editors/mask/mask_select.c | 2 +- source/blender/makesrna/intern/rna_mask.c | 4 ++-- source/blender/makesrna/intern/rna_userdef.c | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index a1a232c7c61..a0c79f4c2c9 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -759,7 +759,7 @@ void MASK_OT_slide_point(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide slide feather instead of vertex"); + RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide feather instead of vertex"); } /******************** toggle cyclic *********************/ diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 226b0fa14be..0e893ee2f9f 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -82,7 +82,7 @@ void MASK_OT_parent_clear(wmOperatorType *ot) { /* identifiers */ ot->name = "Clear Parent"; - ot->description = "Clear the masks parenting"; + ot->description = "Clear the mask's parenting"; ot->idname = "MASK_OT_parent_clear"; /* api callbacks */ @@ -160,7 +160,7 @@ void MASK_OT_parent_set(wmOperatorType *ot) { /* identifiers */ ot->name = "Make Parent"; - ot->description = "Set the masks parenting"; + ot->description = "Set the mask's parenting"; ot->idname = "MASK_OT_parent_set"; /* api callbacks */ diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 143bfec0ccc..55e09529320 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -208,7 +208,7 @@ static int select_all_exec(bContext *C, wmOperator *op) void MASK_OT_select_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "Select or Deselect All"; + ot->name = "(De)select All"; ot->description = "Change selection of all curve points"; ot->idname = "MASK_OT_select_all"; diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index c356cae81af..1532e2e7199 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -324,7 +324,7 @@ static void rna_def_maskParent(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; srna = RNA_def_struct(brna, "MaskParent", NULL); - RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for maskign element"); + RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for masking element"); /* use_parent */ prop = RNA_def_property(srna, "use_parent", PROP_BOOLEAN, PROP_NONE); @@ -497,7 +497,7 @@ static void rna_def_maskSpline(BlenderRNA *brna) rna_def_maskSplinePoint(brna); srna = RNA_def_struct(brna, "MaskSpline", NULL); - RNA_def_struct_ui_text(srna, "Mask spline", "Single spline used for defining mash shape"); + RNA_def_struct_ui_text(srna, "Mask spline", "Single spline used for defining mask shape"); /* weight interpolation */ prop = RNA_def_property(srna, "weight_interpolation", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index ec215120f0c..2df69e78233 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1992,27 +1992,27 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) prop = RNA_def_property(srna, "meta_strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_meta"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Meta Strips", "Meta Strip - Unselected. For grouping related strips"); + RNA_def_property_ui_text(prop, "Meta Strips", "Meta Strip - Unselected (for grouping related strips)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "meta_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_meta_sel"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Meta Strips Selected", "Meta Strip - Selected. For grouping related strips"); + RNA_def_property_ui_text(prop, "Meta Strips Selected", "Meta Strip - Selected (for grouping related strips)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "sound_strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_sound"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Sound Strips", - "Sound Strip - Unselected. For timing speaker sounds"); + "Sound Strip - Unselected (for timing speaker sounds)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "sound_strips_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "nla_sound_sel"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Sound Strips Selected", - "Sound Strip - Selected. For timing speaker sounds"); + "Sound Strip - Selected (for timing speaker sounds)"); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "tweak", PROP_FLOAT, PROP_COLOR_GAMMA); -- cgit v1.2.3 From 510f98576a1b392226330dd854e049f712ddf62c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 4 Jun 2012 19:53:50 +0000 Subject: Cycles / OSL: * Compile fixes, missing ShaderClosure argument for eval functions. (r40163) --- intern/cycles/kernel/kernel_shader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 8e0d36705ad..53a41d58e20 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -520,7 +520,7 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) if(CLOSURE_IS_EMISSION(sc->type)) { #ifdef __OSL__ - eval += OSLShader::emissive_eval(sd)*sc->weight; + eval += OSLShader::emissive_eval(sd, sc)*sc->weight; #else eval += svm_emissive_eval(sd, sc)*sc->weight; #endif @@ -624,7 +624,7 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, if(CLOSURE_IS_VOLUME(sc->type)) { #ifdef __OSL__ - eval += OSLShader::volume_eval_phase(sd, omega_in, omega_out); + eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out); #else eval += volume_eval_phase(sd, sc, omega_in, omega_out); #endif -- cgit v1.2.3 From 5189356d587f51280c9486980d9f5e774338540e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 20:11:09 +0000 Subject: style cleanup --- intern/bsp/intern/BSP_CSGMesh_CFIterator.h | 4 +- intern/container/intern/CTR_List.cpp | 115 +++++++++------------ intern/ghost/intern/GHOST_DisplayManagerNULL.h | 2 +- intern/ghost/intern/GHOST_WindowNULL.h | 26 ++--- intern/ghost/test/multitest/EventToBuf.c | 2 +- intern/memutil/MEM_Allocator.h | 2 +- intern/memutil/MEM_RefCountPtr.h | 2 +- intern/memutil/MEM_SmartPtr.h | 2 +- intern/mikktspace/mikktspace.c | 44 ++++---- intern/raskter/raskter.c | 2 +- intern/utfconv/utfconv.c | 2 +- source/blender/blenkernel/intern/particle_system.c | 2 +- source/blender/blenkernel/intern/writeffmpeg.c | 8 +- source/blender/blenlib/intern/math_color.c | 28 ++--- source/blender/blenlib/intern/string_utf8.c | 4 +- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/collada/AnimationImporter.cpp | 2 +- .../compositor/operations/COM_ImageOperation.cpp | 4 +- source/blender/editors/interface/interface_panel.c | 13 +-- source/blender/editors/space_clip/clip_buttons.c | 2 +- source/blender/editors/space_clip/clip_editor.c | 10 +- source/blender/editors/space_clip/space_clip.c | 8 +- source/blender/editors/space_node/drawnode.c | 4 +- source/blender/editors/space_node/node_edit.c | 16 +-- source/blender/editors/space_node/node_select.c | 2 +- .../editors/transform/transform_conversions.c | 2 +- source/blender/gpu/intern/gpu_material.c | 2 +- source/blender/imbuf/intern/dds/ColorBlock.cpp | 2 +- source/blender/modifiers/intern/MOD_explode.c | 12 +-- source/blender/modifiers/intern/MOD_solidify.c | 2 +- source/blender/nodes/intern/node_common.c | 2 +- source/blender/python/intern/bpy_library.c | 24 ++--- source/blender/windowmanager/intern/wm_operators.c | 4 +- source/gameengine/Ketsji/KX_Scene.cpp | 8 +- 34 files changed, 174 insertions(+), 192 deletions(-) diff --git a/intern/bsp/intern/BSP_CSGMesh_CFIterator.h b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h index cadd3df4360..928d04eda20 100644 --- a/intern/bsp/intern/BSP_CSGMesh_CFIterator.h +++ b/intern/bsp/intern/BSP_CSGMesh_CFIterator.h @@ -127,10 +127,10 @@ BSP_CSGMeshVertexIt_Construct( BSP_CSGMesh_VertexIt * v_it = new BSP_CSGMesh_VertexIt; v_it->mesh = mesh; - if( output->num_elements > 0 ) + if ( output->num_elements > 0 ) v_it->pos = &mesh->VertexSet()[0]; output->it = v_it; -}; +} /** diff --git a/intern/container/intern/CTR_List.cpp b/intern/container/intern/CTR_List.cpp index 2fc7b0261ef..c72d3ccf0d8 100644 --- a/intern/container/intern/CTR_List.cpp +++ b/intern/container/intern/CTR_List.cpp @@ -33,118 +33,95 @@ #include "CTR_List.h" -CTR_Link:: -CTR_Link( -) : +CTR_Link::CTR_Link() : m_next(0), m_prev(0) { } -CTR_Link:: -CTR_Link( - CTR_Link *next, - CTR_Link *prev -) : +CTR_Link::CTR_Link(CTR_Link *next, CTR_Link *prev) : m_next(next), m_prev(prev) { } - CTR_Link * -CTR_Link:: -getNext( -) const { +CTR_Link * +CTR_Link::getNext() const +{ return m_next; } - CTR_Link * -CTR_Link:: -getPrev( -) const { +CTR_Link * +CTR_Link::getPrev() const +{ return m_prev; } - bool -CTR_Link:: -isHead( -) const { +bool +CTR_Link::isHead() const +{ return m_prev == 0; } - bool -CTR_Link:: -isTail( -) const { +bool +CTR_Link::isTail() const +{ return m_next == 0; } - void -CTR_Link:: -insertBefore( - CTR_Link *link -) { - m_next = link; - m_prev = link->m_prev; - m_next->m_prev = this; - m_prev->m_next = this; +void +CTR_Link::insertBefore(CTR_Link *link) +{ + m_next = link; + m_prev = link->m_prev; + m_next->m_prev = this; + m_prev->m_next = this; } - void -CTR_Link:: -insertAfter( - CTR_Link *link -) { - m_next = link->m_next; - m_prev = link; - m_next->m_prev = this; - m_prev->m_next = this; +void +CTR_Link::insertAfter(CTR_Link *link) +{ + m_next = link->m_next; + m_prev = link; + m_next->m_prev = this; + m_prev->m_next = this; } - void -CTR_Link:: -remove( -) { - m_next->m_prev = m_prev; - m_prev->m_next = m_next; +void +CTR_Link::remove() +{ + m_next->m_prev = m_prev; + m_prev->m_next = m_next; } -CTR_List:: -CTR_List( -) : +CTR_List::CTR_List() : m_head(&m_tail, 0), m_tail(0, &m_head) { } - CTR_Link * -CTR_List:: -getHead( -) const { +CTR_Link * +CTR_List:: getHead() const +{ return m_head.getNext(); } - CTR_Link * -CTR_List:: -getTail( -) const { +CTR_Link * +CTR_List::getTail() const +{ return m_tail.getPrev(); } - void -CTR_List:: -addHead( - CTR_Link *link -) { +void +CTR_List::addHead(CTR_Link *link) +{ link->insertAfter(&m_head); } - void -CTR_List:: -addTail( - CTR_Link *link -) { +void +CTR_List::addTail(CTR_Link *link) +{ link->insertBefore(&m_tail); } diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h index eb116e30d2d..4d5a0b008dc 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerNULL.h +++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h @@ -41,7 +41,7 @@ public: GHOST_TSuccess getNumDisplaySettings( GHOST_TUns8 display, GHOST_TInt32& numSettings ) const{ return GHOST_kFailure; } GHOST_TSuccess getDisplaySetting( GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting ) const { return GHOST_kFailure; } GHOST_TSuccess getCurrentDisplaySetting( GHOST_TUns8 display, GHOST_DisplaySetting& setting ) const { return getDisplaySetting(display,GHOST_TInt32(0),setting); } - GHOST_TSuccess setCurrentDisplaySetting( GHOST_TUns8 display, const GHOST_DisplaySetting& setting ){ return GHOST_kSuccess; } + GHOST_TSuccess setCurrentDisplaySetting( GHOST_TUns8 display, const GHOST_DisplaySetting& setting ) { return GHOST_kSuccess; } private: GHOST_SystemNULL * m_system; diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index cde2cb0ba76..dcbb7d2b346 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -60,27 +60,27 @@ public: } protected: - GHOST_TSuccess installDrawingContext( GHOST_TDrawingContextType type ){ return GHOST_kSuccess; } - GHOST_TSuccess removeDrawingContext( ){ return GHOST_kSuccess; } - GHOST_TSuccess setWindowCursorGrab( GHOST_TGrabCursorMode mode ){ return GHOST_kSuccess; } - GHOST_TSuccess setWindowCursorShape( GHOST_TStandardCursor shape ){ return GHOST_kSuccess; } + GHOST_TSuccess installDrawingContext( GHOST_TDrawingContextType type ) { return GHOST_kSuccess; } + GHOST_TSuccess removeDrawingContext( ) { return GHOST_kSuccess; } + GHOST_TSuccess setWindowCursorGrab( GHOST_TGrabCursorMode mode ) { return GHOST_kSuccess; } + GHOST_TSuccess setWindowCursorShape( GHOST_TStandardCursor shape ) { return GHOST_kSuccess; } GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY ) { return GHOST_kSuccess; } - GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color ){ return GHOST_kSuccess; } + GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color ) { return GHOST_kSuccess; } bool getValid( ) const { return true; } - void setTitle( const STR_String& title ){ /* nothing */ } + void setTitle( const STR_String& title ) { /* nothing */ } void getTitle( STR_String& title ) const { title= "untitled"; } void getWindowBounds( GHOST_Rect& bounds ) const { getClientBounds(bounds); } void getClientBounds( GHOST_Rect& bounds ) const { /* nothing */ } - GHOST_TSuccess setClientWidth( GHOST_TUns32 width ){ return GHOST_kFailure; } - GHOST_TSuccess setClientHeight( GHOST_TUns32 height ){ return GHOST_kFailure; } - GHOST_TSuccess setClientSize( GHOST_TUns32 width, GHOST_TUns32 height ){ return GHOST_kFailure; } + GHOST_TSuccess setClientWidth( GHOST_TUns32 width ) { return GHOST_kFailure; } + GHOST_TSuccess setClientHeight( GHOST_TUns32 height ) { return GHOST_kFailure; } + GHOST_TSuccess setClientSize( GHOST_TUns32 width, GHOST_TUns32 height ) { return GHOST_kFailure; } void screenToClient( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const { outX = inX; outY = inY; } void clientToScreen( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const { outX = inX; outY = inY; } - GHOST_TSuccess swapBuffers( ){ return GHOST_kFailure; } - GHOST_TSuccess activateDrawingContext( ){ return GHOST_kFailure; } - ~GHOST_WindowNULL( ){ /* nothing */ } - GHOST_TSuccess setWindowCursorVisibility( bool visible ){ return GHOST_kSuccess; } + GHOST_TSuccess swapBuffers( ) { return GHOST_kFailure; } + GHOST_TSuccess activateDrawingContext( ) { return GHOST_kFailure; } + ~GHOST_WindowNULL( ) { /* nothing */ } + GHOST_TSuccess setWindowCursorVisibility( bool visible ) { return GHOST_kSuccess; } GHOST_TSuccess setState(GHOST_TWindowState state) { return GHOST_kSuccess; } GHOST_TWindowState getState() const { return GHOST_kWindowStateNormal; } GHOST_TSuccess invalidate() { return GHOST_kSuccess; } diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c index f988f0fb86a..034fbe04447 100644 --- a/intern/ghost/test/multitest/EventToBuf.c +++ b/intern/ghost/test/multitest/EventToBuf.c @@ -36,7 +36,7 @@ char *eventtype_to_string(GHOST_TEventType type) { - switch(type) { + switch (type) { case GHOST_kEventCursorMove: return "CursorMove"; case GHOST_kEventButtonDown: return "ButtonDown"; case GHOST_kEventButtonUp: return "ButtonUp"; diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h index 9541604b680..0020094ebbb 100644 --- a/intern/memutil/MEM_Allocator.h +++ b/intern/memutil/MEM_Allocator.h @@ -72,7 +72,7 @@ struct MEM_Allocator } // __p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type){ + void deallocate(pointer __p, size_type) { MEM_freeN(__p); } diff --git a/intern/memutil/MEM_RefCountPtr.h b/intern/memutil/MEM_RefCountPtr.h index 4f475345076..ffdf927b551 100644 --- a/intern/memutil/MEM_RefCountPtr.h +++ b/intern/memutil/MEM_RefCountPtr.h @@ -98,7 +98,7 @@ * * static * MEM_RefCountPtr - * New(...){ + * New(...) { * return MEM_RefCountPtr output( * new UsefullClass(...) * ); diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h index 6a0dc1723c4..722a0a8fd3b 100644 --- a/intern/memutil/MEM_SmartPtr.h +++ b/intern/memutil/MEM_SmartPtr.h @@ -119,7 +119,7 @@ public : MEM_SmartPtr( const MEM_SmartPtr &rhs - ){ + ) { m_val = rhs.Release(); } diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index 24c77c439a7..cba4c406759 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -258,7 +258,7 @@ tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThre { const int verts = pContext->m_pInterface->m_getNumVerticesOfFace(pContext, f); if (verts==3) ++iNrTrianglesIn; - else if(verts==4) iNrTrianglesIn += 2; + else if (verts==4) iNrTrianglesIn += 2; } if (iNrTrianglesIn<=0) return TFALSE; @@ -470,11 +470,11 @@ static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SM const SVec3 vP = GetPosition(pContext, index); if (vMin.x > vP.x) vMin.x = vP.x; - else if(vMax.x < vP.x) vMax.x = vP.x; + else if (vMax.x < vP.x) vMax.x = vP.x; if (vMin.y > vP.y) vMin.y = vP.y; - else if(vMax.y < vP.y) vMax.y = vP.y; + else if (vMax.y < vP.y) vMax.y = vP.y; if (vMin.z > vP.z) vMin.z = vP.z; - else if(vMax.z < vP.z) vMax.z = vP.z; + else if (vMax.z < vP.z) vMax.z = vP.z; } vDim = vsub(vMax,vMin); @@ -485,7 +485,7 @@ static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SM iChannel=1; fMin = vMin.y, fMax=vMax.y; } - else if(vDim.z>vDim.x) + else if (vDim.z>vDim.x) { iChannel=2; fMin = vMin.z, fMax=vMax.z; @@ -590,7 +590,7 @@ static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], cons for (l=(iL_in+1); l<=iR_in; l++) for (c=0; c<3; c++) if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c]; - else if(fvMax[c]dx && dy>dz) channel=1; - else if(dz>dx) channel=2; + else if (dz>dx) channel=2; fSep = 0.5f*(fvMax[channel]+fvMin[channel]); @@ -626,7 +626,7 @@ static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], cons const SVec3 vT2 = GetTexCoord(pContext, index2); i2rec=i2; - //if(vP==vP2 && vN==vN2 && vT==vT2) + //if (vP==vP2 && vN==vN2 && vT==vT2) if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z && vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z && vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z) @@ -812,7 +812,7 @@ static int GenerateInitialVerticesIndexList(STriInfo pTriInfos[], int piTriList_ tbool bQuadDiagIs_02; if (distSQ_02= CalcTexArea(pContext, &piTriListIn[(t+1)*3+0]) ) + else if ( CalcTexArea(pContext, &piTriListIn[t*3+0]) >= CalcTexArea(pContext, &piTriListIn[(t+1)*3+0]) ) bChooseOrientFirstTri = TTRUE; // force match @@ -1142,13 +1142,13 @@ static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], const int * pVerts = &piTriListIn[3*iMyTriIndex+0]; int i=-1; if (pVerts[0]==iVertRep) i=0; - else if(pVerts[1]==iVertRep) i=1; - else if(pVerts[2]==iVertRep) i=2; + else if (pVerts[1]==iVertRep) i=1; + else if (pVerts[2]==iVertRep) i=2; assert(i>=0 && i<3); // early out if (pMyTriInfo->AssignedGroup[i] == pGroup) return TTRUE; - else if(pMyTriInfo->AssignedGroup[i]!=NULL) return TFALSE; + else if (pMyTriInfo->AssignedGroup[i]!=NULL) return TFALSE; if ((pMyTriInfo->iFlag&GROUP_WITH_ANY)!=0) { // first to group with a group-with-anything triangle @@ -1232,8 +1232,8 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con tbool bFound; SVec3 n, vOs, vOt; if (pTriInfos[f].AssignedGroup[0]==pGroup) index=0; - else if(pTriInfos[f].AssignedGroup[1]==pGroup) index=1; - else if(pTriInfos[f].AssignedGroup[2]==pGroup) index=2; + else if (pTriInfos[f].AssignedGroup[1]==pGroup) index=1; + else if (pTriInfos[f].AssignedGroup[2]==pGroup) index=2; assert(index>=0 && index<3); iVertIndex = piTriListIn[f*3+index]; @@ -1381,8 +1381,8 @@ static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriL float fCos, fAngle, fMagS, fMagT; int i=-1, index=-1, i0=-1, i1=-1, i2=-1; if (piTriListIn[3*f+0]==iVertexRepresentitive) i=0; - else if(piTriListIn[3*f+1]==iVertexRepresentitive) i=1; - else if(piTriListIn[3*f+2]==iVertexRepresentitive) i=2; + else if (piTriListIn[3*f+1]==iVertexRepresentitive) i=1; + else if (piTriListIn[3*f+2]==iVertexRepresentitive) i=2; assert(i>=0 && i<3); // project @@ -1404,8 +1404,8 @@ static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriL v2 = vsub(p2,p1); // project - v1 = vsub(v1, vscale(vdot(n,v1),n)); if( VNotZero(v1) ) v1 = Normalize(v1); - v2 = vsub(v2, vscale(vdot(n,v2),n)); if( VNotZero(v2) ) v2 = Normalize(v2); + v1 = vsub(v1, vscale(vdot(n,v1),n)); if ( VNotZero(v1) ) v1 = Normalize(v1); + v2 = vsub(v2, vscale(vdot(n,v2),n)); if ( VNotZero(v2) ) v2 = Normalize(v2); // weight contribution by the angle // between the two edge vectors @@ -1647,7 +1647,7 @@ static void QuickSortEdges(SEdge * pSortBuffer, int iLeft, int iRight, const int SEdge sTmp; const int iElems = iRight-iLeft+1; if (iElems<2) return; - else if(iElems==2) + else if (iElems==2) { if (pSortBuffer[iLeft].array[channel] > pSortBuffer[iRight].array[channel]) { @@ -1868,8 +1868,8 @@ static void DegenEpilogue(STSpace psTspace[], STriInfo pTriInfos[], int piTriLis int iFlag = (1<= 0) && (y_curr < ctx->rb.sizey)) { /* draw the pixels. */ - for (; cpxl <= mpxl; *cpxl++ = 1.0f); + for (; cpxl <= mpxl; *cpxl++ = 1.0f); } } diff --git a/intern/utfconv/utfconv.c b/intern/utfconv/utfconv.c index 189141e487d..a9b2920111d 100644 --- a/intern/utfconv/utfconv.c +++ b/intern/utfconv/utfconv.c @@ -34,7 +34,7 @@ size_t count_utf_8_from_16(const wchar_t *string16) return 0; } - for (i = 0; (u = string16[i]); i++) { + for (i = 0; (u = string16[i]); i++) { if (u < 0x0080) { count += 1; } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index cdedd818b43..f19dfe74a36 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2674,7 +2674,7 @@ static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, flo force[2] += (BLI_frand()-0.5f) * part->brownfac; } - if(part->flag & PART_ROT_DYN && epoint.ave) + if (part->flag & PART_ROT_DYN && epoint.ave) copy_v3_v3(pa->state.ave, epoint.ave); } /* gathers all forces that effect particles and calculates a new state for the particle */ diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 91e93bbd05d..40471514b48 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1003,9 +1003,11 @@ void BKE_ffmpeg_end(void) fprintf(stderr, "Closing ffmpeg...\n"); -/* if (audio_stream) { SEE UPPER - write_audio_frames(); - }*/ +#if 0 + if (audio_stream) { /* SEE UPPER */ + write_audio_frames(); + } +#endif #ifdef WITH_AUDASPACE if (audio_mixdown_device) { diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 9433cfd31df..5b034bd2872 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -285,8 +285,8 @@ void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll) else { h = (r - g) / d + 4.0f; } - } - h /= 6.0f; + } + h /= 6.0f; *lh = h; *ls = s; @@ -634,23 +634,23 @@ void BLI_init_srgb_conversion(void) } static float inverse_srgb_companding(float v) { - if (v > 0.04045f) { - return powf((v + 0.055f) / 1.055f, 2.4); - } - else { - return v / 12.92f; - } + if (v > 0.04045f) { + return powf((v + 0.055f) / 1.055f, 2.4); + } + else { + return v / 12.92f; + } } void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z) { - r = inverse_srgb_companding(r) * 100.0f; - g = inverse_srgb_companding(g) * 100.0f; - b = inverse_srgb_companding(b) * 100.0f; + r = inverse_srgb_companding(r) * 100.0f; + g = inverse_srgb_companding(g) * 100.0f; + b = inverse_srgb_companding(b) * 100.0f; - *x = r * 0.4124 + g * 0.3576 + b * 0.1805; - *y = r * 0.2126 + g * 0.7152 + b * 0.0722; - *z = r * 0.0193 + g * 0.1192 + b * 0.9505; + *x = r * 0.4124 + g * 0.3576 + b * 0.1805; + *y = r * 0.2126 + g * 0.7152 + b * 0.0722; + *z = r * 0.0193 + g * 0.1192 + b * 0.9505; } static float xyz_to_lab_component(float v) diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index e9bccd4244b..9795d4dea2d 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -335,9 +335,9 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size int BLI_str_utf8_size(const char *p) { int mask = 0, len; - unsigned char c = (unsigned char) *p; + unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len); (void)mask; /* quiet warning */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a4d8457bd2d..71e9bfa33e4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6227,7 +6227,7 @@ static void lib_link_mask(FileData *fd, Main *main) mask = main->mask.first; while (mask) { - if(mask->id.flag & LIB_NEEDLINK) { + if (mask->id.flag & LIB_NEEDLINK) { MaskLayer *masklay; if (mask->adt) diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 195057817dd..45d7d4a7684 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -804,7 +804,7 @@ void AnimationImporter::translate_Animations ( COLLADAFW::Node * node, bool is_joint = node->getType() == COLLADAFW::Node::JOINT; COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()]; - Object *ob = is_joint ? armature_importer->get_armature_for_joint(root) : object_map.find(node->getUniqueId())->second; + Object *ob = is_joint ? armature_importer->get_armature_for_joint(root) : object_map.find(node->getUniqueId())->second; if (!ob) { fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str()); return; diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index 020dfdbdc14..04cd91d3c3a 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -99,8 +99,8 @@ void BaseImageOperation::determineResolution(unsigned int resolution[], unsigned { ImBuf *stackbuf = getImBuf(); - resolution[0] = 0; - resolution[1] = 0; + resolution[0] = 0; + resolution[1] = 0; if (stackbuf) { resolution[0] = stackbuf->x; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 21f87029cb0..fc6f406ab59 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -166,13 +166,14 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa) static void panels_collapse_all(ScrArea *sa, ARegion *ar) { - Panel *pa; - int flag = ((panel_aligned(sa, ar)==BUT_HORIZONTAL)? PNL_CLOSEDX: PNL_CLOSEDY); + Panel *pa; + int flag = ((panel_aligned(sa, ar)==BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY); - for (pa= ar->panels.first; pa; pa= pa->next) { - if (pa->type && !(pa->type->flag & PNL_NO_HEADER)) - pa->flag = flag; - } + for (pa= ar->panels.first; pa; pa= pa->next) { + if (pa->type && !(pa->type->flag & PNL_NO_HEADER)) { + pa->flag = flag; + } + } } diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 18f191a46a6..e69e1f15b6e 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -168,7 +168,7 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname) scopes->track_preview_height = (scopes->track_preview_height <= UI_UNIT_Y)?UI_UNIT_Y : scopes->track_preview_height; uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, rect.xmax - rect.xmin, - scopes->track_preview_height, scopes, 0, 0, 0, 0, ""); + scopes->track_preview_height, scopes, 0, 0, 0, 0, ""); } /********************* Marker Template ************************/ diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 8bee06854e1..13e0a3c8b91 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -282,7 +282,7 @@ void ED_space_clip_mask_aspect(SpaceClip *sc, float *aspx, float *aspy) *aspy *= (float)h; #endif - if(*aspx < *aspy) { + if (*aspx < *aspy) { *aspy= *aspy / *aspx; *aspx= 1.0f; } @@ -329,7 +329,7 @@ void ED_space_clip_aspect_dimension_aware(SpaceClip *sc, float *aspx, float *asp *aspx *= (float)w; *aspy *= (float)h; - if(*aspx < *aspy) { + if (*aspx < *aspy) { *aspy= *aspy / *aspx; *aspx= 1.0f; } @@ -691,9 +691,11 @@ void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask) { sc->mask = mask; - if(sc->mask && sc->mask->id.us==0) + if (sc->mask && sc->mask->id.us==0) { sc->clip->id.us = 1; + } - if(C) + if (C) { WM_event_add_notifier(C, NC_MASK|NA_SELECTED, mask); + } } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index aec71d095f7..d61dd862096 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -367,14 +367,14 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) } break; case NC_MASK: - switch(wmn->data) { + switch (wmn->data) { case ND_SELECT: case ND_DATA: case ND_DRAW: ED_area_tag_redraw(sa); break; } - switch(wmn->action) { + switch (wmn->action) { case NA_SELECTED: clip_scopes_tag_refresh(sa); ED_area_tag_redraw(sa); @@ -1097,7 +1097,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) /* Grease Pencil */ clip_draw_grease_pencil((bContext *)C, 1); - if(sc->mode == SC_MODE_MASKEDIT) { + if (sc->mode == SC_MODE_MASKEDIT) { int x, y; int width, height; float zoomx, zoomy, aspx, aspy; @@ -1323,7 +1323,7 @@ static void clip_header_area_listener(ARegion *ar, wmNotifier *wmn) /* for proportional editmode only */ case ND_TOOLSETTINGS: /* TODO - should do this when in mask mode only but no datas available */ - // if(sc->mode == SC_MODE_MASKEDIT) + // if (sc->mode == SC_MODE_MASKEDIT) { ED_region_tag_redraw(ar); } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index aa8a68677c0..1e8541214ce 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1114,7 +1114,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( glDisable(GL_BLEND); /* outline active and selected emphasis */ - if( node->flag & (NODE_ACTIVE|SELECT) ) { + if (node->flag & (NODE_ACTIVE | SELECT)) { glEnable(GL_BLEND); glEnable( GL_LINE_SMOOTH ); /* using different shades of TH_TEXT_HI for the empasis, like triangle */ @@ -1132,7 +1132,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( /* only draw input socket. as they all are placed on the same position. * highlight also if node itself is selected, since we don't display the node body separately! */ - for(sock= node->inputs.first; sock; sock= sock->next) { + for (sock= node->inputs.first; sock; sock= sock->next) { node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT)); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 1b229c78e0f..b4e07546fa9 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2756,11 +2756,11 @@ static int add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int float coord_array[LINK_RESOL+1][2]; int i, b; - if(node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) { + if (node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) { - for(i=0; i 0) { + for (i=0; i 0) { result[0] = (mcoords[i][0]+mcoords[i+1][0])/2.0f; result[1] = (mcoords[i][1]+mcoords[i+1][1])/2.0f; return 1; @@ -2783,18 +2783,18 @@ static int add_reroute_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(&ar->v2d, (short)loc[0], (short)loc[1], &mcoords[i][0], &mcoords[i][1]); i++; - if(i>= 256) break; + if (i>= 256) break; } RNA_END; - if(i>1) { + if (i>1) { bNodeLink *link; float insertPoint[2]; ED_preview_kill_jobs(C); - for(link= snode->edittree->links.first; link; link=link->next) { - if(add_reroute_intersect_check(link, mcoords, i, insertPoint)) { + for (link= snode->edittree->links.first; link; link=link->next) { + if (add_reroute_intersect_check(link, mcoords, i, insertPoint)) { bNodeTemplate ntemp; bNode *rerouteNode; diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 0a3678ca901..e7be750928d 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -76,7 +76,7 @@ static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my) { bNode *node; - for(node=ntree->nodes.last; node; node=node->prev) { + for (node=ntree->nodes.last; node; node=node->prev) { if (node->typeinfo->tweak_area_func) { if (node->typeinfo->tweak_area_func(node, mx, my)) return node; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9c6d7e49c08..9b8e5daca07 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -6035,7 +6035,7 @@ void flushTransMasking(TransInfo *t) invy = 1.0f/aspy; /* flush to 2d vector from internally used 3d vector */ - for(a=0, td = t->data2d, tdm = t->customData; atotal; a++, td++, tdm++) { + for (a=0, td = t->data2d, tdm = t->customData; atotal; a++, td++, tdm++) { td->loc2d[0]= td->loc[0]*invx; td->loc2d[1]= td->loc[1]*invy; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 31008ff8685..78b5219206d 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -772,7 +772,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la GPU_link(mat, "mtex_value_invert", shadfac, &shadfac); GPU_link(mat, "mix_mult", shadfac, rgb, GPU_uniform(lamp->shadow_color), &rgb); GPU_link(mat, "mtex_value_invert", shadfac, &shadfac); - add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff); + add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff); } } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 42bec5874ca..0b9f5c163fb 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -176,7 +176,7 @@ bool ColorBlock::isSingleColorNoAlpha() const int i; for (i = 0; i < 16; i++) { - if (m_color[i].a != 0) c = m_color[i]; + if (m_color[i].a != 0) c = m_color[i]; } Color32 mask(0xFF, 0xFF, 0xFF, 0x00); diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index b69f167f876..b9593353288 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -205,12 +205,12 @@ static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFa return df; } -#define SET_VERTS(a, b, c, d) \ - v[0] = mf->v##a; uv[0] = a - 1; \ - v[1] = mf->v##b; uv[1] = b - 1; \ - v[2] = mf->v##c; uv[2] = c - 1; \ - v[3] = mf->v##d; uv[3] = d - 1; \ - (void)0 +#define SET_VERTS(a, b, c, d) { \ + v[0] = mf->v##a; uv[0] = a - 1; \ + v[1] = mf->v##b; uv[1] = b - 1; \ + v[2] = mf->v##c; uv[2] = c - 1; \ + v[3] = mf->v##d; uv[3] = d - 1; \ + } (void)0 #define GET_ES(v1, v2) edgecut_get(eh, v1, v2) #define INT_UV(uvf, c0, c1) interp_v2_v2v2(uvf, mf->uv[c0], mf->uv[c1], 0.5f) diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 745cf1304bd..6f8e65a6e8e 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -435,7 +435,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (ofs_orig != 0.0f) { scalar_short = scalar_short_vgroup = ofs_orig / 32767.0f; - mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? 0 : numVerts); /* as above but swapped, intentional use 'ofs_new' */ + mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? 0 : numVerts); /* as above but swapped */ dv = dvert; for (i = 0; i < numVerts; i++, mv++) { if (dv) { diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 9f458678ae0..3d1b656fc4e 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -857,7 +857,7 @@ ListBase node_reroute_internal_connect(bNodeTree *ntree, bNode *node) ret.first = ret.last = NULL; /* Security check! */ - if(!ntree) + if (!ntree) return ret; link = MEM_callocN(sizeof(bNodeLink), "internal node link"); diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c index 1d02acbe983..d34bdfe9448 100644 --- a/source/blender/python/intern/bpy_library.c +++ b/source/blender/python/intern/bpy_library.c @@ -170,18 +170,18 @@ static PyTypeObject bpy_lib_Type = { }; PyDoc_STRVAR(bpy_lib_load_doc, - ".. method:: load(filepath, link=False, relative=False)\n" - "\n" - " Returns a context manager which exposes 2 library objects on entering.\n" - " Each object has attributes matching bpy.data which are lists of strings to be linked.\n" - "\n" - " :arg filepath: The path to a blend file.\n" - " :type filepath: string\n" - " :arg link: When False reference to the original file is lost.\n" - " :type link: bool\n" - " :arg relative: When True the path is stored relative to the open blend file.\n" - " :type relative: bool\n" - ); +".. method:: load(filepath, link=False, relative=False)\n" +"\n" +" Returns a context manager which exposes 2 library objects on entering.\n" +" Each object has attributes matching bpy.data which are lists of strings to be linked.\n" +"\n" +" :arg filepath: The path to a blend file.\n" +" :type filepath: string\n" +" :arg link: When False reference to the original file is lost.\n" +" :type link: bool\n" +" :arg relative: When True the path is stored relative to the open blend file.\n" +" :type relative: bool\n" +); static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"filepath", "link", "relative", NULL}; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index d7d55885f37..1cf58b4345b 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2174,8 +2174,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* Options panel */ selected = RNA_boolean_get(op->ptr, "selected"); apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); - include_bone_children = RNA_boolean_get(op->ptr, "include_bone_children"); - use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); + include_bone_children = RNA_boolean_get(op->ptr, "include_bone_children"); + use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); second_life = RNA_boolean_get(op->ptr, "second_life"); /* get editmode results */ diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 4f0ae4261c9..695ad1f945c 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -2267,10 +2267,10 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) return NULL; - if (!m_inactivelist->SearchValue(ob)) { - PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (second argument): object does not belong to scene"); - return NULL; - } + if (!m_inactivelist->SearchValue(ob)) { + PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (second argument): object does not belong to scene"); + return NULL; + } SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); // release here because AddReplicaObject AddRef's -- cgit v1.2.3 From 0d3b19e7340e0f3fa075e90e695ddf760529b925 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 4 Jun 2012 20:50:59 +0000 Subject: Cycles / OSL: * Fixes for changes in the OSL register_closure() API. --- intern/cycles/kernel/osl/osl_closures.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index b87cdf8af86..0793b29d1ac 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -48,7 +48,7 @@ static void generic_closure_setup(OSL::RendererServices *, int id, void *data) prim->setup(); } -static bool generic_closure_mergeable(int id, const void *dataA, const void *dataB) +static bool generic_closure_compare(int id, const void *dataA, const void *dataB) { assert(dataA && dataB); @@ -59,11 +59,7 @@ static bool generic_closure_mergeable(int id, const void *dataA, const void *dat static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare) { - int j; - for(j = 0; params[j].type != TypeDesc(); ++j) {} - int size = params[j].offset; - - ss->register_closure(name, id, params, size, prepare, generic_closure_setup, generic_closure_mergeable); + ss->register_closure(name, id, params, prepare, generic_closure_setup, generic_closure_compare); } void OSLShader::register_closures(OSL::ShadingSystem *ss) -- cgit v1.2.3 From 8db6e682e9c0d55a34c64a490cbf29ff301c4973 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 4 Jun 2012 22:29:17 +0000 Subject: Fix [#31544]: iTaSC assertion when creating armature with no joint. This degenerated case can be obtained by having a single bone in the IK chain and locking all 3 axis. This case was causing an assert in the KDL library. The bug is fixed by simply not creating the IK scene in this case. --- intern/itasc/Armature.cpp | 7 +++++-- intern/itasc/Armature.hpp | 2 +- intern/itasc/FixedObject.cpp | 5 +++-- intern/itasc/FixedObject.hpp | 2 +- intern/itasc/MovingFrame.cpp | 3 ++- intern/itasc/MovingFrame.hpp | 2 +- intern/itasc/Object.hpp | 2 +- intern/itasc/Scene.cpp | 3 ++- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp index 916b0bc7bf3..dd5c1921a98 100644 --- a/intern/itasc/Armature.cpp +++ b/intern/itasc/Armature.cpp @@ -369,11 +369,13 @@ int Armature::addEndEffector(const std::string& name) return m_neffector++; } -void Armature::finalize() +bool Armature::finalize() { unsigned int i, j, c; if (m_finalized) - return; + return true; + if (m_njoint == 0) + return false; initialize(m_njoint, m_noutput, m_neffector); for (i=c=0; ifinalize(); + if (!object->finalize()) + return false; //Check if Object is controlled or uncontrolled. if(object->getType()==Object::Controlled){ int baseFrameIndex = base->addEndEffector(baseFrame); -- cgit v1.2.3 From f94123a5c651b8a65e5e6e11cd2aed8fcc766498 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 22:34:28 +0000 Subject: only use tiff/exr when enabled. --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f50ef91c978..3538c64f1e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,4 @@ +set(Boost_DEBUG TRUE) # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or @@ -647,10 +648,17 @@ if(UNIX AND NOT APPLE) find_package(OpenImageIO) - set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARY} ${OPENEXR_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES}) + set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES}) set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere set(OPENIMAGEIO_DEFINITIONS) + if(WITH_IMAGE_TIFF) + set(OPENIMAGEIO_LIBRARIES "${OPENIMAGEIO_LIBRARIES} ${TIFF_LIBRARY}") + endif() + if(WITH_IMAGE_OPENEXR) + set(OPENIMAGEIO_LIBRARIES "${OPENIMAGEIO_LIBRARIES} ${OPENEXR_LIBRARIES}") + endif() + if(NOT OPENIMAGEIO_FOUND) set(WITH_OPENIMAGEIO OFF) set(WITH_CYCLES OFF) -- cgit v1.2.3 From 2d290040a1fea8319f33a982823bea13d1d95348 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 4 Jun 2012 22:44:58 +0000 Subject: style cleanup --- intern/cycles/kernel/osl/background.cpp | 36 +- intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp | 240 +++---- intern/cycles/kernel/osl/bsdf_diffuse.cpp | 244 +++---- intern/cycles/kernel/osl/bsdf_microfacet.cpp | 779 +++++++++++---------- intern/cycles/kernel/osl/bsdf_oren_nayar.cpp | 40 +- intern/cycles/kernel/osl/bsdf_reflection.cpp | 113 +-- intern/cycles/kernel/osl/bsdf_refraction.cpp | 119 ++-- intern/cycles/kernel/osl/bsdf_transparent.cpp | 87 +-- intern/cycles/kernel/osl/bsdf_ward.cpp | 312 +++++---- intern/cycles/kernel/osl/bsdf_westin.cpp | 346 ++++----- intern/cycles/kernel/osl/bssrdf.cpp | 103 +-- intern/cycles/kernel/osl/debug.cpp | 31 +- intern/cycles/kernel/osl/emissive.cpp | 93 +-- intern/cycles/kernel/osl/nodes/node_color.h | 50 +- intern/cycles/kernel/osl/nodes/node_fresnel.h | 8 +- intern/cycles/kernel/osl/nodes/node_texture.h | 100 +-- intern/cycles/kernel/osl/nodes/stdosl.h | 397 +++++------ intern/cycles/kernel/osl/osl_services.cpp | 152 ++-- intern/cycles/kernel/osl/osl_services.h | 15 +- intern/cycles/kernel/osl/osl_shader.cpp | 152 ++-- intern/cycles/kernel/osl/osl_shader.h | 8 +- intern/cycles/kernel/osl/vol_subsurface.cpp | 156 +++-- 22 files changed, 1814 insertions(+), 1767 deletions(-) diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index c35119ae9cf..81812a46b6c 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -48,17 +48,17 @@ using namespace OSL; /// class GenericBackgroundClosure : public BackgroundClosure { public: - GenericBackgroundClosure() { } + GenericBackgroundClosure() {} - void setup() {}; + void setup() {}; - size_t memsize () const { return sizeof(*this); } + size_t memsize() const { return sizeof(*this); } - const char *name () const { return "background"; } + const char *name() const { return "background"; } - void print_on (std::ostream &out) const { - out << name() << " ()"; - } + void print_on(std::ostream &out) const { + out << name() << " ()"; + } }; @@ -72,27 +72,29 @@ public: /// class HoldoutClosure : ClosurePrimitive { public: - HoldoutClosure () : ClosurePrimitive (Holdout) { } + HoldoutClosure () : ClosurePrimitive(Holdout) {} - void setup() {}; + void setup() {}; - size_t memsize () const { return sizeof(*this); } + size_t memsize() const { return sizeof(*this); } - const char *name () const { return "holdout"; } + const char *name() const { return "holdout"; } - void print_on (std::ostream &out) const { - out << name() << " ()"; - } + void print_on(std::ostream &out) const { + out << name() << " ()"; + } }; ClosureParam closure_background_params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(GenericBackgroundClosure) }; + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(GenericBackgroundClosure) +}; CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure) ClosureParam closure_holdout_params[] = { - CLOSURE_FINISH_PARAM(HoldoutClosure) }; + CLOSURE_FINISH_PARAM(HoldoutClosure) +}; CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure) diff --git a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp index 808837bf211..cb6be6959f5 100644 --- a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp +++ b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp @@ -44,132 +44,134 @@ using namespace OSL; class AshikhminVelvetClosure : public BSDFClosure { public: - Vec3 m_N; - float m_sigma; - float m_invsigma2; - - AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) { } - - void setup() - { - m_sigma = max(m_sigma, 0.01f); - m_invsigma2 = 1.0f/(m_sigma * m_sigma); - } - - bool mergeable (const ClosurePrimitive *other) const { - const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other; - return m_N == comp->m_N && m_sigma == comp->m_sigma && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "ashikhmin_velvet"; } - - void print_on (std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_sigma; - out << ")"; - } - - float albedo (const Vec3 &omega_out) const - { + Vec3 m_N; + float m_sigma; + float m_invsigma2; + + AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) {} + + void setup() + { + m_sigma = max(m_sigma, 0.01f); + m_invsigma2 = 1.0f / (m_sigma * m_sigma); + } + + bool mergeable(const ClosurePrimitive *other) const { + const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other; + return m_N == comp->m_N && m_sigma == comp->m_sigma && + BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "ashikhmin_velvet"; } + + void print_on(std::ostream &out) const + { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_sigma; + out << ")"; + } + + float albedo(const Vec3 &omega_out) const + { return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - Vec3 H = omega_in + omega_out; - H.normalize(); - - float cosNH = m_N.dot(H); - float cosHO = fabsf(omega_out.dot(H)); - - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = max(cosNHdivHO, 0.00001f); - - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; - - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically - - float out = 0.25f * (D * G) / cosNO; - - pdf = 0.5f * (float) M_1_PI; - return Color3 (out, out, out); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from above - send a ray out with uniform - // distribution over the hemisphere - sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - Vec3 H = omega_in + omega_out; - H.normalize(); - - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - float cosNH = m_N.dot(H); - float cosHO = fabsf(omega_out.dot(H)); - - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = max(cosNHdivHO, 0.00001f); - - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; - - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically - - float power = 0.25f * (D * G) / cosNO; - - eval.setValue(power, power, power); - - // TODO: find a better approximation for the retroreflective bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } else - pdf = 0; - return Labels::REFLECT; - } + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO > 0 && cosNI > 0) { + Vec3 H = omega_in + omega_out; + H.normalize(); + + float cosNH = m_N.dot(H); + float cosHO = fabsf(omega_out.dot(H)); + + float cosNHdivHO = cosNH / cosHO; + cosNHdivHO = max(cosNHdivHO, 0.00001f); + + float fac1 = 2 * fabsf(cosNHdivHO * cosNO); + float fac2 = 2 * fabsf(cosNHdivHO * cosNI); + + float sinNH2 = 1 - cosNH * cosNH; + float sinNH4 = sinNH2 * sinNH2; + float cotangent2 = (cosNH * cosNH) / sinNH2; + + float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; + float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically + + float out = 0.25f * (D * G) / cosNO; + + pdf = 0.5f * (float) M_1_PI; + return Color3(out, out, out); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // we are viewing the surface from above - send a ray out with uniform + // distribution over the hemisphere + sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); + if (Ng.dot(omega_in) > 0) { + Vec3 H = omega_in + omega_out; + H.normalize(); + + float cosNI = m_N.dot(omega_in); + float cosNO = m_N.dot(omega_out); + float cosNH = m_N.dot(H); + float cosHO = fabsf(omega_out.dot(H)); + + float cosNHdivHO = cosNH / cosHO; + cosNHdivHO = max(cosNHdivHO, 0.00001f); + + float fac1 = 2 * fabsf(cosNHdivHO * cosNO); + float fac2 = 2 * fabsf(cosNHdivHO * cosNI); + + float sinNH2 = 1 - cosNH * cosNH; + float sinNH4 = sinNH2 * sinNH2; + float cotangent2 = (cosNH * cosNH) / sinNH2; + + float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; + float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically + + float power = 0.25f * (D * G) / cosNO; + + eval.setValue(power, power, power); + + // TODO: find a better approximation for the retroreflective bounce + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + domega_in_dx *= 125; + domega_in_dy *= 125; + } + else + pdf = 0; + return Labels::REFLECT; + } }; ClosureParam bsdf_ashikhmin_velvet_params[] = { - CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N), - CLOSURE_FLOAT_PARAM (AshikhminVelvetClosure, m_sigma), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) }; + CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N), + CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, m_sigma), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) +}; CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure) diff --git a/intern/cycles/kernel/osl/bsdf_diffuse.cpp b/intern/cycles/kernel/osl/bsdf_diffuse.cpp index 352e75f73c9..582ac01d959 100644 --- a/intern/cycles/kernel/osl/bsdf_diffuse.cpp +++ b/intern/cycles/kernel/osl/bsdf_diffuse.cpp @@ -44,137 +44,141 @@ using namespace OSL; class DiffuseClosure : public BSDFClosure { public: - Vec3 m_N; - - DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const DiffuseClosure *comp = (const DiffuseClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "diffuse"; } - - void print_on (std::ostream &out) const - { - out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cos_pi = max(m_N.dot(omega_in),0.0f) * (float) M_1_PI; - pdf = cos_pi; - return Color3 (cos_pi, cos_pi, cos_pi); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - eval.setValue(pdf, pdf, pdf); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } else - pdf = 0; - return Labels::REFLECT; - } + Vec3 m_N; + + DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) {} + + void setup() {}; + + bool mergeable(const ClosurePrimitive *other) const { + const DiffuseClosure *comp = (const DiffuseClosure *)other; + return m_N == comp->m_N && BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "diffuse"; } + + void print_on(std::ostream &out) const + { + out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + float cos_pi = max(m_N.dot(omega_in), 0.0f) * (float) M_1_PI; + pdf = cos_pi; + return Color3(cos_pi, cos_pi, cos_pi); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // we are viewing the surface from the right side - send a ray out with cosine + // distribution over the hemisphere + sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); + if (Ng.dot(omega_in) > 0) { + eval.setValue(pdf, pdf, pdf); + // TODO: find a better approximation for the diffuse bounce + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + domega_in_dx *= 125; + domega_in_dy *= 125; + } + else + pdf = 0; + return Labels::REFLECT; + } }; class TranslucentClosure : public BSDFClosure { public: - Vec3 m_N; - - TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const TranslucentClosure *comp = (const TranslucentClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "translucent"; } - - void print_on (std::ostream &out) const - { - out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI; - pdf = cos_pi; - return Color3 (cos_pi, cos_pi, cos_pi); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere (-m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) < 0) { - eval.setValue(pdf, pdf, pdf); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= -125; - domega_in_dy *= -125; - } else - pdf = 0; - return Labels::TRANSMIT; - } + Vec3 m_N; + + TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) {} + + void setup() {}; + + bool mergeable(const ClosurePrimitive *other) const { + const TranslucentClosure *comp = (const TranslucentClosure *)other; + return m_N == comp->m_N && BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "translucent"; } + + void print_on(std::ostream &out) const + { + out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI; + pdf = cos_pi; + return Color3(cos_pi, cos_pi, cos_pi); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // we are viewing the surface from the right side - send a ray out with cosine + // distribution over the hemisphere + sample_cos_hemisphere(-m_N, omega_out, randu, randv, omega_in, pdf); + if (Ng.dot(omega_in) < 0) { + eval.setValue(pdf, pdf, pdf); + // TODO: find a better approximation for the diffuse bounce + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + domega_in_dx *= -125; + domega_in_dy *= -125; + } + else + pdf = 0; + return Labels::TRANSMIT; + } }; ClosureParam bsdf_diffuse_params[] = { - CLOSURE_VECTOR_PARAM (DiffuseClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM (DiffuseClosure) }; + CLOSURE_VECTOR_PARAM(DiffuseClosure, m_N), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(DiffuseClosure) +}; ClosureParam bsdf_translucent_params[] = { - CLOSURE_VECTOR_PARAM (TranslucentClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM (TranslucentClosure) }; + CLOSURE_VECTOR_PARAM(TranslucentClosure, m_N), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(TranslucentClosure) +}; CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure) CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure) diff --git a/intern/cycles/kernel/osl/bsdf_microfacet.cpp b/intern/cycles/kernel/osl/bsdf_microfacet.cpp index d87268da81e..09730d8c3e1 100644 --- a/intern/cycles/kernel/osl/bsdf_microfacet.cpp +++ b/intern/cycles/kernel/osl/bsdf_microfacet.cpp @@ -52,85 +52,85 @@ CCL_NAMESPACE_BEGIN template class MicrofacetGGXClosure : public BSDFClosure { public: - Vec3 m_N; - float m_ag; // width parameter (roughness) - float m_eta; // index of refraction (for fresnel term) - MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; } + Vec3 m_N; + float m_ag; // width parameter (roughness) + float m_eta; // index of refraction (for fresnel term) + MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; } - void setup() + void setup() { m_ag = clamp(m_ag, 1e-5f, 1.0f); } - bool mergeable (const ClosurePrimitive *other) const { - const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other; - return m_N == comp->m_N && m_ag == comp->m_ag && - m_eta == comp->m_eta && BSDFClosure::mergeable(other); - } + bool mergeable(const ClosurePrimitive *other) const { + const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other; + return m_N == comp->m_N && m_ag == comp->m_ag && + m_eta == comp->m_eta && BSDFClosure::mergeable(other); + } - size_t memsize () const { return sizeof(*this); } + size_t memsize() const { return sizeof(*this); } - const char *name () const { - return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx"; - } + const char *name() const { + return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx"; + } - void print_on (std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_ag << ", "; - out << m_eta; - out << ")"; - } + void print_on(std::ostream &out) const { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_ag << ", "; + out << m_eta; + out << ")"; + } - float albedo (const Vec3 &omega_out) const - { + float albedo(const Vec3 &omega_out) const + { return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 1) return Color3 (0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNI > 0 && cosNO > 0) { - // get half vector - Vec3 Hr = omega_in + omega_out; - Hr.normalize(); - // eq. 20: (F*G*D)/(4*in*on) - // eq. 33: first we calculate D(m) with m=Hr: - float alpha2 = m_ag * m_ag; - float cosThetaM = m_N.dot(Hr); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - float out = (G * D) * 0.25f / cosNO; - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / Hr.dot(omega_out); - return Color3 (out, out, out); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 0) return Color3 (0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO <= 0 || cosNI >= 0) - return Color3 (0, 0, 0); // vectors on same side -- not possible - // compute half-vector of the refraction (eq. 16) - Vec3 ht = -(m_eta * omega_in + omega_out); - Vec3 Ht = ht; Ht.normalize(); - float cosHO = Ht.dot(omega_out); + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + if (Refractive == 1) return Color3(0, 0, 0); + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNI > 0 && cosNO > 0) { + // get half vector + Vec3 Hr = omega_in + omega_out; + Hr.normalize(); + // eq. 20: (F*G*D)/(4*in*on) + // eq. 33: first we calculate D(m) with m=Hr: + float alpha2 = m_ag * m_ag; + float cosThetaM = m_N.dot(Hr); + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + // eq. 34: now calculate G1(i,m) and G1(o,m) + float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + float G = G1o * G1i; + float out = (G * D) * 0.25f / cosNO; + // eq. 24 + float pm = D * cosThetaM; + // convert into pdf of the sampled direction + // eq. 38 - but see also: + // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + pdf = pm * 0.25f / Hr.dot(omega_out); + return Color3(out, out, out); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + if (Refractive == 0) return Color3(0, 0, 0); + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO <= 0 || cosNI >= 0) + return Color3(0, 0, 0); // vectors on same side -- not possible + // compute half-vector of the refraction (eq. 16) + Vec3 ht = -(m_eta * omega_in + omega_out); + Vec3 Ht = ht; Ht.normalize(); + float cosHO = Ht.dot(omega_out); float cosHI = Ht.dot(omega_in); // eq. 33: first we calculate D(m) with m=Ht: @@ -148,122 +148,123 @@ public: float invHt2 = 1 / ht.dot(ht); pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2; float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO; - return Color3 (out, out, out); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - Vec3 X, Y, Z = m_N; - make_orthonormals(Z, X, Y); - // generate a random microfacet normal m - // eq. 35,36: - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alpha2 = m_ag * m_ag; - float tanThetaM2 = alpha2 * randu / (1 - randu); - float cosThetaM = 1 / sqrtf(1 + tanThetaM2); - float sinThetaM = cosThetaM * sqrtf(tanThetaM2); - float phiM = 2 * float(M_PI) * randv; - Vec3 m = (cosf(phiM) * sinThetaM) * X + - (sinf(phiM) * sinThetaM) * Y + - cosThetaM * Z; - if (Refractive == 0) { - float cosMO = m.dot(omega_out); - if (cosMO > 0) { - // eq. 39 - compute actual reflected direction - omega_in = 2 * cosMO * m - omega_out; - if (Ng.dot(omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / cosMO; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - eval.setValue(out, out, out); - domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; - domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; + return Color3(out, out, out); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + Vec3 X, Y, Z = m_N; + make_orthonormals(Z, X, Y); + // generate a random microfacet normal m + // eq. 35,36: + // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) + // and sin(atan(x)) == x/sqrt(1+x^2) + float alpha2 = m_ag * m_ag; + float tanThetaM2 = alpha2 * randu / (1 - randu); + float cosThetaM = 1 / sqrtf(1 + tanThetaM2); + float sinThetaM = cosThetaM * sqrtf(tanThetaM2); + float phiM = 2 * float(M_PI) * randv; + Vec3 m = (cosf(phiM) * sinThetaM) * X + + (sinf(phiM) * sinThetaM) * Y + + cosThetaM * Z; + if (Refractive == 0) { + float cosMO = m.dot(omega_out); + if (cosMO > 0) { + // eq. 39 - compute actual reflected direction + omega_in = 2 * cosMO * m - omega_out; + if (Ng.dot(omega_in) > 0) { + // microfacet normal is visible to this ray + // eq. 33 + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + // eq. 24 + float pm = D * cosThetaM; + // convert into pdf of the sampled direction + // eq. 38 - but see also: + // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + pdf = pm * 0.25f / cosMO; + // eval BRDF*cosNI + float cosNI = m_N.dot(omega_in); + // eq. 34: now calculate G1(i,m) and G1(o,m) + float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + float G = G1o * G1i; + // eq. 20: (F*G*D)/(4*in*on) + float out = (G * D) * 0.25f / cosNO; + eval.setValue(out, out, out); + domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; + domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; /* disabled for now - gives texture filtering problems */ #if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // roughness but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; #endif - } - } - } else { - // CAUTION: the i and o variables are inverted relative to the paper - // eq. 39 - compute actual refractive direction - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - - if (!inside) { - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 21 - float cosHI = m.dot(omega_in); - float cosHO = m.dot(omega_out); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - eval.setValue(out, out, out); + } + } + } + else { + // CAUTION: the i and o variables are inverted relative to the paper + // eq. 39 - compute actual refractive direction + Vec3 R, dRdx, dRdy; + Vec3 T, dTdx, dTdy; + bool inside; + fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, + R, dRdx, dRdy, + T, dTdx, dTdy, + inside); + + if (!inside) { + omega_in = T; + domega_in_dx = dTdx; + domega_in_dy = dTdy; + // eq. 33 + float cosThetaM2 = cosThetaM * cosThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); + // eq. 24 + float pm = D * cosThetaM; + // eval BRDF*cosNI + float cosNI = m_N.dot(omega_in); + // eq. 34: now calculate G1(i,m) and G1(o,m) + float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); + float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); + float G = G1o * G1i; + // eq. 21 + float cosHI = m.dot(omega_in); + float cosHO = m.dot(omega_out); + float Ht2 = m_eta * cosHI + cosHO; + Ht2 *= Ht2; + float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); + // eq. 38 and eq. 17 + pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; + eval.setValue(out, out, out); /* disabled for now - gives texture filtering problems */ #if 0 - // Since there is some blur to this refraction, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; + // Since there is some blur to this refraction, make the + // derivatives a bit bigger. In theory this varies with the + // roughness but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; #endif - } - } - } - return Refractive ? Labels::TRANSMIT : Labels::REFLECT; - } + } + } + } + return Refractive ? Labels::TRANSMIT : Labels::REFLECT; + } }; // microfacet model with Beckmann facet distribution @@ -271,89 +272,92 @@ public: template class MicrofacetBeckmannClosure : public BSDFClosure { public: - Vec3 m_N; - float m_ab; // width parameter (roughness) - float m_eta; // index of refraction (for fresnel term) - MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { } + Vec3 m_N; + float m_ab; // width parameter (roughness) + float m_eta; // index of refraction (for fresnel term) + MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { + } - void setup() + void setup() { m_ab = clamp(m_ab, 1e-5f, 1.0f); } - bool mergeable (const ClosurePrimitive *other) const { - const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other; - return m_N == comp->m_N && m_ab == comp->m_ab && - m_eta == comp->m_eta && BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char * name () const { - return Refractive ? "microfacet_beckmann_refraction" - : "microfacet_beckmann"; - } - - void print_on (std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_ab << ", "; - out << m_eta; - out << ")"; - } - - float albedo (const Vec3 &omega_out) const - { + bool mergeable(const ClosurePrimitive *other) const { + const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other; + return m_N == comp->m_N && m_ab == comp->m_ab && + m_eta == comp->m_eta && BSDFClosure::mergeable(other); + } + + size_t memsize() const { + return sizeof(*this); + } + + const char *name() const { + return Refractive ? "microfacet_beckmann_refraction" + : "microfacet_beckmann"; + } + + void print_on(std::ostream &out) const + { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_ab << ", "; + out << m_eta; + out << ")"; + } + + float albedo(const Vec3 &omega_out) const + { return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 1) return Color3 (0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - // get half vector - Vec3 Hr = omega_in + omega_out; - Hr.normalize(); - // eq. 20: (F*G*D)/(4*in*on) - // eq. 25: first we calculate D(m) with m=Hr: - float alpha2 = m_ab * m_ab; - float cosThetaM = m_N.dot(Hr); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - float out = (G * D) * 0.25f / cosNO; - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / Hr.dot(omega_out); - return Color3 (out, out, out); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 0) return Color3 (0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO <= 0 || cosNI >= 0) - return Color3 (0, 0, 0); - // compute half-vector of the refraction (eq. 16) - Vec3 ht = -(m_eta * omega_in + omega_out); - Vec3 Ht = ht; Ht.normalize(); - float cosHO = Ht.dot(omega_out); + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + if (Refractive == 1) return Color3(0, 0, 0); + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO > 0 && cosNI > 0) { + // get half vector + Vec3 Hr = omega_in + omega_out; + Hr.normalize(); + // eq. 20: (F*G*D)/(4*in*on) + // eq. 25: first we calculate D(m) with m=Hr: + float alpha2 = m_ab * m_ab; + float cosThetaM = m_N.dot(Hr); + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); + // eq. 26, 27: now calculate G1(i,m) and G1(o,m) + float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); + float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); + float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; + float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G = G1o * G1i; + float out = (G * D) * 0.25f / cosNO; + // eq. 24 + float pm = D * cosThetaM; + // convert into pdf of the sampled direction + // eq. 38 - but see also: + // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + pdf = pm * 0.25f / Hr.dot(omega_out); + return Color3(out, out, out); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + if (Refractive == 0) return Color3(0, 0, 0); + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO <= 0 || cosNI >= 0) + return Color3(0, 0, 0); + // compute half-vector of the refraction (eq. 16) + Vec3 ht = -(m_eta * omega_in + omega_out); + Vec3 Ht = ht; Ht.normalize(); + float cosHO = Ht.dot(omega_out); float cosHI = Ht.dot(omega_in); // eq. 33: first we calculate D(m) with m=Ht: @@ -373,156 +377,161 @@ public: float invHt2 = 1 / ht.dot(ht); pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2; float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO; - return Color3 (out, out, out); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - Vec3 X, Y, Z = m_N; - make_orthonormals(Z, X, Y); - // generate a random microfacet normal m - // eq. 35,36: - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alpha2 = m_ab * m_ab; - float tanThetaM = sqrtf(-alpha2 * logf(1 - randu)); - float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM); - float sinThetaM = cosThetaM * tanThetaM; - float phiM = 2 * float(M_PI) * randv; - Vec3 m = (cosf(phiM) * sinThetaM) * X + - (sinf(phiM) * sinThetaM) * Y + - cosThetaM * Z; - if (Refractive == 0) { - float cosMO = m.dot(omega_out); - if (cosMO > 0) { - // eq. 39 - compute actual reflected direction - omega_in = 2 * cosMO * m - omega_out; - if (Ng.dot(omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 25 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / cosMO; - // Eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - eval.setValue(out, out, out); - domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; - domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; + return Color3(out, out, out); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + Vec3 X, Y, Z = m_N; + make_orthonormals(Z, X, Y); + // generate a random microfacet normal m + // eq. 35,36: + // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) + // and sin(atan(x)) == x/sqrt(1+x^2) + float alpha2 = m_ab * m_ab; + float tanThetaM = sqrtf(-alpha2 * logf(1 - randu)); + float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM); + float sinThetaM = cosThetaM * tanThetaM; + float phiM = 2 * float(M_PI) * randv; + Vec3 m = (cosf(phiM) * sinThetaM) * X + + (sinf(phiM) * sinThetaM) * Y + + cosThetaM * Z; + if (Refractive == 0) { + float cosMO = m.dot(omega_out); + if (cosMO > 0) { + // eq. 39 - compute actual reflected direction + omega_in = 2 * cosMO * m - omega_out; + if (Ng.dot(omega_in) > 0) { + // microfacet normal is visible to this ray + // eq. 25 + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = tanThetaM * tanThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); + // eq. 24 + float pm = D * cosThetaM; + // convert into pdf of the sampled direction + // eq. 38 - but see also: + // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf + pdf = pm * 0.25f / cosMO; + // Eval BRDF*cosNI + float cosNI = m_N.dot(omega_in); + // eq. 26, 27: now calculate G1(i,m) and G1(o,m) + float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); + float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); + float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; + float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G = G1o * G1i; + // eq. 20: (F*G*D)/(4*in*on) + float out = (G * D) * 0.25f / cosNO; + eval.setValue(out, out, out); + domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; + domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; /* disabled for now - gives texture filtering problems */ #if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // roughness but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; #endif - } - } - } else { - // CAUTION: the i and o variables are inverted relative to the paper - // eq. 39 - compute actual refractive direction - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - if (!inside) { - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 21 - float cosHI = m.dot(omega_in); - float cosHO = m.dot(omega_out); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - eval.setValue(out, out, out); + } + } + } + else { + // CAUTION: the i and o variables are inverted relative to the paper + // eq. 39 - compute actual refractive direction + Vec3 R, dRdx, dRdy; + Vec3 T, dTdx, dTdy; + bool inside; + fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, + R, dRdx, dRdy, + T, dTdx, dTdy, + inside); + if (!inside) { + omega_in = T; + domega_in_dx = dTdx; + domega_in_dy = dTdy; + // eq. 33 + float cosThetaM2 = cosThetaM * cosThetaM; + float tanThetaM2 = tanThetaM * tanThetaM; + float cosThetaM4 = cosThetaM2 * cosThetaM2; + float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); + // eq. 24 + float pm = D * cosThetaM; + // eval BRDF*cosNI + float cosNI = m_N.dot(omega_in); + // eq. 26, 27: now calculate G1(i,m) and G1(o,m) + float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); + float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); + float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; + float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G = G1o * G1i; + // eq. 21 + float cosHI = m.dot(omega_in); + float cosHO = m.dot(omega_out); + float Ht2 = m_eta * cosHI + cosHO; + Ht2 *= Ht2; + float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); + // eq. 38 and eq. 17 + pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; + eval.setValue(out, out, out); /* disabled for now - gives texture filtering problems */ #if 0 - // Since there is some blur to this refraction, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; + // Since there is some blur to this refraction, make the + // derivatives a bit bigger. In theory this varies with the + // roughness but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; #endif - } - } - } - return Refractive ? Labels::TRANSMIT : Labels::REFLECT; - } + } + } + } + return Refractive ? Labels::TRANSMIT : Labels::REFLECT; + } }; ClosureParam bsdf_microfacet_ggx_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N), - CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<0>, m_ag), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) }; + CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N), + CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<0>, m_ag), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) +}; ClosureParam bsdf_microfacet_ggx_refraction_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N), - CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<1>, m_ag), - CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<1>, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>) }; + CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N), + CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_ag), + CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_eta), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>) +}; ClosureParam bsdf_microfacet_beckmann_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N), - CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<0>, m_ab), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) }; + CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<0>, m_ab), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) +}; ClosureParam bsdf_microfacet_beckmann_refraction_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N), - CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<1>, m_ab), - CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<1>, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>) }; + CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_ab), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_eta), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>) +}; CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>) CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>) diff --git a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp b/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp index dd6c59d98c2..83d0e583695 100644 --- a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp +++ b/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp @@ -26,13 +26,13 @@ CCL_NAMESPACE_BEGIN using namespace OSL; -class OrenNayarClosure: public BSDFClosure { +class OrenNayarClosure : public BSDFClosure { public: Vec3 m_N; float m_sigma; float m_a, m_b; - OrenNayarClosure(): BSDFClosure(Labels::DIFFUSE) {} + OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {} void setup() { m_sigma = clamp(m_sigma, 0.0f, 1.0f); @@ -43,19 +43,19 @@ public: m_b = m_sigma * div; } - bool mergeable(const ClosurePrimitive* other) const { - const OrenNayarClosure* comp = static_cast(other); + bool mergeable(const ClosurePrimitive *other) const { + const OrenNayarClosure *comp = static_cast(other); return - m_N == comp->m_N && - m_sigma == comp->m_sigma && - BSDFClosure::mergeable(other); + m_N == comp->m_N && + m_sigma == comp->m_sigma && + BSDFClosure::mergeable(other); } size_t memsize() const { return sizeof(*this); } - const char* name() const { + const char *name() const { return "oren_nayar"; } @@ -87,13 +87,13 @@ public: } ustring sample( - const Vec3& Ng, - const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy, - float randu, float randv, - Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy, - float& pdf, Color3& eval - ) const { - sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf); + const Vec3& Ng, + const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy, + float randu, float randv, + Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy, + float& pdf, Color3& eval + ) const { + sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); if (Ng.dot(omega_in) > 0.0f) { float is = get_intensity(m_N, omega_out, omega_in); @@ -118,7 +118,7 @@ private: float nv = max(n.dot(v), 0.0f); float t = l.dot(v) - nl * nv; - if(t > 0.0f) { + if (t > 0.0f) { t /= max(nl, nv) + 1e-8f; } return nl * (m_a + m_b * t); @@ -126,10 +126,10 @@ private: }; ClosureParam bsdf_oren_nayar_params[] = { - CLOSURE_VECTOR_PARAM (OrenNayarClosure, m_N), - CLOSURE_FLOAT_PARAM (OrenNayarClosure, m_sigma), - CLOSURE_STRING_KEYPARAM ("label"), - CLOSURE_FINISH_PARAM (OrenNayarClosure) + CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N), + CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(OrenNayarClosure) }; CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure) diff --git a/intern/cycles/kernel/osl/bsdf_reflection.cpp b/intern/cycles/kernel/osl/bsdf_reflection.cpp index b0caff6df44..7041b4ced6f 100644 --- a/intern/cycles/kernel/osl/bsdf_reflection.cpp +++ b/intern/cycles/kernel/osl/bsdf_reflection.cpp @@ -42,65 +42,66 @@ using namespace OSL; class ReflectionClosure : public BSDFClosure { public: - Vec3 m_N; // shading normal - ReflectionClosure() : BSDFClosure(Labels::SINGULAR) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const ReflectionClosure *comp = (const ReflectionClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "reflection"; } - - void print_on (std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // only one direction is possible - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - omega_in = (2 * cosNO) * m_N - omega_out; - if (Ng.dot(omega_in) > 0) { - domega_in_dx = 2 * m_N.dot(domega_out_dx) * m_N - domega_out_dx; - domega_in_dy = 2 * m_N.dot(domega_out_dy) * m_N - domega_out_dy; - pdf = 1; - eval.setValue(1, 1, 1); - } - } - return Labels::REFLECT; - } + Vec3 m_N; // shading normal + ReflectionClosure() : BSDFClosure(Labels::SINGULAR) {} + + void setup() {}; + + bool mergeable(const ClosurePrimitive *other) const { + const ReflectionClosure *comp = (const ReflectionClosure *)other; + return m_N == comp->m_N && BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "reflection"; } + + void print_on(std::ostream &out) const { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // only one direction is possible + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + omega_in = (2 * cosNO) * m_N - omega_out; + if (Ng.dot(omega_in) > 0) { + domega_in_dx = 2 * m_N.dot(domega_out_dx) * m_N - domega_out_dx; + domega_in_dy = 2 * m_N.dot(domega_out_dy) * m_N - domega_out_dy; + pdf = 1; + eval.setValue(1, 1, 1); + } + } + return Labels::REFLECT; + } }; ClosureParam bsdf_reflection_params[] = { - CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(ReflectionClosure) }; + CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(ReflectionClosure) +}; CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure) diff --git a/intern/cycles/kernel/osl/bsdf_refraction.cpp b/intern/cycles/kernel/osl/bsdf_refraction.cpp index 3ae7a3811b4..f56ad7b127c 100644 --- a/intern/cycles/kernel/osl/bsdf_refraction.cpp +++ b/intern/cycles/kernel/osl/bsdf_refraction.cpp @@ -42,77 +42,78 @@ using namespace OSL; class RefractionClosure : public BSDFClosure { public: - Vec3 m_N; // shading normal - float m_eta; // ratio of indices of refraction (inside / outside) - RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) { } + Vec3 m_N; // shading normal + float m_eta; // ratio of indices of refraction (inside / outside) + RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) {} - void setup() {} + void setup() {} - bool mergeable (const ClosurePrimitive *other) const { - const RefractionClosure *comp = (const RefractionClosure *)other; - return m_N == comp->m_N && m_eta == comp->m_eta && - BSDFClosure::mergeable(other); - } + bool mergeable(const ClosurePrimitive *other) const { + const RefractionClosure *comp = (const RefractionClosure *)other; + return m_N == comp->m_N && m_eta == comp->m_eta && + BSDFClosure::mergeable(other); + } - size_t memsize () const { return sizeof(*this); } + size_t memsize() const { return sizeof(*this); } - const char *name () const { return "refraction"; } + const char *name() const { return "refraction"; } - void print_on (std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_eta; - out << ")"; - } + void print_on(std::ostream &out) const { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_eta; + out << ")"; + } - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } - float albedo (const Vec3 &omega_out) const - { + float albedo(const Vec3 &omega_out) const + { return 1.0f; - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - - fresnel_dielectric(m_eta, m_N, - omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - - if (!inside) { - pdf = 1; - eval.setValue(1.0f, 1.0f, 1.0f); - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - } - - return Labels::TRANSMIT; - } + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + Vec3 R, dRdx, dRdy; + Vec3 T, dTdx, dTdy; + bool inside; + + fresnel_dielectric(m_eta, m_N, + omega_out, domega_out_dx, domega_out_dy, + R, dRdx, dRdy, + T, dTdx, dTdy, + inside); + + if (!inside) { + pdf = 1; + eval.setValue(1.0f, 1.0f, 1.0f); + omega_in = T; + domega_in_dx = dTdx; + domega_in_dy = dTdy; + } + + return Labels::TRANSMIT; + } }; ClosureParam bsdf_refraction_params[] = { - CLOSURE_VECTOR_PARAM(RefractionClosure, m_N), - CLOSURE_FLOAT_PARAM (RefractionClosure, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(RefractionClosure) }; + CLOSURE_VECTOR_PARAM(RefractionClosure, m_N), + CLOSURE_FLOAT_PARAM(RefractionClosure, m_eta), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(RefractionClosure) +}; CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure) diff --git a/intern/cycles/kernel/osl/bsdf_transparent.cpp b/intern/cycles/kernel/osl/bsdf_transparent.cpp index 941abd6a483..acde92530a2 100644 --- a/intern/cycles/kernel/osl/bsdf_transparent.cpp +++ b/intern/cycles/kernel/osl/bsdf_transparent.cpp @@ -42,54 +42,55 @@ using namespace OSL; class TransparentClosure : public BSDFClosure { public: - TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) { } - - void setup() {} - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "transparent"; } - - void print_on (std::ostream &out) const { - out << name() << " ()"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // only one direction is possible - omega_in = -omega_out; - domega_in_dx = -domega_out_dx; - domega_in_dy = -domega_out_dy; - pdf = 1; - eval.setValue(1, 1, 1); - return Labels::TRANSMIT; - } + TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) {} + + void setup() {} + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "transparent"; } + + void print_on(std::ostream &out) const { + out << name() << " ()"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // only one direction is possible + omega_in = -omega_out; + domega_in_dx = -domega_out_dx; + domega_in_dy = -domega_out_dy; + pdf = 1; + eval.setValue(1, 1, 1); + return Labels::TRANSMIT; + } }; ClosureParam bsdf_transparent_params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(TransparentClosure) }; + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(TransparentClosure) +}; CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure) diff --git a/intern/cycles/kernel/osl/bsdf_ward.cpp b/intern/cycles/kernel/osl/bsdf_ward.cpp index a7742a04d13..4aacbc4ffc3 100644 --- a/intern/cycles/kernel/osl/bsdf_ward.cpp +++ b/intern/cycles/kernel/osl/bsdf_ward.cpp @@ -46,175 +46,179 @@ using namespace OSL; // see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf class WardClosure : public BSDFClosure { public: - Vec3 m_N; - Vec3 m_T; - float m_ax, m_ay; - WardClosure() : BSDFClosure(Labels::GLOSSY) { } + Vec3 m_N; + Vec3 m_T; + float m_ax, m_ay; + WardClosure() : BSDFClosure(Labels::GLOSSY) {} - void setup() + void setup() { m_ax = clamp(m_ax, 1e-5f, 1.0f); m_ay = clamp(m_ay, 1e-5f, 1.0f); } - bool mergeable (const ClosurePrimitive *other) const { - const WardClosure *comp = (const WardClosure *)other; - return m_N == comp->m_N && m_T == comp->m_T && - m_ax == comp->m_ax && m_ay == comp->m_ay && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "ward"; } - - void print_on (std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ("; - out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), "; - out << m_ax << ", " << m_ay << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNI > 0 && cosNO > 0) { - // get half vector and get x,y basis on the surface for anisotropy - Vec3 H = omega_in + omega_out; - H.normalize(); // normalize needed for pdf - Vec3 X, Y; - make_orthonormals(m_N, m_T, X, Y); - // eq. 4 - float dotx = H.dot(X) / m_ax; - float doty = H.dot(Y) / m_ay; - float dotn = H.dot(m_N); - float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); - float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); - float exp_val = expf(-exp_arg); - float out = cosNI * exp_val / denom; - float oh = H.dot(omega_out); - denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; - pdf = exp_val / denom; - return Color3 (out, out, out); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // get x,y basis on the surface for anisotropy - Vec3 X, Y; - make_orthonormals(m_N, m_T, X, Y); - // generate random angles for the half vector - // eq. 7 (taking care around discontinuities to keep - // output angle in the right quadrant) - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alphaRatio = m_ay / m_ax; - float cosPhi, sinPhi; - if (randu < 0.25f) { - float val = 4 * randu; - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = tanPhi * cosPhi; - } else if (randu < 0.5) { - float val = 1 - 4 * (0.5f - randu); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - // phi = (float) M_PI - phi; - cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = -tanPhi * cosPhi; - } else if (randu < 0.75f) { - float val = 4 * (randu - 0.5f); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - //phi = (float) M_PI + phi; - cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = tanPhi * cosPhi; - } else { - float val = 1 - 4 * (1 - randu); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - // phi = 2 * (float) M_PI - phi; - cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = -tanPhi * cosPhi; - } - // eq. 6 - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay); - float tanTheta2 = -logf(1 - randv) / thetaDenom; - float cosTheta = 1 / sqrtf(1 + tanTheta2); - float sinTheta = cosTheta * sqrtf(tanTheta2); - - Vec3 h; // already normalized becaused expressed from spherical coordinates - h.x = sinTheta * cosPhi; - h.y = sinTheta * sinPhi; - h.z = cosTheta; - // compute terms that are easier in local space - float dotx = h.x / m_ax; - float doty = h.y / m_ay; - float dotn = h.z; - // transform to world space - h = h.x * X + h.y * Y + h.z * m_N; - // generate the final sample - float oh = h.dot(omega_out); - omega_in.x = 2 * oh * h.x - omega_out.x; - omega_in.y = 2 * oh * h.y - omega_out.y; - omega_in.z = 2 * oh * h.z - omega_out.z; - if (Ng.dot(omega_in) > 0) { - float cosNI = m_N.dot(omega_in); - if (cosNI > 0) { - // eq. 9 - float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); - float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; - pdf = expf(-exp_arg) / denom; - // compiler will reuse expressions already computed - denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); - float power = cosNI * expf(-exp_arg) / denom; - eval.setValue(power, power, power); - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + bool mergeable(const ClosurePrimitive *other) const { + const WardClosure *comp = (const WardClosure *)other; + return m_N == comp->m_N && m_T == comp->m_T && + m_ax == comp->m_ax && m_ay == comp->m_ay && + BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "ward"; } + + void print_on(std::ostream &out) const { + out << name() << " (("; + out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ("; + out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), "; + out << m_ax << ", " << m_ay << ")"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNI > 0 && cosNO > 0) { + // get half vector and get x,y basis on the surface for anisotropy + Vec3 H = omega_in + omega_out; + H.normalize(); // normalize needed for pdf + Vec3 X, Y; + make_orthonormals(m_N, m_T, X, Y); + // eq. 4 + float dotx = H.dot(X) / m_ax; + float doty = H.dot(Y) / m_ay; + float dotn = H.dot(m_N); + float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); + float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); + float exp_val = expf(-exp_arg); + float out = cosNI * exp_val / denom; + float oh = H.dot(omega_out); + denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; + pdf = exp_val / denom; + return Color3(out, out, out); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + // get x,y basis on the surface for anisotropy + Vec3 X, Y; + make_orthonormals(m_N, m_T, X, Y); + // generate random angles for the half vector + // eq. 7 (taking care around discontinuities to keep + // output angle in the right quadrant) + // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) + // and sin(atan(x)) == x/sqrt(1+x^2) + float alphaRatio = m_ay / m_ax; + float cosPhi, sinPhi; + if (randu < 0.25f) { + float val = 4 * randu; + float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); + cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); + sinPhi = tanPhi * cosPhi; + } + else if (randu < 0.5) { + float val = 1 - 4 * (0.5f - randu); + float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); + // phi = (float) M_PI - phi; + cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); + sinPhi = -tanPhi * cosPhi; + } + else if (randu < 0.75f) { + float val = 4 * (randu - 0.5f); + float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); + //phi = (float) M_PI + phi; + cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); + sinPhi = tanPhi * cosPhi; + } + else { + float val = 1 - 4 * (1 - randu); + float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); + // phi = 2 * (float) M_PI - phi; + cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); + sinPhi = -tanPhi * cosPhi; + } + // eq. 6 + // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) + // and sin(atan(x)) == x/sqrt(1+x^2) + float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay); + float tanTheta2 = -logf(1 - randv) / thetaDenom; + float cosTheta = 1 / sqrtf(1 + tanTheta2); + float sinTheta = cosTheta * sqrtf(tanTheta2); + + Vec3 h; // already normalized becaused expressed from spherical coordinates + h.x = sinTheta * cosPhi; + h.y = sinTheta * sinPhi; + h.z = cosTheta; + // compute terms that are easier in local space + float dotx = h.x / m_ax; + float doty = h.y / m_ay; + float dotn = h.z; + // transform to world space + h = h.x * X + h.y * Y + h.z * m_N; + // generate the final sample + float oh = h.dot(omega_out); + omega_in.x = 2 * oh * h.x - omega_out.x; + omega_in.y = 2 * oh * h.y - omega_out.y; + omega_in.z = 2 * oh * h.z - omega_out.z; + if (Ng.dot(omega_in) > 0) { + float cosNI = m_N.dot(omega_in); + if (cosNI > 0) { + // eq. 9 + float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); + float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; + pdf = expf(-exp_arg) / denom; + // compiler will reuse expressions already computed + denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); + float power = cosNI * expf(-exp_arg) / denom; + eval.setValue(power, power, power); + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; /* disabled for now - gives texture filtering problems */ #if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // roughness but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; #endif - } - } - } - return Labels::REFLECT; - } + } + } + } + return Labels::REFLECT; + } }; ClosureParam bsdf_ward_params[] = { - CLOSURE_VECTOR_PARAM(WardClosure, m_N), - CLOSURE_VECTOR_PARAM(WardClosure, m_T), - CLOSURE_FLOAT_PARAM (WardClosure, m_ax), - CLOSURE_FLOAT_PARAM (WardClosure, m_ay), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WardClosure) }; + CLOSURE_VECTOR_PARAM(WardClosure, m_N), + CLOSURE_VECTOR_PARAM(WardClosure, m_T), + CLOSURE_FLOAT_PARAM(WardClosure, m_ax), + CLOSURE_FLOAT_PARAM(WardClosure, m_ay), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(WardClosure) +}; CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure) diff --git a/intern/cycles/kernel/osl/bsdf_westin.cpp b/intern/cycles/kernel/osl/bsdf_westin.cpp index d322f6a7f7e..a476e8045f7 100644 --- a/intern/cycles/kernel/osl/bsdf_westin.cpp +++ b/intern/cycles/kernel/osl/bsdf_westin.cpp @@ -44,193 +44,197 @@ using namespace OSL; class WestinBackscatterClosure : public BSDFClosure { public: - Vec3 m_N; - float m_roughness; - float m_invroughness; - WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) { } + Vec3 m_N; + float m_roughness; + float m_invroughness; + WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {} - void setup() - { + void setup() + { m_roughness = clamp(m_roughness, 1e-5f, 1.0f); - m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; - } - - bool mergeable (const ClosurePrimitive *other) const { - const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; - return m_N == comp->m_N && m_roughness == comp->m_roughness && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "westin_backscatter"; } - - void print_on (std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_roughness; - out << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float cosine = omega_out.dot(omega_in); - pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; - pdf *= 0.5f * float(M_1_PI); - return Color3 (pdf, pdf, pdf); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - domega_in_dx = domega_out_dx; - domega_in_dy = domega_out_dy; - Vec3 T, B; - make_orthonormals (omega_out, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_invroughness + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - ( cosTheta) * omega_out; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); - pdf = (m_invroughness + 1) * pdf; - eval.setValue(pdf, pdf, pdf); - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } + m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; + } + + bool mergeable(const ClosurePrimitive *other) const { + const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; + return m_N == comp->m_N && m_roughness == comp->m_roughness && + BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "westin_backscatter"; } + + void print_on(std::ostream &out) const + { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_roughness; + out << ")"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + // pdf is implicitly 0 (no indirect sampling) + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO > 0 && cosNI > 0) { + float cosine = omega_out.dot(omega_in); + pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; + pdf *= 0.5f * float(M_1_PI); + return Color3(pdf, pdf, pdf); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + domega_in_dx = domega_out_dx; + domega_in_dy = domega_out_dy; + Vec3 T, B; + make_orthonormals(omega_out, T, B); + float phi = 2 * (float) M_PI * randu; + float cosTheta = powf(randv, 1 / (m_invroughness + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + (cosTheta) * omega_out; + if (Ng.dot(omega_in) > 0) + { + // common terms for pdf and eval + float cosNI = m_N.dot(omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); + pdf = (m_invroughness + 1) * pdf; + eval.setValue(pdf, pdf, pdf); + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; + } + } + } + return Labels::REFLECT; + } }; class WestinSheenClosure : public BSDFClosure { public: - Vec3 m_N; - float m_edginess; + Vec3 m_N; + float m_edginess; // float m_normalization; - WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const WestinSheenClosure *comp = (const WestinSheenClosure *)other; - return m_N == comp->m_N && m_edginess == comp->m_edginess && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "westin_sheen"; } - - void print_on (std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_edginess; - out << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float sinNO2 = 1 - cosNO * cosNO; - pdf = cosNI * float(M_1_PI); - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - return Color3 (westin, westin, westin); - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - // TODO: account for sheen when sampling - float cosNO = m_N.dot(omega_out); - float sinNO2 = 1 - cosNO * cosNO; - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - eval.setValue(westin, westin, westin); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } else - pdf = 0; - return Labels::REFLECT; - } + WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {} + + void setup() {}; + + bool mergeable(const ClosurePrimitive *other) const { + const WestinSheenClosure *comp = (const WestinSheenClosure *)other; + return m_N == comp->m_N && m_edginess == comp->m_edginess && + BSDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "westin_sheen"; } + + void print_on(std::ostream &out) const + { + out << name() << " ("; + out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_edginess; + out << ")"; + } + + float albedo(const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + // pdf is implicitly 0 (no indirect sampling) + float cosNO = m_N.dot(omega_out); + float cosNI = m_N.dot(omega_in); + if (cosNO > 0 && cosNI > 0) { + float sinNO2 = 1 - cosNO * cosNO; + pdf = cosNI * float(M_1_PI); + float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; + return Color3(westin, westin, westin); + } + return Color3(0, 0, 0); + } + + Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const + { + return Color3(0, 0, 0); + } + + ustring sample(const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + // we are viewing the surface from the right side - send a ray out with cosine + // distribution over the hemisphere + sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); + if (Ng.dot(omega_in) > 0) { + // TODO: account for sheen when sampling + float cosNO = m_N.dot(omega_out); + float sinNO2 = 1 - cosNO * cosNO; + float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; + eval.setValue(westin, westin, westin); + // TODO: find a better approximation for the diffuse bounce + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + domega_in_dx *= 125; + domega_in_dy *= 125; + } + else { + pdf = 0; + } + return Labels::REFLECT; + } }; ClosureParam bsdf_westin_backscatter_params[] = { - CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), - CLOSURE_FLOAT_PARAM (WestinBackscatterClosure, m_roughness), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinBackscatterClosure) }; + CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), + CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(WestinBackscatterClosure) +}; ClosureParam bsdf_westin_sheen_params[] = { - CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), - CLOSURE_FLOAT_PARAM (WestinSheenClosure, m_edginess), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinSheenClosure) }; + CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), + CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(WestinSheenClosure) +}; CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure) CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure) diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bssrdf.cpp index 66d7818e677..b195cf513cd 100644 --- a/intern/cycles/kernel/osl/bssrdf.cpp +++ b/intern/cycles/kernel/osl/bssrdf.cpp @@ -42,62 +42,63 @@ using namespace OSL; class BSSRDFCubicClosure : public BSSRDFClosure { public: - Color3 m_radius; - Color3 m_scale; - float m_max_radius; - - template - static inline T pow3 (const T &x) { return x * x * x; } - - template - static inline T pow5 (const T &x) { T x2 = x * x; return x2 * x2 * x; } - - BSSRDFCubicClosure() { } - - void setup() - { - // pre-compute some terms - m_max_radius = 0; - for (int i = 0; i < 3; i++) { - m_scale[i] = m_radius[i] > 0 ? 4 / pow5 (m_radius[i]) : 0; - m_max_radius = std::max (m_max_radius, m_radius[i]); - } - } - - bool mergeable (const ClosurePrimitive *other) const { - const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other; - return m_radius == comp->m_radius && BSSRDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "bssrdf_cubic"; } - - void print_on (std::ostream &out) const - { - out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), (" - << m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))"; - } - - Color3 eval (float r) const - { - return Color3 ((r < m_radius.x) ? pow3 (m_radius.x - r) * m_scale.x : 0, - (r < m_radius.y) ? pow3 (m_radius.y - r) * m_scale.y : 0, - (r < m_radius.z) ? pow3 (m_radius.z - r) * m_scale.z : 0); - } - - float max_radius() const - { - return m_max_radius; - } + Color3 m_radius; + Color3 m_scale; + float m_max_radius; + + template + static inline T pow3(const T &x) { return x * x * x; } + + template + static inline T pow5(const T &x) { T x2 = x * x; return x2 * x2 * x; } + + BSSRDFCubicClosure() {} + + void setup() + { + // pre-compute some terms + m_max_radius = 0; + for (int i = 0; i < 3; i++) { + m_scale[i] = m_radius[i] > 0 ? 4 / pow5(m_radius[i]) : 0; + m_max_radius = std::max(m_max_radius, m_radius[i]); + } + } + + bool mergeable(const ClosurePrimitive *other) const { + const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other; + return m_radius == comp->m_radius && BSSRDFClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "bssrdf_cubic"; } + + void print_on(std::ostream &out) const + { + out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), (" + << m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))"; + } + + Color3 eval(float r) const + { + return Color3((r < m_radius.x) ? pow3(m_radius.x - r) * m_scale.x : 0, + (r < m_radius.y) ? pow3(m_radius.y - r) * m_scale.y : 0, + (r < m_radius.z) ? pow3(m_radius.z - r) * m_scale.z : 0); + } + + float max_radius() const + { + return m_max_radius; + } }; ClosureParam closure_bssrdf_cubic_params[] = { - CLOSURE_COLOR_PARAM (BSSRDFCubicClosure, m_radius), - CLOSURE_STRING_KEYPARAM ("label"), - CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) }; + CLOSURE_COLOR_PARAM(BSSRDFCubicClosure, m_radius), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) +}; CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure) diff --git a/intern/cycles/kernel/osl/debug.cpp b/intern/cycles/kernel/osl/debug.cpp index 8c3f8b2b323..768a9100e8a 100644 --- a/intern/cycles/kernel/osl/debug.cpp +++ b/intern/cycles/kernel/osl/debug.cpp @@ -49,30 +49,31 @@ using namespace OSL; class DebugClosure : public ClosurePrimitive { public: - ustring m_tag; + ustring m_tag; - DebugClosure () : ClosurePrimitive (Debug) { } + DebugClosure () : ClosurePrimitive(Debug) {} - bool mergeable (const ClosurePrimitive *other) const { - const DebugClosure *comp = (const DebugClosure *)other; - return m_tag == comp->m_tag && - ClosurePrimitive::mergeable(other); - } + bool mergeable(const ClosurePrimitive *other) const { + const DebugClosure *comp = (const DebugClosure *)other; + return m_tag == comp->m_tag && + ClosurePrimitive::mergeable(other); + } - size_t memsize () const { return sizeof(*this); } + size_t memsize() const { return sizeof(*this); } - const char *name () const { return "debug"; } + const char *name() const { return "debug"; } - void print_on (std::ostream &out) const { - out << name() << " (\"" << m_tag.c_str() << "\")"; - } + void print_on(std::ostream &out) const { + out << name() << " (\"" << m_tag.c_str() << "\")"; + } }; ClosureParam closure_debug_params[] = { - CLOSURE_STRING_PARAM(DebugClosure, m_tag), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(DebugClosure) }; + CLOSURE_STRING_PARAM(DebugClosure, m_tag), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(DebugClosure) +}; CLOSURE_PREPARE(closure_debug_prepare, DebugClosure) diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp index 2d2d6e1fdde..0a582c3f558 100644 --- a/intern/cycles/kernel/osl/emissive.cpp +++ b/intern/cycles/kernel/osl/emissive.cpp @@ -49,57 +49,58 @@ using namespace OSL; /// class GenericEmissiveClosure : public EmissiveClosure { public: - GenericEmissiveClosure() { } - - void setup() { } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "emission"; } - - void print_on (std::ostream &out) const { - out << name() << "()"; - } - - Color3 eval (const Vec3 &Ng, const Vec3 &omega_out) const - { - float cosNO = fabsf(Ng.dot(omega_out)); - float res = cosNO > 0 ? 1.0f: 0.0f; - return Color3(res, res, res); - } - - void sample (const Vec3 &Ng, float randu, float randv, - Vec3 &omega_out, float &pdf) const - { - // We don't do anything sophisticated here for the step - // We just sample the whole cone uniformly to the cosine - Vec3 T, B; - make_orthonormals(Ng, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = sqrtf(1.0f - 1.0f * randv); - float sinTheta = sqrtf(1.0f - cosTheta * cosTheta); - omega_out = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - cosTheta * Ng; - pdf = 1.0f / float(M_PI); - } - - /// Return the probability distribution function in the direction omega_out, - /// given the parameters and the light's surface normal. This MUST match - /// the PDF computed by sample(). - float pdf (const Vec3 &Ng, - const Vec3 &omega_out) const - { - float cosNO = Ng.dot(omega_out); - return cosNO > 0 ? 1.0f: 0.0f; - } + GenericEmissiveClosure() { } + + void setup() {} + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "emission"; } + + void print_on(std::ostream &out) const { + out << name() << "()"; + } + + Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const + { + float cosNO = fabsf(Ng.dot(omega_out)); + float res = cosNO > 0 ? 1.0f : 0.0f; + return Color3(res, res, res); + } + + void sample(const Vec3 &Ng, float randu, float randv, + Vec3 &omega_out, float &pdf) const + { + // We don't do anything sophisticated here for the step + // We just sample the whole cone uniformly to the cosine + Vec3 T, B; + make_orthonormals(Ng, T, B); + float phi = 2 * (float) M_PI * randu; + float cosTheta = sqrtf(1.0f - 1.0f * randv); + float sinTheta = sqrtf(1.0f - cosTheta * cosTheta); + omega_out = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + cosTheta * Ng; + pdf = 1.0f / float(M_PI); + } + + /// Return the probability distribution function in the direction omega_out, + /// given the parameters and the light's surface normal. This MUST match + /// the PDF computed by sample(). + float pdf(const Vec3 &Ng, + const Vec3 &omega_out) const + { + float cosNO = Ng.dot(omega_out); + return cosNO > 0 ? 1.0f : 0.0f; + } }; ClosureParam closure_emission_params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(GenericEmissiveClosure) }; + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(GenericEmissiveClosure) +}; CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure) diff --git a/intern/cycles/kernel/osl/nodes/node_color.h b/intern/cycles/kernel/osl/nodes/node_color.h index 37d092eae78..80786e4e369 100644 --- a/intern/cycles/kernel/osl/nodes/node_color.h +++ b/intern/cycles/kernel/osl/nodes/node_color.h @@ -18,18 +18,18 @@ float color_srgb_to_scene_linear(float c) { - if(c < 0.04045) - return (c < 0.0)? 0.0: c * (1.0/12.92); + if (c < 0.04045) + return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); else - return pow((c + 0.055)*(1.0/1.055), 2.4); + return pow((c + 0.055) * (1.0 / 1.055), 2.4); } float color_scene_linear_to_srgb(float c) { - if(c < 0.0031308) - return (c < 0.0)? 0.0: c * 12.92; - else - return 1.055 * pow(c, 1.0/2.4) - 0.055; + if (c < 0.0031308) + return (c < 0.0) ? 0.0 : c * 12.92; + else + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; } color color_srgb_to_scene_linear(color c) @@ -61,27 +61,27 @@ color rgb_to_hsv(color rgb) v = cmax; - if(cmax != 0.0) { - s = cdelta/cmax; + if (cmax != 0.0) { + s = cdelta / cmax; } else { s = 0.0; h = 0.0; } - if(s == 0.0) { + if (s == 0.0) { h = 0.0; } else { - c = (color(cmax, cmax, cmax) - rgb)/cdelta; + c = (color(cmax, cmax, cmax) - rgb) / cdelta; - if(rgb[0] == cmax) h = c[2] - c[1]; - else if(rgb[1] == cmax) h = 2.0 + c[0] - c[2]; + if (rgb[0] == cmax) h = c[2] - c[1]; + else if (rgb[1] == cmax) h = 2.0 + c[0] - c[2]; else h = 4.0 + c[1] - c[0]; h /= 6.0; - if(h < 0.0) + if (h < 0.0) h += 1.0; } @@ -97,26 +97,26 @@ color hsv_to_rgb(color hsv) s = hsv[1]; v = hsv[2]; - if(s==0.0) { + if (s == 0.0) { rgb = color(v, v, v); } else { - if(h==1.0) + if (h == 1.0) h = 0.0; h *= 6.0; i = floor(h); f = h - i; rgb = color(f, f, f); - p = v*(1.0-s); - q = v*(1.0-(s*f)); - t = v*(1.0-(s*(1.0-f))); - - if(i == 0.0) rgb = color(v, t, p); - else if(i == 1.0) rgb = color(q, v, p); - else if(i == 2.0) rgb = color(p, v, t); - else if(i == 3.0) rgb = color(p, q, v); - else if(i == 4.0) rgb = color(t, p, v); + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + if (i == 0.0) rgb = color(v, t, p); + else if (i == 1.0) rgb = color(q, v, p); + else if (i == 2.0) rgb = color(p, v, t); + else if (i == 3.0) rgb = color(p, q, v); + else if (i == 4.0) rgb = color(t, p, v); else rgb = color(v, p, q); } diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.h b/intern/cycles/kernel/osl/nodes/node_fresnel.h index 0c8a5276ede..0368c1910aa 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.h +++ b/intern/cycles/kernel/osl/nodes/node_fresnel.h @@ -7,11 +7,11 @@ float fresnel_dielectric(vector Incoming, normal Normal, float eta) float g = eta * eta - 1 + c * c; float result; - if(g > 0) { + if (g > 0) { g = sqrt(g); - float A =(g - c)/(g + c); - float B =(c *(g + c)- 1)/(c *(g - c)+ 1); - result = 0.5 * A * A *(1 + B * B); + float A = (g - c) / (g + c); + float B = (c * (g + c) - 1) / (c * (g - c) + 1); + result = 0.5 * A * A * (1 + B * B); } else result = 1.0; /* TIR (no refracted component) */ diff --git a/intern/cycles/kernel/osl/nodes/node_texture.h b/intern/cycles/kernel/osl/nodes/node_texture.h index e0ec8038ee4..d2dbd6db8b3 100644 --- a/intern/cycles/kernel/osl/nodes/node_texture.h +++ b/intern/cycles/kernel/osl/nodes/node_texture.h @@ -20,20 +20,20 @@ float voronoi_distance(string distance_metric, vector d, float e) { float result = 0.0; - if(distance_metric == "Distance Squared") + if (distance_metric == "Distance Squared") result = dot(d, d); - if(distance_metric == "Actual Distance") + if (distance_metric == "Actual Distance") result = length(d); - if(distance_metric == "Manhattan") + if (distance_metric == "Manhattan") result = fabs(d[0]) + fabs(d[1]) + fabs(d[2]); - if(distance_metric == "Chebychev") + if (distance_metric == "Chebychev") result = max(fabs(d[0]), max(fabs(d[1]), fabs(d[2]))); - if(distance_metric == "Minkovsky 1/2") + if (distance_metric == "Minkovsky 1/2") result = sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1])); - if(distance_metric == "Minkovsky 4") - result = sqrt(sqrt(dot(d*d, d*d))); - if(distance_metric == "Minkovsky") - result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0/e); + if (distance_metric == "Minkovsky 4") + result = sqrt(sqrt(dot(d * d, d * d))); + if (distance_metric == "Minkovsky") + result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e); return result; } @@ -63,9 +63,9 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4]) da[2] = 1e10; da[3] = 1e10; - for(xx = xi-1; xx <= xi+1; xx++) { - for(yy = yi-1; yy <= yi+1; yy++) { - for(zz = zi-1; zz <= zi+1; zz++) { + for (xx = xi - 1; xx <= xi + 1; xx++) { + for (yy = yi - 1; yy <= yi + 1; yy++) { + for (zz = zi - 1; zz <= zi + 1; zz++) { point ip = point(xx, yy, zz); point vp = (point)cellnoise_color(ip); point pd = p - (vp + ip); @@ -73,7 +73,7 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4]) vp += point(xx, yy, zz); - if(d < da[0]) { + if (d < da[0]) { da[3] = da[2]; da[2] = da[1]; da[1] = da[0]; @@ -84,7 +84,7 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4]) pa[1] = pa[0]; pa[0] = vp; } - else if(d < da[1]) { + else if (d < da[1]) { da[3] = da[2]; da[2] = da[1]; da[1] = d; @@ -93,14 +93,14 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4]) pa[2] = pa[1]; pa[1] = vp; } - else if(d < da[2]) { + else if (d < da[2]) { da[3] = da[2]; da[2] = d; pa[3] = pa[2]; pa[2] = vp; } - else if(d < da[3]) { + else if (d < da[3]) { da[3] = d; pa[3] = vp; } @@ -138,16 +138,16 @@ float voronoi_F1F2(point p) { return voronoi_FnFn(p, 0, 1); } float voronoi_Cr(point p) { /* crackle type pattern, just a scale/clamp of F2-F1 */ - float t = 10.0*voronoi_F1F2(p); - return (t > 1.0)? 1.0: t; + float t = 10.0 * voronoi_F1F2(p); + return (t > 1.0) ? 1.0 : t; } -float voronoi_F1S(point p) { return 2.0*voronoi_F1(p) - 1.0; } -float voronoi_F2S(point p) { return 2.0*voronoi_F2(p) - 1.0; } -float voronoi_F3S(point p) { return 2.0*voronoi_F3(p) - 1.0; } -float voronoi_F4S(point p) { return 2.0*voronoi_F4(p) - 1.0; } -float voronoi_F1F2S(point p) { return 2.0*voronoi_F1F2(p) - 1.0; } -float voronoi_CrS(point p) { return 2.0*voronoi_Cr(p) - 1.0; } +float voronoi_F1S(point p) { return 2.0 * voronoi_F1(p) - 1.0; } +float voronoi_F2S(point p) { return 2.0 * voronoi_F2(p) - 1.0; } +float voronoi_F3S(point p) { return 2.0 * voronoi_F3(p) - 1.0; } +float voronoi_F4S(point p) { return 2.0 * voronoi_F4(p) - 1.0; } +float voronoi_F1F2S(point p) { return 2.0 * voronoi_F1F2(p) - 1.0; } +float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; } /* Noise Bases */ @@ -155,21 +155,21 @@ float noise_basis(point p, string basis) { float result = 0.0; - if(basis == "Perlin") + if (basis == "Perlin") result = noise(p); - if(basis == "Voronoi F1") + if (basis == "Voronoi F1") result = voronoi_F1S(p); - if(basis == "Voronoi F2") + if (basis == "Voronoi F2") result = voronoi_F2S(p); - if(basis == "Voronoi F3") + if (basis == "Voronoi F3") result = voronoi_F3S(p); - if(basis == "Voronoi F4") + if (basis == "Voronoi F4") result = voronoi_F4S(p); - if(basis == "Voronoi F2-F1") + if (basis == "Voronoi F2-F1") result = voronoi_F1F2S(p); - if(basis == "Voronoi Crackle") + if (basis == "Voronoi Crackle") result = voronoi_CrS(p); - if(basis == "Cell Noise") + if (basis == "Cell Noise") result = cellnoise(p); return result; @@ -180,7 +180,7 @@ float noise_basis(point p, string basis) float noise_basis_hard(point p, string basis, int hard) { float t = noise_basis(p, basis); - return (hard)? fabs(2.0*t - 1.0): t; + return (hard) ? fabs(2.0 * t - 1.0) : t; } /* Waves */ @@ -189,22 +189,22 @@ float noise_wave(string wave, float a) { float result = 0.0; - if(wave == "Sine") { - result = 0.5 + 0.5*sin(a); + if (wave == "Sine") { + result = 0.5 + 0.5 * sin(a); } - else if(wave == "Saw") { - float b = 2*M_PI; + else if (wave == "Saw") { + float b = 2 * M_PI; int n = (int)(a / b); - a -= n*b; - if(a < 0) a += b; + a -= n * b; + if (a < 0) a += b; result = a / b; } - else if(wave == "Tri") { - float b = 2*M_PI; + else if (wave == "Tri") { + float b = 2 * M_PI; float rmax = 1.0; - result = rmax - 2.0*fabs(floor((a*(1.0/b))+0.5) - (a*(1.0/b))); + result = rmax - 2.0 * fabs(floor((a * (1.0 / b)) + 0.5) - (a * (1.0 / b))); } return result; @@ -219,18 +219,18 @@ float noise_turbulence(point p, string basis, int octaves, int hard) float sum = 0.0; int i; - for(i = 0; i <= octaves; i++) { - float t = noise_basis(fscale*p, basis); + for (i = 0; i <= octaves; i++) { + float t = noise_basis(fscale * p, basis); - if(hard) - t = fabs(2.0*t - 1.0); + if (hard) + t = fabs(2.0 * t - 1.0); - sum += t*amp; + sum += t * amp; amp *= 0.5; fscale *= 2.0; } - sum *= ((float)(1 << octaves)/(float)((1 << (octaves+1)) - 1)); + sum *= ((float)(1 << octaves) / (float)((1 << (octaves + 1)) - 1)); return sum; } @@ -241,8 +241,8 @@ float nonzero(float f, float eps) { float r; - if(abs(f) < eps) - r = sign(f)*eps; + if (abs(f) < eps) + r = sign(f) * eps; else r = f; diff --git a/intern/cycles/kernel/osl/nodes/stdosl.h b/intern/cycles/kernel/osl/nodes/stdosl.h index e4a110e737c..0c07c501d69 100644 --- a/intern/cycles/kernel/osl/nodes/stdosl.h +++ b/intern/cycles/kernel/osl/nodes/stdosl.h @@ -163,241 +163,246 @@ vector normalize (vector v) BUILTIN; vector faceforward (vector N, vector I, vector Nref) BUILTIN; vector faceforward (vector N, vector I) BUILTIN; vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; } -vector refract (vector I, vector N, float eta) { - float IdotN = dot (I, N); - float k = 1 - eta*eta * (1 - IdotN*IdotN); - return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k))); +vector refract(vector I, vector N, float eta) { + float IdotN = dot(I, N); + float k = 1 - eta * eta * (1 - IdotN * IdotN); + return (k < 0) ? vector(0, 0, 0) : (eta * I - N * (eta * IdotN + sqrt(k))); } -void fresnel (vector I, normal N, float eta, - output float Kr, output float Kt, - output vector R, output vector T) +void fresnel(vector I, normal N, float eta, + output float Kr, output float Kt, + output vector R, output vector T) { - float sqr(float x) { return x*x; } - float c = dot(I, N); - if (c < 0) - c = -c; - R = reflect(I, N); - float g = 1.0 / sqr(eta) - 1.0 + c * c; - if (g >= 0.0) { - g = sqrt (g); - float beta = g - c; - float F = (c * (g+c) - 1.0) / (c * beta + 1.0); - F = 0.5 * (1.0 + sqr(F)); - F *= sqr (beta / (g+c)); - Kr = F; - Kt = (1.0 - Kr) * eta*eta; - // OPT: the following recomputes some of the above values, but it - // gives us the same result as if the shader-writer called refract() - T = refract(I, N, eta); - } else { - // total internal reflection - Kr = 1.0; - Kt = 0.0; - T = vector (0,0,0); - } + float sqr(float x) { + return x * x; + } + float c = dot(I, N); + if (c < 0) + c = -c; + R = reflect(I, N); + float g = 1.0 / sqr(eta) - 1.0 + c * c; + if (g >= 0.0) { + g = sqrt(g); + float beta = g - c; + float F = (c * (g + c) - 1.0) / (c * beta + 1.0); + F = 0.5 * (1.0 + sqr(F)); + F *= sqr(beta / (g + c)); + Kr = F; + Kt = (1.0 - Kr) * eta * eta; + // OPT: the following recomputes some of the above values, but it + // gives us the same result as if the shader-writer called refract() + T = refract(I, N, eta); + } + else { + // total internal reflection + Kr = 1.0; + Kt = 0.0; + T = vector(0, 0, 0); + } #undef sqr } -void fresnel (vector I, normal N, float eta, - output float Kr, output float Kt) +void fresnel(vector I, normal N, float eta, + output float Kr, output float Kt) { - vector R, T; - fresnel(I, N, eta, Kr, Kt, R, T); + vector R, T; + fresnel(I, N, eta, Kr, Kt, R, T); } -point rotate (point q, float angle, point a, point b) BUILTIN; +point rotate(point q, float angle, point a, point b) BUILTIN; -normal transform (matrix Mto, normal p) BUILTIN; -vector transform (matrix Mto, vector p) BUILTIN; -point transform (matrix Mto, point p) BUILTIN; +normal transform(matrix Mto, normal p) BUILTIN; +vector transform(matrix Mto, vector p) BUILTIN; +point transform(matrix Mto, point p) BUILTIN; // Implementation of transform-with-named-space in terms of matrices: -point transform (string tospace, point x) +point transform(string tospace, point x) { - return transform (matrix ("common", tospace), x); + return transform(matrix("common", tospace), x); } -point transform (string fromspace, string tospace, point x) +point transform(string fromspace, string tospace, point x) { - return transform (matrix (fromspace, tospace), x); + return transform(matrix(fromspace, tospace), x); } -vector transform (string tospace, vector x) +vector transform(string tospace, vector x) { - return transform (matrix ("common", tospace), x); + return transform(matrix("common", tospace), x); } -vector transform (string fromspace, string tospace, vector x) +vector transform(string fromspace, string tospace, vector x) { - return transform (matrix (fromspace, tospace), x); + return transform(matrix(fromspace, tospace), x); } -normal transform (string tospace, normal x) +normal transform(string tospace, normal x) { - return transform (matrix ("common", tospace), x); + return transform(matrix("common", tospace), x); } -normal transform (string fromspace, string tospace, normal x) +normal transform(string fromspace, string tospace, normal x) { - return transform (matrix (fromspace, tospace), x); + return transform(matrix(fromspace, tospace), x); } -float transformu (string tounits, float x) BUILTIN; -float transformu (string fromunits, string tounits, float x) BUILTIN; +float transformu(string tounits, float x) BUILTIN; +float transformu(string fromunits, string tounits, float x) BUILTIN; // Color functions -float luminance (color c) { - return dot ((vector)c, vector(0.2126, 0.7152, 0.0722)); +float luminance(color c) { + return dot((vector)c, vector(0.2126, 0.7152, 0.0722)); } -color transformc (string to, color x) +color transformc(string to, color x) { - color rgb_to_hsv (color rgb) { // See Foley & van Dam - float r = rgb[0], g = rgb[1], b = rgb[2]; - float mincomp = min (r, min (g, b)); - float maxcomp = max (r, max (g, b)); - float delta = maxcomp - mincomp; // chroma - float h, s, v; - v = maxcomp; - if (maxcomp > 0) - s = delta / maxcomp; - else s = 0; - if (s <= 0) - h = 0; - else { - if (r >= maxcomp) h = (g-b) / delta; - else if (g >= maxcomp) h = 2 + (b-r) / delta; - else h = 4 + (r-g) / delta; - h /= 6; - if (h < 0) - h += 1; - } - return color (h, s, v); - } - - color rgb_to_hsl (color rgb) { // See Foley & van Dam - // First convert rgb to hsv, then to hsl - float minval = min (rgb[0], min (rgb[1], rgb[2])); - color hsv = rgb_to_hsv (rgb); - float maxval = hsv[2]; // v == maxval - float h = hsv[0], s, l = (minval+maxval) / 2; - if (minval == maxval) - s = 0; // special 'achromatic' case, hue is 0 - else if (l <= 0.5) - s = (maxval - minval) / (maxval + minval); - else - s = (maxval - minval) / (2 - maxval - minval); - return color (h, s, l); - } - - color r; - if (to == "rgb" || to == "RGB") - r = x; - else if (to == "hsv") - r = rgb_to_hsv (x); - else if (to == "hsl") - r = rgb_to_hsl (x); - else if (to == "YIQ") - r = color (dot (vector(0.299, 0.587, 0.114), (vector)x), - dot (vector(0.596, -0.275, -0.321), (vector)x), - dot (vector(0.212, -0.523, 0.311), (vector)x)); - else if (to == "xyz") - r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x), - dot (vector(0.212671, 0.715160, 0.072169), (vector)x), - dot (vector(0.019334, 0.119193, 0.950227), (vector)x)); - else { - error ("Unknown color space \"%s\"", to); - r = x; - } - return r; + color rgb_to_hsv(color rgb) { // See Foley & van Dam + float r = rgb[0], g = rgb[1], b = rgb[2]; + float mincomp = min(r, min(g, b)); + float maxcomp = max(r, max(g, b)); + float delta = maxcomp - mincomp; // chroma + float h, s, v; + v = maxcomp; + if (maxcomp > 0) + s = delta / maxcomp; + else s = 0; + if (s <= 0) + h = 0; + else { + if (r >= maxcomp) h = (g - b) / delta; + else if (g >= maxcomp) h = 2 + (b - r) / delta; + else h = 4 + (r - g) / delta; + h /= 6; + if (h < 0) + h += 1; + } + return color(h, s, v); + } + + color rgb_to_hsl(color rgb) { // See Foley & van Dam + // First convert rgb to hsv, then to hsl + float minval = min(rgb[0], min(rgb[1], rgb[2])); + color hsv = rgb_to_hsv(rgb); + float maxval = hsv[2]; // v == maxval + float h = hsv[0], s, l = (minval + maxval) / 2; + if (minval == maxval) + s = 0; // special 'achromatic' case, hue is 0 + else if (l <= 0.5) + s = (maxval - minval) / (maxval + minval); + else + s = (maxval - minval) / (2 - maxval - minval); + return color(h, s, l); + } + + color r; + if (to == "rgb" || to == "RGB") + r = x; + else if (to == "hsv") + r = rgb_to_hsv(x); + else if (to == "hsl") + r = rgb_to_hsl(x); + else if (to == "YIQ") + r = color(dot(vector(0.299, 0.587, 0.114), (vector)x), + dot(vector(0.596, -0.275, -0.321), (vector)x), + dot(vector(0.212, -0.523, 0.311), (vector)x)); + else if (to == "xyz") + r = color(dot(vector(0.412453, 0.357580, 0.180423), (vector)x), + dot(vector(0.212671, 0.715160, 0.072169), (vector)x), + dot(vector(0.019334, 0.119193, 0.950227), (vector)x)); + else { + error("Unknown color space \"%s\"", to); + r = x; + } + return r; } -color transformc (string from, string to, color x) +color transformc(string from, string to, color x) { - color hsv_to_rgb (color c) { // Reference: Foley & van Dam - float h = c[0], s = c[1], v = c[2]; - color r; - if (s < 0.0001) { - r = v; - } else { - h = 6 * (h - floor(h)); // expand to [0..6) - int hi = (int)h; - float f = h - hi; - float p = v * (1-s); - float q = v * (1-s*f); - float t = v * (1-s*(1-f)); - if (hi == 0) r = color (v, t, p); - else if (hi == 1) r = color (q, v, p); - else if (hi == 2) r = color (p, v, t); - else if (hi == 3) r = color (p, q, v); - else if (hi == 4) r = color (t, p, v); - else r = color (v, p, q); - } - return r; - } - - color hsl_to_rgb (color c) { - float h = c[0], s = c[1], l = c[2]; - // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam) - float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s); - color r; - if (v <= 0) { - r = 0; - } else { - float min = 2 * l - v; - s = (v - min) / v; - r = hsv_to_rgb (color (h, s, v)); - } - return r; - } - - color r; - if (from == "rgb" || from == "RGB") - r = x; - else if (from == "hsv") - r = hsv_to_rgb (x); - else if (from == "hsl") - r = hsl_to_rgb (x); - else if (from == "YIQ") - r = color (dot (vector(1, 0.9557, 0.6199), (vector)x), - dot (vector(1, -0.2716, -0.6469), (vector)x), - dot (vector(1, -1.1082, 1.7051), (vector)x)); - else if (from == "xyz") - r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x), - dot (vector(-0.969256, 1.875991, 0.041556), (vector)x), - dot (vector( 0.055648, -0.204043, 1.057311), (vector)x)); - else { - error ("Unknown color space \"%s\"", to); - r = x; - } - return transformc (to, r); + color hsv_to_rgb(color c) { // Reference: Foley & van Dam + float h = c[0], s = c[1], v = c[2]; + color r; + if (s < 0.0001) { + r = v; + } + else { + h = 6 * (h - floor(h)); // expand to [0..6) + int hi = (int)h; + float f = h - hi; + float p = v * (1 - s); + float q = v * (1 - s * f); + float t = v * (1 - s * (1 - f)); + if (hi == 0) r = color(v, t, p); + else if (hi == 1) r = color(q, v, p); + else if (hi == 2) r = color(p, v, t); + else if (hi == 3) r = color(p, q, v); + else if (hi == 4) r = color(t, p, v); + else r = color(v, p, q); + } + return r; + } + + color hsl_to_rgb(color c) { + float h = c[0], s = c[1], l = c[2]; + // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam) + float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s); + color r; + if (v <= 0) { + r = 0; + } + else { + float min = 2 * l - v; + s = (v - min) / v; + r = hsv_to_rgb(color(h, s, v)); + } + return r; + } + + color r; + if (from == "rgb" || from == "RGB") + r = x; + else if (from == "hsv") + r = hsv_to_rgb(x); + else if (from == "hsl") + r = hsl_to_rgb(x); + else if (from == "YIQ") + r = color(dot(vector(1, 0.9557, 0.6199), (vector)x), + dot(vector(1, -0.2716, -0.6469), (vector)x), + dot(vector(1, -1.1082, 1.7051), (vector)x)); + else if (from == "xyz") + r = color(dot(vector(3.240479, -1.537150, -0.498535), (vector)x), + dot(vector(-0.969256, 1.875991, 0.041556), (vector)x), + dot(vector(0.055648, -0.204043, 1.057311), (vector)x)); + else { + error("Unknown color space \"%s\"", to); + r = x; + } + return transformc(to, r); } // Matrix functions -float determinant (matrix m) BUILTIN; -matrix transpose (matrix m) BUILTIN; +float determinant(matrix m) BUILTIN; +matrix transpose(matrix m) BUILTIN; // Pattern generation -float step (float edge, float x) BUILTIN; -color step (color edge, color x) BUILTIN; -point step (point edge, point x) BUILTIN; -vector step (vector edge, vector x) BUILTIN; -normal step (normal edge, normal x) BUILTIN; -float smoothstep (float edge0, float edge1, float x) BUILTIN; +float step(float edge, float x) BUILTIN; +color step(color edge, color x) BUILTIN; +point step(point edge, point x) BUILTIN; +vector step(vector edge, vector x) BUILTIN; +normal step(normal edge, normal x) BUILTIN; +float smoothstep(float edge0, float edge1, float x) BUILTIN; // Derivatives and area operators @@ -408,24 +413,26 @@ float smoothstep (float edge0, float edge1, float x) BUILTIN; // String functions -int strlen (string s) BUILTIN; -int startswith (string s, string prefix) BUILTIN; -int endswith (string s, string suffix) BUILTIN; -string substr (string s, int start, int len) BUILTIN; -string substr (string s, int start) { return substr (s, start, strlen(s)); } +int strlen(string s) BUILTIN; +int startswith(string s, string prefix) BUILTIN; +int endswith(string s, string suffix) BUILTIN; +string substr(string s, int start, int len) BUILTIN; +string substr(string s, int start) { + return substr(s, start, strlen(s)); +} // Define concat in terms of shorter concat -string concat (string a, string b, string c) { - return concat(concat(a,b), c); +string concat(string a, string b, string c) { + return concat(concat(a, b), c); } -string concat (string a, string b, string c, string d) { - return concat(concat(a,b,c), d); +string concat(string a, string b, string c, string d) { + return concat(concat(a, b, c), d); } -string concat (string a, string b, string c, string d, string e) { - return concat(concat(a,b,c,d), e); +string concat(string a, string b, string c, string d, string e) { + return concat(concat(a, b, c, d), e); } -string concat (string a, string b, string c, string d, string e, string f) { - return concat(concat(a,b,c,d,e), f); +string concat(string a, string b, string c, string d, string e, string f) { + return concat(concat(a, b, c, d, e), f); } @@ -438,7 +445,7 @@ closure color diffuse(normal N) BUILTIN; closure color oren_nayar(normal N, float sigma) BUILTIN; closure color translucent(normal N) BUILTIN; closure color reflection(normal N, float eta) BUILTIN; -closure color reflection(normal N) { return reflection (N, 0.0); } +closure color reflection(normal N) { return reflection(N, 0.0); } closure color refraction(normal N, float eta) BUILTIN; closure color dielectric(normal N, float eta) BUILTIN; closure color transparent() BUILTIN; @@ -446,7 +453,7 @@ closure color microfacet_ggx(normal N, float ag) BUILTIN; closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN; closure color microfacet_beckmann(normal N, float ab) BUILTIN; closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN; -closure color ward(normal N, vector T,float ax, float ay) BUILTIN; +closure color ward(normal N, vector T, float ax, float ay) BUILTIN; closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color westin_backscatter(normal N, float roughness) BUILTIN; closure color westin_sheen(normal N, float edginess) BUILTIN; @@ -460,7 +467,7 @@ closure color holdout() BUILTIN; closure color subsurface(float eta, float g, float mfp, float albedo) BUILTIN; // Renderer state -int raytype (string typename) BUILTIN; +int raytype(string typename) BUILTIN; #undef BUILTIN #undef BUILTIN_DERIV diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 1b52a3e489b..ca9e47c9f77 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -37,7 +37,7 @@ CCL_NAMESPACE_BEGIN /* RenderServices implementation */ -#define TO_MATRIX44(m) (*(OSL::Matrix44*)&(m)) +#define TO_MATRIX44(m) (*(OSL::Matrix44 *)&(m)) /* static ustrings */ ustring OSLRenderServices::u_distance("distance"); @@ -66,12 +66,12 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr { /* this is only used for shader and object space, we don't really have a concept of shader space, so we just use object space for both. */ - if(xform) { + if (xform) { KernelGlobals *kg = kernel_globals; - const ShaderData *sd = (const ShaderData*)xform; + const ShaderData *sd = (const ShaderData *)xform; int object = sd->object; - if(object != ~0) { + if (object != ~0) { Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); tfm = transform_transpose(tfm); result = TO_MATRIX44(tfm); @@ -87,12 +87,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform { /* this is only used for shader and object space, we don't really have a concept of shader space, so we just use object space for both. */ - if(xform) { + if (xform) { KernelGlobals *kg = kernel_globals; - const ShaderData *sd = (const ShaderData*)xform; + const ShaderData *sd = (const ShaderData *)xform; int object = sd->object; - if(object != ~0) { + if (object != ~0) { Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); tfm = transform_transpose(tfm); result = TO_MATRIX44(tfm); @@ -108,22 +108,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti { KernelGlobals *kg = kernel_globals; - if(from == u_ndc) { + if (from == u_ndc) { Transform tfm = transform_transpose(kernel_data.cam.ndctoworld); result = TO_MATRIX44(tfm); return true; } - else if(from == u_raster) { + else if (from == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); result = TO_MATRIX44(tfm); return true; } - else if(from == u_screen) { + else if (from == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.screentoworld); result = TO_MATRIX44(tfm); return true; } - else if(from == u_camera) { + else if (from == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); result = TO_MATRIX44(tfm); return true; @@ -136,22 +136,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl { KernelGlobals *kg = kernel_globals; - if(to == u_ndc) { + if (to == u_ndc) { Transform tfm = transform_transpose(kernel_data.cam.worldtondc); result = TO_MATRIX44(tfm); return true; } - else if(to == u_raster) { + else if (to == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); result = TO_MATRIX44(tfm); return true; } - else if(to == u_screen) { + else if (to == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); result = TO_MATRIX44(tfm); return true; } - else if(to == u_camera) { + else if (to == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); result = TO_MATRIX44(tfm); return true; @@ -161,56 +161,57 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl } bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, - ustring object, TypeDesc type, ustring name, - int index, void *val) + ustring object, TypeDesc type, ustring name, + int index, void *val) { return false; } static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, - const OSLGlobals::Attribute& attr, bool derivatives, void *val) + const OSLGlobals::Attribute& attr, bool derivatives, void *val) { - if(attr.type == TypeDesc::TypeFloat) { - float *fval = (float*)val; + if (attr.type == TypeDesc::TypeFloat) { + float *fval = (float *)val; fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, - (derivatives)? &fval[1]: NULL, (derivatives)? &fval[2]: NULL); + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); } else { /* todo: this won't work when float3 has w component */ - float3 *fval = (float3*)val; + float3 *fval = (float3 *)val; fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, - (derivatives)? &fval[1]: NULL, (derivatives)? &fval[2]: NULL); + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); } return true; } static bool get_mesh_attribute_convert(KernelGlobals *kg, const ShaderData *sd, - const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) + const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) { - if(attr.type == TypeDesc::TypeFloat) { + if (attr.type == TypeDesc::TypeFloat) { float tmp[3]; - float3 *fval = (float3*)val; + float3 *fval = (float3 *)val; get_mesh_attribute(kg, sd, attr, derivatives, tmp); fval[0] = make_float3(tmp[0], tmp[0], tmp[0]); - if(derivatives) { + if (derivatives) { fval[1] = make_float3(tmp[1], tmp[1], tmp[1]); fval[2] = make_float3(tmp[2], tmp[2], tmp[2]); } return true; } - else if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { + else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) + { float3 tmp[3]; - float *fval = (float*)val; + float *fval = (float *)val; get_mesh_attribute(kg, sd, attr, derivatives, tmp); fval[0] = average(tmp[0]); - if(derivatives) { + if (derivatives) { fval[1] = average(tmp[1]); fval[2] = average(tmp[2]); } @@ -226,29 +227,29 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat size_t datasize = attr.value.datasize(); memcpy(val, attr.value.data(), datasize); - if(derivatives) - memset((char*)val + datasize, 0, datasize*2); + if (derivatives) + memset((char *)val + datasize, 0, datasize * 2); } bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name, - TypeDesc type, ustring name, void *val) + TypeDesc type, ustring name, void *val) { KernelGlobals *kg = kernel_globals; - const ShaderData *sd = (const ShaderData*)renderstate; + const ShaderData *sd = (const ShaderData *)renderstate; int object = sd->object; int tri = sd->prim; /* lookup of attribute on another object */ - if(object_name != u_empty) { + if (object_name != u_empty) { OSLGlobals::ObjectNameMap::iterator it = kg->osl.object_name_map.find(object_name); - if(it == kg->osl.object_name_map.end()) + if (it == kg->osl.object_name_map.end()) return false; object = it->second; tri = ~0; } - else if(object == ~0) { + else if (object == ~0) { /* no background attributes supported */ return false; } @@ -257,20 +258,23 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object]; OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); - if(it == attribute_map.end()) + if (it == attribute_map.end()) return false; /* type mistmatch? */ const OSLGlobals::Attribute& attr = it->second; - if(attr.elem != ATTR_ELEMENT_VALUE) { + if (attr.elem != ATTR_ELEMENT_VALUE) { /* triangle and vertex attributes */ - if(tri != ~0) { - if(attr.type == type || (attr.type == TypeDesc::TypeColor && - (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal))) + if (tri != ~0) { + if (attr.type == type || (attr.type == TypeDesc::TypeColor && + (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal))) + { return get_mesh_attribute(kg, sd, attr, derivatives, val); - else + } + else { return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val); + } } } else { @@ -283,7 +287,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri } bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type, - void *renderstate, void *val) + void *renderstate, void *val) { return false; /* disabled by lockgeom */ } @@ -294,7 +298,7 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst } void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names, - TypeDesc *attr_types, int nattrs) + TypeDesc *attr_types, int nattrs) { #ifdef WITH_PARTIO m_attr_queries.push_back(AttrQuery()); @@ -308,28 +312,32 @@ void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names, to the query. Just to prevent buffer overruns */ query.capacity = -1; - for(int i = 0; i < nattrs; ++i) - { + for (int i = 0; i < nattrs; ++i) { query.attr_names[i] = attr_names[i]; - TypeDesc element_type = attr_types[i].elementtype (); + TypeDesc element_type = attr_types[i].elementtype(); - if(query.capacity < 0) - query.capacity = attr_types[i].numelements(); + if (query.capacity < 0) + query.capacity = attr_types[i].numelements(); else - query.capacity = min(query.capacity, (int)attr_types[i].numelements()); + query.capacity = min(query.capacity, (int)attr_types[i].numelements()); /* convert the OSL (OIIO) type to the equivalent Partio type so we can do a fast check at query time. */ - if(element_type == TypeDesc::TypeFloat) - query.attr_partio_types[i] = Partio::FLOAT; - else if(element_type == TypeDesc::TypeInt) - query.attr_partio_types[i] = Partio::INT; - else if(element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint || - element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal) - query.attr_partio_types[i] = Partio::VECTOR; - else - return NULL; /* report some error of unknown type */ + if (element_type == TypeDesc::TypeFloat) { + query.attr_partio_types[i] = Partio::FLOAT; + } + else if (element_type == TypeDesc::TypeInt) { + query.attr_partio_types[i] = Partio::INT; + } + else if (element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint || + element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal) + { + query.attr_partio_types[i] = Partio::VECTOR; + } + else { + return NULL; /* report some error of unknown type */ + } } /* this is valid until the end of RenderServices */ @@ -348,18 +356,18 @@ Partio::ParticlesData *OSLRenderServices::get_pointcloud(ustring filename) #endif int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius, - int max_points, void *_attr_query, void **attr_outdata) + int max_points, void *_attr_query, void **attr_outdata) { /* todo: this code has never been tested, and most likely does not work. it's based on the example code in OSL */ #ifdef WITH_PARTIO /* query Partio for this pointcloud lookup using cached attr_query */ - if(!_attr_query) + if (!_attr_query) return 0; AttrQuery *attr_query = (AttrQuery *)_attr_query; - if(attr_query->capacity < max_points) + if (attr_query->capacity < max_points) return 0; /* get the pointcloud entry for the given filename */ @@ -370,13 +378,13 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo int nattrs = attr_query->attr_names.size(); Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs); - for(int i = 0; i < nattrs; ++i) { + for (int i = 0; i < nattrs; ++i) { /* special case attributes */ - if(attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index) + if (attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index) continue; /* lookup the attribute by name*/ - if(!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) { + if (!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) { /* issue an error here and return, types don't match */ Partio::endCachedAccess(cloud); cloud->release(); @@ -394,14 +402,14 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo int count = indices.size(); /* retrieve the attributes directly to user space */ - for(int j = 0; j < nattrs; ++j) { + for (int j = 0; j < nattrs; ++j) { /* special cases */ - if(attr_query->attr_names[j] == u_distance) { - for(int i = 0; i < count; ++i) + if (attr_query->attr_names[j] == u_distance) { + for (int i = 0; i < count; ++i) ((float *)attr_outdata[j])[i] = sqrtf(dist2[i]); } - else if(attr_query->attr_names[j] == u_index) { - for(int i = 0; i < count; ++i) + else if (attr_query->attr_names[j] == u_index) { + for (int i = 0; i < count; ++i) ((int *)attr_outdata[j])[i] = indices[i]; } else { diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 85a01e54e5c..88735c073c2 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -57,19 +57,19 @@ public: bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time); bool get_array_attribute(void *renderstate, bool derivatives, - ustring object, TypeDesc type, ustring name, - int index, void *val); + ustring object, TypeDesc type, ustring name, + int index, void *val); bool get_attribute(void *renderstate, bool derivatives, ustring object, - TypeDesc type, ustring name, void *val); + TypeDesc type, ustring name, void *val); bool get_userdata(bool derivatives, ustring name, TypeDesc type, - void *renderstate, void *val); + void *renderstate, void *val); bool has_userdata(ustring name, TypeDesc type, void *renderstate); void *get_pointcloud_attr_query(ustring *attr_names, - TypeDesc *attr_types, int nattrs); + TypeDesc *attr_types, int nattrs); int pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius, - int max_points, void *attr_query, void **attr_outdata); + int max_points, void *attr_query, void **attr_outdata); private: KernelGlobals *kernel_globals; @@ -79,8 +79,7 @@ private: right now it only caches the types already converted to Partio constants. this is what get_pointcloud_attr_query returns */ - struct AttrQuery - { + struct AttrQuery { /* names of the attributes to query */ std::vector attr_names; /* types as (enum Partio::ParticleAttributeType) of the diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 18a8e974492..fc28833bb8c 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -37,7 +37,7 @@ tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); void OSLShader::thread_init(KernelGlobals *kg) { - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData(); @@ -46,12 +46,12 @@ void OSLShader::thread_init(KernelGlobals *kg) tls_set(kg->osl.thread_data, tdata); - ((OSLRenderServices*)ssi->renderer())->thread_init(kg); + ((OSLRenderServices *)ssi->renderer())->thread_init(kg); } void OSLShader::thread_free(KernelGlobals *kg) { - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); @@ -62,12 +62,12 @@ void OSLShader::thread_free(KernelGlobals *kg) /* Globals */ -#define TO_VEC3(v) (*(OSL::Vec3*)&(v)) -#define TO_COLOR3(v) (*(OSL::Color3*)&(v)) +#define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) +#define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, - int path_flag, OSL::ShaderGlobals *globals) + int path_flag, OSL::ShaderGlobals *globals) { /* copy from shader data to shader globals */ globals->P = TO_VEC3(sd->P); @@ -86,7 +86,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, globals->dvdy = sd->dv.dy; globals->dPdu = TO_VEC3(sd->dPdu); globals->dPdv = TO_VEC3(sd->dPdv); - globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object); + globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object); /* booleans */ globals->raytype = path_flag; /* todo: add our own ray types */ @@ -109,35 +109,35 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, /* Surface */ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, - const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) + const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives use a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ - if(closure->type == OSL::ClosureColor::COMPONENT) { - OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; - OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); + if (closure->type == OSL::ClosureColor::COMPONENT) { + OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; + OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); - if(prim) { + if (prim) { ShaderClosure sc; sc.prim = prim; sc.weight = weight; - switch(prim->category()) { + switch (prim->category()) { case ClosurePrimitive::BSDF: { - if(sd->num_closure == MAX_CLOSURE) + if (sd->num_closure == MAX_CLOSURE) return; - OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim; + OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim; ustring scattering = bsdf->scattering(); /* no caustics option */ - if(no_glossy && scattering == OSL::Labels::GLOSSY) + if (no_glossy && scattering == OSL::Labels::GLOSSY) return; /* sample weight */ float albedo = bsdf->albedo(TO_VEC3(sd->I)); - float sample_weight = fabsf(average(weight))*albedo; + float sample_weight = fabsf(average(weight)) * albedo; float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight; sc.sample_weight = sample_weight; @@ -145,10 +145,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sd->osl_closure.bsdf_sample_sum = sample_sum; /* scattering flags */ - if(scattering == OSL::Labels::DIFFUSE) - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; - else if(scattering == OSL::Labels::GLOSSY) - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + if (scattering == OSL::Labels::DIFFUSE) + sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL; + else if (scattering == OSL::Labels::GLOSSY) + sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; else sd->flag |= SD_BSDF; @@ -157,7 +157,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, break; } case ClosurePrimitive::Emissive: { - if(sd->num_closure == MAX_CLOSURE) + if (sd->num_closure == MAX_CLOSURE) return; /* sample weight */ @@ -175,7 +175,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, break; } case ClosurePrimitive::Holdout: - if(sd->num_closure == MAX_CLOSURE) + if (sd->num_closure == MAX_CLOSURE) return; sc.sample_weight = 0.0f; @@ -192,12 +192,12 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, } } } - else if(closure->type == OSL::ClosureColor::MUL) { - OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; + else if (closure->type == OSL::ClosureColor::MUL) { + OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight); } - else if(closure->type == OSL::ClosureColor::ADD) { - OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; + else if (closure->type == OSL::ClosureColor::ADD) { + OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight); flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight); } @@ -206,7 +206,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); @@ -218,14 +218,14 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int /* execute shader for this point */ int shader = sd->shader & SHADER_MASK; - if(kg->osl.surface_state[shader]) + if (kg->osl.surface_state[shader]) ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals); /* flatten closure tree */ sd->num_closure = 0; sd->randb_closure = randb; - if(globals->Ci) { + if (globals->Ci) { bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics; flatten_surface_closure_tree(sd, no_glossy, globals->Ci); } @@ -239,23 +239,23 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) * is only one supported closure type at the moment, which has no evaluation * functions, so we just sum the weights */ - if(closure->type == OSL::ClosureColor::COMPONENT) { - OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; - OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); + if (closure->type == OSL::ClosureColor::COMPONENT) { + OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; + OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); - if(prim && prim->category() == OSL::ClosurePrimitive::Background) + if (prim && prim->category() == OSL::ClosurePrimitive::Background) return make_float3(1.0f, 1.0f, 1.0f); } - else if(closure->type == OSL::ClosureColor::MUL) { - OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; + else if (closure->type == OSL::ClosureColor::MUL) { + OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure); } - else if(closure->type == OSL::ClosureColor::ADD) { - OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; + else if (closure->type == OSL::ClosureColor::ADD) { + OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; return flatten_background_closure_tree(add->closureA) + - flatten_background_closure_tree(add->closureB); + flatten_background_closure_tree(add->closureB); } return make_float3(0.0f, 0.0f, 0.0f); @@ -264,7 +264,7 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); @@ -274,11 +274,11 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ - if(kg->osl.background_state) + if (kg->osl.background_state) ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals); /* return background color immediately */ - if(globals->Ci) + if (globals->Ci) return flatten_background_closure_tree(globals->Ci); return make_float3(0.0f, 0.0f, 0.0f); @@ -287,23 +287,23 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl /* Volume */ static void flatten_volume_closure_tree(ShaderData *sd, - const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) + const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { /* OSL gives use a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ - if(closure->type == OSL::ClosureColor::COMPONENT) { - OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; - OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); + if (closure->type == OSL::ClosureColor::COMPONENT) { + OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; + OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data(); - if(prim) { + if (prim) { ShaderClosure sc; sc.prim = prim; sc.weight = weight; - switch(prim->category()) { + switch (prim->category()) { case ClosurePrimitive::Volume: { - if(sd->num_closure == MAX_CLOSURE) + if (sd->num_closure == MAX_CLOSURE) return; /* sample weight */ @@ -329,12 +329,12 @@ static void flatten_volume_closure_tree(ShaderData *sd, } } } - else if(closure->type == OSL::ClosureColor::MUL) { - OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; + else if (closure->type == OSL::ClosureColor::MUL) { + OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); } - else if(closure->type == OSL::ClosureColor::ADD) { - OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; + else if (closure->type == OSL::ClosureColor::ADD) { + OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; flatten_volume_closure_tree(sd, add->closureA, weight); flatten_volume_closure_tree(sd, add->closureB, weight); } @@ -343,7 +343,7 @@ static void flatten_volume_closure_tree(ShaderData *sd, void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); @@ -355,7 +355,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int /* execute shader */ int shader = sd->shader & SHADER_MASK; - if(kg->osl.volume_state[shader]) + if (kg->osl.volume_state[shader]) ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals); /* retrieve resulting closures */ @@ -363,7 +363,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int sd->osl_closure.num_volume = 0; sd->osl_closure.randb = randb; - if(globals->Ci) + if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); } @@ -372,7 +372,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); @@ -384,7 +384,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) /* execute shader */ int shader = sd->shader & SHADER_MASK; - if(kg->osl.displacement_state[shader]) + if (kg->osl.displacement_state[shader]) ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals); /* get back position */ @@ -393,17 +393,17 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) void OSLShader::release(KernelGlobals *kg, const ShaderData *sd) { - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; + OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); - ssi->release_context((OSL::pvt::ShadingContext*)sd->osl_ctx, tdata->thread_info); + ssi->release_context((OSL::pvt::ShadingContext *)sd->osl_ctx, tdata->thread_info); } /* BSDF Closure */ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf) { - OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure*)sc->prim; + OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure *)sc->prim; int label = LABEL_NONE; pdf = 0.0f; @@ -412,27 +412,27 @@ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float ustring ulabel; ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng), - TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), - randu, randv, - TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy), - pdf, TO_COLOR3(eval)); + TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), + randu, randv, + TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy), + pdf, TO_COLOR3(eval)); /* convert OSL label */ - if(ulabel == OSL::Labels::REFLECT) + if (ulabel == OSL::Labels::REFLECT) label = LABEL_REFLECT; - else if(ulabel == OSL::Labels::TRANSMIT) + else if (ulabel == OSL::Labels::TRANSMIT) label = LABEL_TRANSMIT; else - return LABEL_NONE; /* sampling failed */ + return LABEL_NONE; /* sampling failed */ /* convert scattering to our bitflag label */ ustring uscattering = sample_bsdf->scattering(); - if(uscattering == OSL::Labels::DIFFUSE) + if (uscattering == OSL::Labels::DIFFUSE) label |= LABEL_DIFFUSE; - else if(uscattering == OSL::Labels::GLOSSY) + else if (uscattering == OSL::Labels::GLOSSY) label |= LABEL_GLOSSY; - else if(uscattering == OSL::Labels::SINGULAR) + else if (uscattering == OSL::Labels::SINGULAR) label |= LABEL_SINGULAR; else label |= LABEL_TRANSPARENT; @@ -442,10 +442,10 @@ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf) { - OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim; + OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)sc->prim; OSL::Color3 bsdf_eval; - if(dot(sd->Ng, omega_in) >= 0.0f) + if (dot(sd->Ng, omega_in) >= 0.0f) bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); else bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); @@ -457,7 +457,7 @@ float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc) { - OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)sc->prim; + OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim; OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I)); eval += TO_FLOAT3(emissive_eval); @@ -468,9 +468,9 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc) float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { - OSL::VolumeClosure *volume = (OSL::VolumeClosure*)sc->prim; + OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim; OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out)); - return TO_FLOAT3(volume_eval)*sc->weight; + return TO_FLOAT3(volume_eval) * sc->weight; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index 6b1d402989b..815557ed203 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -68,15 +68,15 @@ public: /* sample & eval */ static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, - float randu, float randv, - float3& eval, float3& omega_in, differential3& domega_in, float& pdf); + float randu, float randv, + float3& eval, float3& omega_in, differential3& domega_in, float& pdf); static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, - const float3& omega_in, float& pdf); + const float3& omega_in, float& pdf); static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc); static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, - const float3 omega_in, const float3 omega_out); + const float3 omega_in, const float3 omega_out); /* release */ static void release(KernelGlobals *kg, const ShaderData *sd); diff --git a/intern/cycles/kernel/osl/vol_subsurface.cpp b/intern/cycles/kernel/osl/vol_subsurface.cpp index 0cd3060051b..818a057b6cc 100644 --- a/intern/cycles/kernel/osl/vol_subsurface.cpp +++ b/intern/cycles/kernel/osl/vol_subsurface.cpp @@ -46,88 +46,90 @@ using namespace OSL; class SubsurfaceClosure : public VolumeClosure { public: - float m_g; - float m_eta; - Color3 m_mfp, m_albedo; - static float root_find_Rd(const float Rd0, const float A) { - // quick exit for trivial cases - if (Rd0 <= 0) return 0; - const float A43 = A * 4.0f / 3.0f; - // Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection - // method can be used because this function is monotonicaly increasing. - float lo = 0, hi = 1; - for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient - // eval function at midpoint - float alpha = 0.5f * (lo + hi); - float a1 = sqrtf(3 * (1 - alpha)); - float e1 = expf(-a1); - float e2 = expf(-A43 * a1); - float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0; - if (fabsf(Rd) < 1e-6f) - return alpha; // close enough - else if (Rd > 0) - hi = alpha; // root is on left side - else - lo = alpha; // root is on right side - } - // didn't quite converge, pick result in the middle of remaining interval - return 0.5f * (lo + hi); - } - SubsurfaceClosure() { } - - void setup() - { - ior(m_eta); - - if (m_g >= 0.99f) m_g = 0.99f; - if (m_g <= -0.99f) m_g = -0.99f; - - // eq.10 - float inv_eta = 1 / m_eta; - float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta; - float A = (1 + Fdr) / (1 - Fdr); - // compute sigma_s, sigma_a (eq.16) - Color3 alpha_prime = Color3 (root_find_Rd(m_albedo[0], A), - root_find_Rd(m_albedo[1], A), - root_find_Rd(m_albedo[2], A)); - Color3 sigma_t_prime = Color3 (m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f, - m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f, - m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f); - Color3 sigma_s_prime = alpha_prime * sigma_t_prime; - - sigma_s((1.0f / (1 - m_g)) * sigma_s_prime); - sigma_a(sigma_t_prime - sigma_s_prime); - } - - bool mergeable (const ClosurePrimitive *other) const { - const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other; - return m_g == comp->m_g && VolumeClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "subsurface"; } - - void print_on (std::ostream &out) const { - out << name() << " ()"; - } - - virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const { - float costheta = omega_in.dot(omega_out); - float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f)); - return Color3 (ph, ph, ph); - } + float m_g; + float m_eta; + Color3 m_mfp, m_albedo; + static float root_find_Rd(const float Rd0, const float A) { + // quick exit for trivial cases + if (Rd0 <= 0) return 0; + const float A43 = A * 4.0f / 3.0f; + // Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection + // method can be used because this function is monotonicaly increasing. + float lo = 0, hi = 1; + for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient + // eval function at midpoint + float alpha = 0.5f * (lo + hi); + float a1 = sqrtf(3 * (1 - alpha)); + float e1 = expf(-a1); + float e2 = expf(-A43 * a1); + float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0; + if (fabsf(Rd) < 1e-6f) + return alpha; // close enough + else if (Rd > 0) + hi = alpha; // root is on left side + else + lo = alpha; // root is on right side + } + // didn't quite converge, pick result in the middle of remaining interval + return 0.5f * (lo + hi); + } + SubsurfaceClosure() { + } + + void setup() + { + ior(m_eta); + + if (m_g >= 0.99f) m_g = 0.99f; + if (m_g <= -0.99f) m_g = -0.99f; + + // eq.10 + float inv_eta = 1 / m_eta; + float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta; + float A = (1 + Fdr) / (1 - Fdr); + // compute sigma_s, sigma_a (eq.16) + Color3 alpha_prime = Color3(root_find_Rd(m_albedo[0], A), + root_find_Rd(m_albedo[1], A), + root_find_Rd(m_albedo[2], A)); + Color3 sigma_t_prime = Color3(m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f, + m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f, + m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f); + Color3 sigma_s_prime = alpha_prime * sigma_t_prime; + + sigma_s((1.0f / (1 - m_g)) * sigma_s_prime); + sigma_a(sigma_t_prime - sigma_s_prime); + } + + bool mergeable(const ClosurePrimitive *other) const { + const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other; + return m_g == comp->m_g && VolumeClosure::mergeable(other); + } + + size_t memsize() const { return sizeof(*this); } + + const char *name() const { return "subsurface"; } + + void print_on(std::ostream &out) const { + out << name() << " ()"; + } + + virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const { + float costheta = omega_in.dot(omega_out); + float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f)); + return Color3(ph, ph, ph); + } }; ClosureParam closure_subsurface_params[] = { - CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_eta), - CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_g), - CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_mfp), - CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_albedo), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(SubsurfaceClosure) }; + CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_eta), + CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_g), + CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_mfp), + CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_albedo), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(SubsurfaceClosure) +}; CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure) -- cgit v1.2.3 From 4260804c006d37ff44ce958719b52d2ecc4d38d7 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 4 Jun 2012 23:14:57 +0000 Subject: Fix NULL free warning in multires. --- source/blender/blenkernel/intern/multires.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index d818ca09f20..4cbfb4f0f3e 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1058,7 +1058,8 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm /* if needed, reallocate multires paint mask */ if (gpm && gpm->level < key.level) { gpm->level = key.level; - MEM_freeN(gpm->data); + if (gpm->data) + MEM_freeN(gpm->data); gpm->data = MEM_callocN(sizeof(float) * key.grid_area, "gpm.data"); } -- cgit v1.2.3 From d24a27ca3643e8f9b7bcc5123e56077df9afe005 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 4 Jun 2012 23:53:59 +0000 Subject: Fix remesh output changing when input is moved relative to origin. Fixes bug [#31626] Remesh modifier generates different results depending on object origin position Was incorrectly initializing bounding box min/max to zero, now uses INIT_MINMAX. --- source/blender/modifiers/intern/MOD_remesh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 57966b5824b..2b55471be3d 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -87,6 +87,7 @@ static void init_dualcon_mesh(DualConInput *mesh, DerivedMesh *dm) mesh->face_stride = sizeof(MFace); mesh->totface = dm->getNumTessFaces(dm); + INIT_MINMAX(mesh->min, mesh->max); dm->getMinMax(dm, mesh->min, mesh->max); } -- cgit v1.2.3 From 06556a92e5ba0b0d541792e1ac2b84eaf59998b8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 06:18:31 +0000 Subject: correction to own change with cmake, oiio linking. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3538c64f1e9..bd038415772 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -653,10 +653,10 @@ if(UNIX AND NOT APPLE) set(OPENIMAGEIO_DEFINITIONS) if(WITH_IMAGE_TIFF) - set(OPENIMAGEIO_LIBRARIES "${OPENIMAGEIO_LIBRARIES} ${TIFF_LIBRARY}") + list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}") endif() if(WITH_IMAGE_OPENEXR) - set(OPENIMAGEIO_LIBRARIES "${OPENIMAGEIO_LIBRARIES} ${OPENEXR_LIBRARIES}") + list(APPEND OPENIMAGEIO_LIBRARIES "${OPENEXR_LIBRARIES}") endif() if(NOT OPENIMAGEIO_FOUND) -- cgit v1.2.3 From a0f5e200cc9f83c4a276c0978e136d4d7c3193a9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 06:54:18 +0000 Subject: fix for possible uninitialized pointer use in mask rasterize and remove some dead code. --- source/blender/blenkernel/intern/mask.c | 86 ++++++++++++++++----------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 870a84df66a..9c2955e9118 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1972,15 +1972,6 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) /* temp blending buffer */ const int buffer_size = width * height; float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__); - float max_dseg_len = 0.0f; - - if (width >= height) { - max_dseg_len = (float)(width); - } - else { - max_dseg_len = (float)(height); - } - max_dseg_len = 1.0f / max_dseg_len; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; @@ -1999,51 +1990,56 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) float (*diff_feather_points)[2]; int tot_diff_feather_points; - diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point); + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, + &tot_diff_point); + if (tot_diff_point) { diff_feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, &tot_diff_feather_points); - } - /* TODO, make this optional! */ - if (width != height) { - float *fp; - float *ffp; - int i; - float asp; - - if (width < height) { - fp = &diff_points[0][0]; - ffp = &diff_feather_points[0][0]; - asp = (float)width / (float)height; - } - else { - fp = &diff_points[0][1]; - ffp = &diff_feather_points[0][1]; - asp = (float)height / (float)width; - } + /* TODO, make this optional! */ + if (width != height) { + float *fp; + float *ffp; + int i; + float asp; + + if (width < height) { + fp = &diff_points[0][0]; + ffp = tot_diff_feather_points ? &diff_feather_points[0][0] : NULL; + asp = (float)width / (float)height; + } + else { + fp = &diff_points[0][1]; + ffp = tot_diff_feather_points ? &diff_feather_points[0][1] : NULL; + asp = (float)height / (float)width; + } - for (i = 0; i < tot_diff_point; i++, fp += 2) { - (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; - } - for (i = 0; i < tot_diff_feather_points; i++, ffp += 2) { - (*ffp) = (((*ffp) - 0.5f) / asp) + 0.5f; - } - } + for (i = 0; i < tot_diff_point; i++, fp += 2) { + (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; + } - if (tot_diff_point) { - PLX_raskterize((float (*)[2])diff_points, tot_diff_point, - buffer_tmp, width, height); - - if (tot_diff_feather_points) { - PLX_raskterize_feather((float (*)[2])diff_points, tot_diff_point, - (float (*)[2])diff_feather_points, tot_diff_feather_points, - buffer_tmp, width, height); - MEM_freeN(diff_feather_points); + if (tot_diff_feather_points) { + for (i = 0; i < tot_diff_feather_points; i++, ffp += 2) { + (*ffp) = (((*ffp) - 0.5f) / asp) + 0.5f; + } + } } - MEM_freeN(diff_points); + if (tot_diff_point) { + PLX_raskterize(diff_points, tot_diff_point, + buffer_tmp, width, height); + + if (tot_diff_feather_points) { + PLX_raskterize_feather(diff_points, tot_diff_point, + diff_feather_points, tot_diff_feather_points, + buffer_tmp, width, height); + MEM_freeN(diff_feather_points); + } + + MEM_freeN(diff_points); + } } } -- cgit v1.2.3 From 0c59218a1d0f673d15dc61e68f018cc895e31fc9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 07:01:43 +0000 Subject: mask switch direction now swaps handle direction too --- source/blender/blenkernel/intern/mask.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 9c2955e9118..b904b78ffdd 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -383,16 +383,27 @@ void BKE_mask_point_direction_switch(MaskSplinePoint *point) const int tot_uw_half = tot_uw / 2; int i; - if (tot_uw < 2) { - return; + float co_tmp[2]; + + /* swap handles */ + copy_v2_v2(co_tmp, point->bezt.vec[0]); + copy_v2_v2(point->bezt.vec[0], point->bezt.vec[2]); + copy_v2_v2(point->bezt.vec[2], co_tmp); + /* in this case the flags are unlikely to be different but swap anyway */ + SWAP(char, point->bezt.f1, point->bezt.f3); + SWAP(char, point->bezt.h1, point->bezt.h2); + + + /* swap UW's */ + if (tot_uw > 1) { + /* count */ + for (i = 0; i < tot_uw_half; i++) { + MaskSplinePointUW *uw_a = &point->uw[i]; + MaskSplinePointUW *uw_b = &point->uw[tot_uw - (i + 1)]; + SWAP(MaskSplinePointUW, *uw_a, *uw_b); + } } - /* count */ - for (i = 0; i < tot_uw_half; i++) { - MaskSplinePointUW *uw_a = &point->uw[i]; - MaskSplinePointUW *uw_b = &point->uw[tot_uw - (i + 1)]; - SWAP(MaskSplinePointUW, *uw_a, *uw_b); - } for (i = 0; i < tot_uw; i++) { MaskSplinePointUW *uw = &point->uw[i]; uw->u = 1.0f - uw->u; -- cgit v1.2.3 From 67ba133b19c20b83d06c9c2dd5f2fb5bea5463b5 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Tue, 5 Jun 2012 08:06:15 +0000 Subject: Fix #31706, Crash loading old file in trunk build. --- source/blender/blenloader/intern/readfile.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 71e9bfa33e4..f9200f83997 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6724,6 +6724,11 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo char basepath[FILE_MAXDIR]; char filename[FILE_MAXFILE]; + /* ugly, need to remove the old inputs list to avoid bad pointer checks when adding new sockets. + * sock->storage is expected to contain path info in ntreeCompositOutputFileAddSocket. + */ + node->inputs.first = node->inputs.last = NULL; + node->storage = nimf; /* split off filename from the old path, to be used as socket sub-path */ -- cgit v1.2.3 From 0adf252c9b92dac4bc56e92c531464c59b71d91c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 5 Jun 2012 08:41:53 +0000 Subject: Fix #31593: Every time I switch between edit and object mode, it crashes Crash was caused by incorrect restoring OpenGL context due to some weird bit operations used to indicate whether stuff like color arrays is initialized resulting in some unpredictable results on different platforms and drivers. --- source/blender/gpu/intern/gpu_buffers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 4c6ead3d3f4..75ed7d7eb19 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -1151,7 +1151,7 @@ void GPU_buffer_unbind(void) glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } } - GLStates &= !(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE | + GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE | GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE); @@ -1191,7 +1191,7 @@ void GPU_color_switch(int mode) else { if (GLStates & GPU_BUFFER_COLOR_STATE) glDisableClientState(GL_COLOR_ARRAY); - GLStates &= (!GPU_BUFFER_COLOR_STATE); + GLStates &= ~GPU_BUFFER_COLOR_STATE; } } -- cgit v1.2.3 From 2221b994bc67bd93d7eb97491d8dacfe869c1e9c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 5 Jun 2012 09:29:47 +0000 Subject: Cycles / OSL: * Remove oslexec_pvt.h header and some typo fixes. * This file needs deeper updates for changes done in OSL 0.6.0, see https://github.com/imageworks/OpenShadingLanguage/commit/11ce51418b45e975ace4d919a4bdd8c2001ba300 --- intern/cycles/kernel/osl/osl_shader.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index fc28833bb8c..d8d510a7c9b 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -27,7 +27,6 @@ #include "util_foreach.h" #include -#include CCL_NAMESPACE_BEGIN @@ -111,7 +110,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { - /* OSL gives use a closure tree, we flatten it into arrays per + /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if (closure->type == OSL::ClosureColor::COMPONENT) { @@ -235,7 +234,7 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) { - /* OSL gives use a closure tree, if we are shading for background there + /* OSL gives us a closure tree, if we are shading for background there * is only one supported closure type at the moment, which has no evaluation * functions, so we just sum the weights */ @@ -289,7 +288,7 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl static void flatten_volume_closure_tree(ShaderData *sd, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { - /* OSL gives use a closure tree, we flatten it into arrays per + /* OSL gives us a closure tree, we flatten it into arrays per * closure type, for evaluation, sampling, etc later on. */ if (closure->type == OSL::ClosureColor::COMPONENT) { -- cgit v1.2.3 From ae8103240d2cf66d2d6aea5bddbc0074700df122 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 09:37:44 +0000 Subject: mask editing - clear feather weights (alt+s) - fix for glitch where placing the feather would jitter. --- release/scripts/startup/bl_ui/space_clip.py | 21 +++-- source/blender/blenkernel/BKE_mask.h | 9 ++- source/blender/blenkernel/intern/mask.c | 59 ++++++++------ .../editors/interface/interface_templates.c | 2 +- source/blender/editors/mask/mask_add.c | 2 +- source/blender/editors/mask/mask_edit.c | 4 + source/blender/editors/mask/mask_intern.h | 1 + source/blender/editors/mask/mask_ops.c | 90 ++++++++++++++++++++-- source/blender/makesrna/intern/rna_mask.c | 2 +- 9 files changed, 151 insertions(+), 39 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index e834712ffe9..d09effc8ff3 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -63,9 +63,11 @@ class CLIP_HT_header(Header): toolsettings = context.tool_settings row = layout.row(align=True) - row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True) + row.prop(toolsettings, "use_proportional_edit_mask", + text="", icon_only=True) if toolsettings.use_proportional_edit_objects: - row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) + row.prop(toolsettings, "proportional_edit_falloff", + text="", icon_only=True) elif sc.view == 'GRAPH': row = layout.row(align=True) @@ -289,7 +291,8 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel): col.prop(settings, "keyframe_b") col = layout.column(align=True) - col.active = tracking_object.is_camera and not settings.use_tripod_solver + col.active = (tracking_object.is_camera and + not settings.use_tripod_solver) col.label(text="Refine:") col.prop(settings, "refine_intrinsics", text="") @@ -723,13 +726,16 @@ class CLIP_PT_active_mask_point(Panel): clip = parent.id tracking = clip.tracking - col.prop_search(parent, "parent", tracking, "objects", icon='OBJECT_DATA', text="Object:") + col.prop_search(parent, "parent", tracking, + "objects", icon='OBJECT_DATA', text="Object:") if parent.parent and parent.parent in tracking.objects: - object = clip.tracking.objects[parent.parent] - col.prop_search(parent, "sub_parent", object, "tracks", icon='ANIM_DATA', text="Track:") + object = tracking.objects[parent.parent] + col.prop_search(parent, "sub_parent", object, + "tracks", icon='ANIM_DATA', text="Track:") else: - col.prop_search(parent, "sub_parent", clip.tracking, "tracks", icon='ANIM_DATA', text="Track:") + col.prop_search(parent, "sub_parent", tracking, + "tracks", icon='ANIM_DATA', text="Track:") class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): @@ -1210,6 +1216,7 @@ class CLIP_MT_mask(Menu): layout.separator() layout.operator("mask.cyclic_toggle") layout.operator("mask.switch_direction") + layout.operator("mask.feather_weight_clear") # TODO, better place? layout.separator() layout.operator("mask.parent_clear") diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 3f837f995ce..f426d96cd5e 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -69,7 +69,14 @@ float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feath void BKE_mask_point_direction_switch(struct MaskSplinePoint *point); void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline); -float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float start_u, const float co[2]); + +typedef enum { + MASK_PROJ_NEG = -1, + MASK_PROJ_ANY = 0, + MASK_PROJ_POS = 1 +} eMaskSign; +float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point, + float start_u, const float co[2], const eMaskSign sign); /* point */ int BKE_mask_point_has_handle(struct MaskSplinePoint *point); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b904b78ffdd..99333411d8a 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -410,8 +410,6 @@ void BKE_mask_point_direction_switch(MaskSplinePoint *point) } } -//typedef (float)[MASK_OBJECT_SHAPE_ELEM_SIZE] MaskLayerShapeElem; - typedef struct MaskLayerShapeElem { float value[MASK_OBJECT_SHAPE_ELEM_SIZE]; } MaskLayerShapeElem; @@ -467,7 +465,8 @@ void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline) } -float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2]) +float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, + float start_u, const float co[2], const eMaskSign sign) { const float proj_eps = 1e-3; const float proj_eps_squared = proj_eps * proj_eps; @@ -475,6 +474,8 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, flo float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u; float ang = -1.0f; + BLI_assert(ABS(sign) <= 1); /* (-1, 0, 1) */ + while (u1 > 0.0f || u2 < 1.0f) { float n1[2], n2[2], co1[2], co2[2]; float v1[2], v2[2]; @@ -485,20 +486,26 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, flo BKE_mask_point_normal(spline, point, u1, n1); sub_v2_v2v2(v1, co, co1); - if (len_squared_v2(v1) > proj_eps_squared) { - ang1 = angle_v2v2(v1, n1); - if (ang1 > M_PI / 2.0f) - ang1 = M_PI - ang1; + if ((sign == MASK_PROJ_ANY) || + ((sign == MASK_PROJ_NEG) && (dot_v2v2(v1, n1) <= 0.0f)) || + ((sign == MASK_PROJ_POS) && (dot_v2v2(v1, n1) >= 0.0f))) + { - if (ang < 0.0f || ang1 < ang) { - ang = ang1; + if (len_squared_v2(v1) > proj_eps_squared) { + ang1 = angle_v2v2(v1, n1); + if (ang1 > M_PI / 2.0f) + ang1 = M_PI - ang1; + + if (ang < 0.0f || ang1 < ang) { + ang = ang1; + u = u1; + } + } + else { u = u1; + break; } } - else { - u = u1; - break; - } } if (u2 <= 1.0f) { @@ -506,20 +513,26 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, flo BKE_mask_point_normal(spline, point, u2, n2); sub_v2_v2v2(v2, co, co2); - if (len_squared_v2(v2) > proj_eps_squared) { - ang2 = angle_v2v2(v2, n2); - if (ang2 > M_PI / 2.0f) - ang2 = M_PI - ang2; + if ((sign == MASK_PROJ_ANY) || + ((sign == MASK_PROJ_NEG) && (dot_v2v2(v2, n2) <= 0.0f)) || + ((sign == MASK_PROJ_POS) && (dot_v2v2(v2, n2) >= 0.0f))) + { + + if (len_squared_v2(v2) > proj_eps_squared) { + ang2 = angle_v2v2(v2, n2); + if (ang2 > M_PI / 2.0f) + ang2 = M_PI - ang2; - if (ang2 < ang) { - ang = ang2; + if (ang2 < ang) { + ang = ang2; + u = u2; + } + } + else { u = u2; + break; } } - else { - u = u2; - break; - } } u1 -= du; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index daba096696c..2d9c6ee7657 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2242,7 +2242,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe } } else if (itemptr->type == &RNA_MaskLayer) { - split = uiLayoutSplit(sub, 0.66f, 0); + split = uiLayoutSplit(sub, 0.5f, 0); uiItemL(split, name, icon); diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index cdfdde4ef31..82f82862577 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -150,7 +150,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c *point_r = point; if (u_r) { - u = BKE_mask_spline_project_co(point_spline, point, u, normal_co); + u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY); *u_r = u; } diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 9a32cff04c3..34d297155f9 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -212,6 +212,9 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_hide_view_clear); WM_operatortype_append(MASK_OT_hide_view_set); + /* feather */ + WM_operatortype_append(MASK_OT_feather_weight_clear); + /* shape */ WM_operatortype_append(MASK_OT_slide_point); WM_operatortype_append(MASK_OT_cyclic_toggle); @@ -293,6 +296,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0); /* relationships */ WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index d2efab8613a..9ac55f22fd9 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -54,6 +54,7 @@ void MASK_OT_delete(struct wmOperatorType *ot); void MASK_OT_hide_view_clear(struct wmOperatorType *ot); void MASK_OT_hide_view_set(struct wmOperatorType *ot); +void MASK_OT_feather_weight_clear(struct wmOperatorType *ot); void MASK_OT_switch_direction(struct wmOperatorType *ot); void MASK_OT_handle_type_set(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index a0c79f4c2c9..dea5345c69f 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -355,10 +355,12 @@ void MASK_OT_layer_remove(wmOperatorType *ot) /******************** slide *********************/ -#define SLIDE_ACTION_NONE 0 -#define SLIDE_ACTION_POINT 1 -#define SLIDE_ACTION_HANDLE 2 -#define SLIDE_ACTION_FEATHER 3 +enum { + SLIDE_ACTION_NONE = 0, + SLIDE_ACTION_POINT = 1, + SLIDE_ACTION_HANDLE = 2, + SLIDE_ACTION_FEATHER = 3 +}; typedef struct SlidePointData { int action; @@ -648,7 +650,29 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) add_v2_v2v2(offco, data->feather, dco); if (data->uw) { - float u = BKE_mask_spline_project_co(data->spline, data->point, data->uw->u, offco); + /* project on both sides and find the closest one, + * prevents flickering when projecting onto both sides can happen */ + const float u_pos = BKE_mask_spline_project_co(data->spline, data->point, + data->uw->u, offco, MASK_PROJ_NEG); + const float u_neg = BKE_mask_spline_project_co(data->spline, data->point, + data->uw->u, offco, MASK_PROJ_POS); + float dist_pos = FLT_MAX; + float dist_neg = FLT_MAX; + float co_pos[2]; + float co_neg[2]; + float u; + + if (u_pos > 0.0f && u_pos < 1.0f) { + BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos); + dist_pos = len_squared_v2v2(offco, co_pos); + } + + if (u_neg > 0.0f && u_neg < 1.0f) { + BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg); + dist_neg = len_squared_v2v2(offco, co_neg); + } + + u = dist_pos < dist_neg ? u_pos : u_neg; if (u > 0.0f && u < 1.0f) { data->uw->u = u; @@ -1165,5 +1189,61 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers"); +} + + +static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int changed = FALSE; + int i; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + BezTriple *bezt = &point->bezt; + bezt->weight = 0.0f; + changed = TRUE; + } + } + } + } + + if (changed) { + /* TODO: only update edited splines */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_feather_weight_clear(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Feather Weight"; + ot->description = "Reset the feather weight to zero"; + ot->idname = "MASK_OT_feather_weight_clear"; + + /* api callbacks */ + ot->exec = mask_feather_weight_clear_exec; + ot->poll = ED_maskedit_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 1532e2e7199..51d370d5a88 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -583,7 +583,7 @@ static void rna_def_mask_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MASK_BLENDFLAG_INVERT); - RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); + RNA_def_property_ui_text(prop, "Restrict View", "Invert the mask black/white"); RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); } -- cgit v1.2.3 From f885306bb8b12fb20817bd499fb52d9f072d6b55 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 5 Jun 2012 09:57:19 +0000 Subject: Fix #31702: Drag and Drop parenting crashes Blender Crash was caused by recent changes in parent drop operator which were aimed to prevent parenting objects between different scenes (which probably makes sense). The problem was how it was checked if objects belongs to the same scene -- outliner tree with type ID_SCE was used for this which works pretty nice for All Scenes outliner view. But in other view modes there is no scene element in outliner tree which lead to some NULL pointer dereferences. Currently resolved this by assuming that if there's no Scene parent element in outliner tree parent and child belongs to the same scene which is active scene. This is truth for current view modes of outliner but if it'll be changed in the future this assumption shall be updated and re-implemented with some smarter checks of which scene object from outliner belongs to. --- source/blender/editors/space_outliner/outliner_edit.c | 7 ++++++- source/blender/editors/space_outliner/space_outliner.c | 11 ++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index a752a7d71ae..e5f7b8fd76d 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1503,7 +1503,12 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) scene = (Scene *)outliner_search_back(soops, te_found, ID_SCE); if (scene == NULL) { - return OPERATOR_CANCELLED; + /* currently outlier organized in a way, that if there's no parent scene + * element for object it means that all displayed objects belong to + * active scene and parenting them is allowed (sergey) + */ + + scene = CTX_data_scene(C); } if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) { diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 4d45be561c6..c78be8bd223 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -98,7 +98,16 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) if (te_valid) { /* check that parent/child are both in the same scene */ Scene *scene = (Scene *)outliner_search_back(soops, te_valid, ID_SCE); - if (BKE_scene_base_find(scene, (Object *)id)) { + + if (!scene) { + /* currently outlier organized in a way, that if there's no parent scene + * element for object it means that all displayed objects belong to + * active scene and parenting them is allowed (sergey) + */ + return 1; + } + + if (scene && BKE_scene_base_find(scene, (Object *)id)) { return 1; } } -- cgit v1.2.3 From 33246ea4370c0bfbca08157aa817e4da65859211 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 5 Jun 2012 11:28:15 +0000 Subject: Fix #31713: Mask editor: RMB drag crashes Blender Simple missed NULL check in TransData creation. --- source/blender/editors/transform/transform_conversions.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9b8e5daca07..746ca9c33a4 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5950,6 +5950,11 @@ static void createTransMaskingData(bContext *C, TransInfo *t) int count = 0, countsel = 0; int propmode = t->flag & T_PROP_EDIT; + t->total = 0; + + if (!mask) + return; + /* count */ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline = masklay->splines.first; -- cgit v1.2.3 From dd198685c4a8a51f279a2d7257f6e56ff5289db2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 11:28:54 +0000 Subject: code cleanup: var names in mask code --- source/blender/blenkernel/intern/mask.c | 144 ++++++++++++++++---------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 99333411d8a..2eafd7f17a4 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -163,26 +163,26 @@ static int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - MaskSplinePoint *next_point; - BezTriple *bezt, *next_bezt; + MaskSplinePoint *point_next; + BezTriple *bezt, *bezt_next; float a, b, c, len; int cur_resol; if (i == spline->tot_point - 1) { if (spline->flag & MASK_SPLINE_CYCLIC) - next_point = &spline->points[0]; + point_next = &spline->points[0]; else break; } else - next_point = &spline->points[i + 1]; + point_next = &spline->points[i + 1]; bezt = &point->bezt; - next_bezt = &next_point->bezt; + bezt_next = &point_next->bezt; a = len_v3v3(bezt->vec[1], bezt->vec[2]); - b = len_v3v3(bezt->vec[2], next_bezt->vec[0]); - c = len_v3v3(next_bezt->vec[0], next_bezt->vec[1]); + b = len_v3v3(bezt->vec[2], bezt_next->vec[0]); + c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); len = a + b + c; cur_resol = len / max_segment; @@ -635,7 +635,7 @@ float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplin { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - BezTriple *bezt, *next; + BezTriple *bezt, *bezt_next; float *diff_points, *fp; int j, resol = BKE_mask_spline_resolution(spline, width, height); @@ -643,13 +643,13 @@ float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplin if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(points_array[0].bezt); + bezt_next = &(points_array[0].bezt); else - next = NULL; + bezt_next = NULL; } - else next = &((point + 1))->bezt; + else bezt_next = &((point + 1))->bezt; - if (!next) + if (!bezt_next) return NULL; /* resol+1 because of 'forward_diff_bezier' function */ @@ -658,11 +658,11 @@ float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplin for (j = 0; j < 2; j++) { BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j], - next->vec[0][j], next->vec[1][j], + bezt_next->vec[0][j], bezt_next->vec[1][j], fp + j, resol, 2 * sizeof(float)); } - copy_v2_v2(fp + 2 * resol, next->vec[1]); + copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]); return diff_points; } @@ -676,25 +676,25 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - BezTriple *bezt = &point->bezt, *next; + BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2]; if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(points_array[0].bezt); + bezt_next = &(points_array[0].bezt); else - next = NULL; + bezt_next = NULL; } - else next = &((point + 1))->bezt; + else bezt_next = &((point + 1))->bezt; - if (!next) { + if (!bezt_next) { copy_v2_v2(co, bezt->vec[1]); return; } interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); - interp_v2_v2v2(q1, bezt->vec[2], next->vec[0], u); - interp_v2_v2v2(q2, next->vec[0], next->vec[1], u); + interp_v2_v2v2(q1, bezt->vec[2], bezt_next->vec[0], u); + interp_v2_v2v2(q2, bezt_next->vec[0], bezt_next->vec[1], u); interp_v2_v2v2(r0, q0, q1, u); interp_v2_v2v2(r1, q1, q2, u); @@ -706,20 +706,20 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - BezTriple *bezt = &point->bezt, *next; + BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; if (point == &points_array[spline->tot_point - 1]) { if (spline->flag & MASK_SPLINE_CYCLIC) - next = &(points_array[0].bezt); + bezt_next = &(points_array[0].bezt); else - next = NULL; + bezt_next = NULL; } else { - next = &((point + 1))->bezt; + bezt_next = &((point + 1))->bezt; } - if (!next) { + if (!bezt_next) { BKE_mask_point_handle(point, vec); sub_v2_v2v2(n, vec, bezt->vec[1]); @@ -728,8 +728,8 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, } interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); - interp_v2_v2v2(q1, bezt->vec[2], next->vec[0], u); - interp_v2_v2v2(q2, next->vec[0], next->vec[1], u); + interp_v2_v2v2(q1, bezt->vec[2], bezt_next->vec[0], u); + interp_v2_v2v2(q2, bezt_next->vec[0], bezt_next->vec[1], u); interp_v2_v2v2(r0, q0, q1, u); interp_v2_v2v2(r1, q1, q2, u); @@ -1108,28 +1108,28 @@ int BKE_mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delt } } -static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev_point, MaskSplinePoint *next_point) +static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *point_prev, MaskSplinePoint *point_next) { BezTriple *bezt = &point->bezt; - BezTriple *prev_bezt = NULL, *next_bezt = NULL; + BezTriple *bezt_prev = NULL, *bezt_next = NULL; //int handle_type = bezt->h1; - if (prev_point) - prev_bezt = &prev_point->bezt; + if (point_prev) + bezt_prev = &point_prev->bezt; - if (next_point) - next_bezt = &next_point->bezt; + if (point_next) + bezt_next = &point_next->bezt; #if 1 - if (prev_bezt || next_bezt) { - BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + if (bezt_prev || bezt_next) { + BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0); } #else if (handle_type == HD_VECT) { - BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0); } else if (handle_type == HD_AUTO) { - BKE_nurb_handle_calc(bezt, prev_bezt, next_bezt, 0); + BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0); } else if (handle_type == HD_ALIGN) { float v1[3], v2[3]; @@ -1157,37 +1157,37 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *prev void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, MaskSplinePoint *point, MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) { - MaskSplinePoint *prev_point, *next_point; + MaskSplinePoint *point_prev, *point_next; int i = (int)(point - spline->points); BLI_assert(i >= i && i < spline->tot_point); if (i == 0) { if (spline->flag & MASK_SPLINE_CYCLIC) { - prev_point = &spline->points[spline->tot_point - 1]; + point_prev = &spline->points[spline->tot_point - 1]; } else { - prev_point = NULL; + point_prev = NULL; } } else { - prev_point = point - 1; + point_prev = point - 1; } if (i == spline->tot_point - 1) { if (spline->flag & MASK_SPLINE_CYCLIC) { - next_point = &spline->points[0]; + point_next = &spline->points[0]; } else { - next_point = NULL; + point_next = NULL; } } else { - next_point = point + 1; + point_next = point + 1; } - *r_point_prev = prev_point; - *r_point_next = next_point; + *r_point_prev = point_prev; + *r_point_next = point_next; } /* calculates the tanget of a point by its previous and next @@ -1196,21 +1196,21 @@ void BKE_mask_calc_tangent_polyline(Mask *mask, MaskSpline *spline, MaskSplinePo { float tvec_a[2], tvec_b[2]; - MaskSplinePoint *prev_point, *next_point; + MaskSplinePoint *point_prev, *point_next; BKE_mask_get_handle_point_adjacent(mask, spline, point, - &prev_point, &next_point); + &point_prev, &point_next); - if (prev_point) { - sub_v2_v2v2(tvec_a, point->bezt.vec[1], prev_point->bezt.vec[1]); + if (point_prev) { + sub_v2_v2v2(tvec_a, point->bezt.vec[1], point_prev->bezt.vec[1]); normalize_v2(tvec_a); } else { zero_v2(tvec_a); } - if (next_point) { - sub_v2_v2v2(tvec_b, next_point->bezt.vec[1], point->bezt.vec[1]); + if (point_next) { + sub_v2_v2v2(tvec_b, point_next->bezt.vec[1], point->bezt.vec[1]); normalize_v2(tvec_b); } else { @@ -1223,12 +1223,12 @@ void BKE_mask_calc_tangent_polyline(Mask *mask, MaskSpline *spline, MaskSplinePo void BKE_mask_calc_handle_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) { - MaskSplinePoint *prev_point, *next_point; + MaskSplinePoint *point_prev, *point_next; BKE_mask_get_handle_point_adjacent(mask, spline, point, - &prev_point, &next_point); + &point_prev, &point_next); - mask_calc_point_handle(point, prev_point, next_point); + mask_calc_point_handle(point, point_prev, point_next); } static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dist) @@ -1250,31 +1250,31 @@ void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSp float weight_average = 0.0f; - MaskSplinePoint *prev_point, *next_point; + MaskSplinePoint *point_prev, *point_next; BLI_assert(u >= 0.0f && u <= 1.0f); BKE_mask_get_handle_point_adjacent(mask, spline, point, - &prev_point, &next_point); + &point_prev, &point_next); - if (prev_point && next_point) { - length_average = ((len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]) * (1.0f - u)) + - (len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]) * u)); + if (point_prev && point_next) { + length_average = ((len_v2v2(point_prev->bezt.vec[0], point_prev->bezt.vec[1]) * (1.0f - u)) + + (len_v2v2(point_next->bezt.vec[2], point_next->bezt.vec[1]) * u)); - weight_average = (prev_point->bezt.weight * (1.0f - u) + - next_point->bezt.weight * u); + weight_average = (point_prev->bezt.weight * (1.0f - u) + + point_next->bezt.weight * u); length_tot = 1; } else { - if (prev_point) { - length_average += len_v2v2(prev_point->bezt.vec[0], prev_point->bezt.vec[1]); - weight_average += prev_point->bezt.weight; + if (point_prev) { + length_average += len_v2v2(point_prev->bezt.vec[0], point_prev->bezt.vec[1]); + weight_average += point_prev->bezt.weight; length_tot++; } - if (next_point) { - length_average += len_v2v2(next_point->bezt.vec[2], next_point->bezt.vec[1]); - weight_average += next_point->bezt.weight; + if (point_next) { + length_average += len_v2v2(point_next->bezt.vec[2], point_next->bezt.vec[1]); + weight_average += point_next->bezt.weight; length_tot++; } } @@ -1298,18 +1298,18 @@ void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSp void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, const short do_recalc_length) { - MaskSplinePoint *prev_point, *next_point; + MaskSplinePoint *point_prev, *point_next; const char h_back[2] = {point->bezt.h1, point->bezt.h2}; const float length_average = (do_recalc_length) ? 0.0f /* dummy value */ : (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) + len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) / 2.0f; BKE_mask_get_handle_point_adjacent(mask, spline, point, - &prev_point, &next_point); + &point_prev, &point_next); point->bezt.h1 = HD_AUTO; point->bezt.h2 = HD_AUTO; - mask_calc_point_handle(point, prev_point, next_point); + mask_calc_point_handle(point, point_prev, point_next); point->bezt.h1 = h_back[0]; point->bezt.h2 = h_back[1]; -- cgit v1.2.3 From aca2e6a739efdfe8c37dbfe182d5c4557c12ae5e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 11:46:55 +0000 Subject: code cleanup: helper functions for masking. --- source/blender/blenkernel/intern/mask.c | 148 ++++++++++++++++---------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 2eafd7f17a4..5f6bd862fc2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -58,6 +58,68 @@ #include "raskter.h" +static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) +{ + if (point == &points_array[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + return &points_array[0]; + } + else { + return NULL; + } + } + else { + return point + 1; + } +} + +static MaskSplinePoint *mask_spline_point_prev(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) +{ + if (point == points_array) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + return &points_array[spline->tot_point - 1]; + } + else { + return NULL; + } + } + else { + return point - 1; + } +} + +static BezTriple *mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) +{ + if (point == &points_array[spline->tot_point - 1]) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + return &(points_array[0].bezt); + } + else { + return NULL; + } + } + else { + return &((point + 1))->bezt; + } +} + +#if 0 +static BezTriple *mask_spline_point_prev_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) +{ + if (point == points_array) { + if (spline->flag & MASK_SPLINE_CYCLIC) { + return &(points_array[0].bezt); + } + else { + return NULL; + } + } + else { + return &((point - 1))->bezt; + } +} +#endif + MaskSplinePoint *BKE_mask_spline_point_array(MaskSpline *spline) { return spline->points_deform ? spline->points_deform : spline->points; @@ -163,22 +225,16 @@ static int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - MaskSplinePoint *point_next; BezTriple *bezt, *bezt_next; float a, b, c, len; int cur_resol; - if (i == spline->tot_point - 1) { - if (spline->flag & MASK_SPLINE_CYCLIC) - point_next = &spline->points[0]; - else - break; - } - else - point_next = &spline->points[i + 1]; - bezt = &point->bezt; - bezt_next = &point_next->bezt; + bezt_next = mask_spline_point_next_bezt(spline, spline->points, point); + + if (bezt_next == NULL) { + break; + } a = len_v3v3(bezt->vec[1], bezt->vec[2]); b = len_v3v3(bezt->vec[2], bezt_next->vec[0]); @@ -640,14 +696,7 @@ float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplin int j, resol = BKE_mask_spline_resolution(spline, width, height); bezt = &point->bezt; - - if (point == &points_array[spline->tot_point - 1]) { - if (spline->flag & MASK_SPLINE_CYCLIC) - bezt_next = &(points_array[0].bezt); - else - bezt_next = NULL; - } - else bezt_next = &((point + 1))->bezt; + bezt_next = mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) return NULL; @@ -679,13 +728,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2]; - if (point == &points_array[spline->tot_point - 1]) { - if (spline->flag & MASK_SPLINE_CYCLIC) - bezt_next = &(points_array[0].bezt); - else - bezt_next = NULL; - } - else bezt_next = &((point + 1))->bezt; + bezt_next = mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { copy_v2_v2(co, bezt->vec[1]); @@ -709,15 +752,7 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, BezTriple *bezt = &point->bezt, *bezt_next; float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; - if (point == &points_array[spline->tot_point - 1]) { - if (spline->flag & MASK_SPLINE_CYCLIC) - bezt_next = &(points_array[0].bezt); - else - bezt_next = NULL; - } - else { - bezt_next = &((point + 1))->bezt; - } + bezt_next = mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) { BKE_mask_point_handle(point, vec); @@ -750,17 +785,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) float cur_u, cur_w, next_u, next_w, fac; int i; - if (point == &points_array[spline->tot_point - 1]) { - if (spline->flag & MASK_SPLINE_CYCLIC) { - bezt_next = &(points_array[0].bezt); - } - else { - bezt_next = NULL; - } - } - else { - bezt_next = &((point + 1))->bezt; - } + bezt_next = mask_spline_point_next_bezt(spline, points_array, point); if (!bezt_next) return bezt->weight; @@ -1157,37 +1182,12 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *poin void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, MaskSplinePoint *point, MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) { - MaskSplinePoint *point_prev, *point_next; int i = (int)(point - spline->points); - BLI_assert(i >= i && i < spline->tot_point); + (void)i; /* quiet release builds */ - if (i == 0) { - if (spline->flag & MASK_SPLINE_CYCLIC) { - point_prev = &spline->points[spline->tot_point - 1]; - } - else { - point_prev = NULL; - } - } - else { - point_prev = point - 1; - } - - if (i == spline->tot_point - 1) { - if (spline->flag & MASK_SPLINE_CYCLIC) { - point_next = &spline->points[0]; - } - else { - point_next = NULL; - } - } - else { - point_next = point + 1; - } - - *r_point_prev = point_prev; - *r_point_next = point_next; + *r_point_prev = mask_spline_point_prev(spline, spline->points, point); + *r_point_next = mask_spline_point_next(spline, spline->points, point); } /* calculates the tanget of a point by its previous and next -- cgit v1.2.3 From 49cc9c7502dcbdc60b4d0e7df7fe3e304e622010 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 12:09:24 +0000 Subject: code cleanup: mask feather weight - add in checks for u==1 or u==0 --- source/blender/blenkernel/intern/mask.c | 66 +++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 5f6bd862fc2..26e0f14e08b 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -780,47 +780,57 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - BezTriple *bezt = &point->bezt, *bezt_next; - float cur_u, cur_w, next_u, next_w, fac; - int i; bezt_next = mask_spline_point_next_bezt(spline, points_array, point); - if (!bezt_next) + if (!bezt_next) { return bezt->weight; + } + else if (u <= 0.0) { + return bezt->weight; + } + else if (u >= 1.0f) { + return bezt_next->weight; + } + else { + float cur_u, cur_w, next_u, next_w, fac; + int i; - for (i = 0; i < point->tot_uw + 1; i++) { + for (i = 0; i < point->tot_uw + 1; i++) { - if (i == 0) { - cur_u = 0.0f; - cur_w = bezt->weight; - } - else { - cur_u = point->uw[i - 1].u; - cur_w = point->uw[i - 1].w; + if (i == 0) { + cur_u = 0.0f; + cur_w = bezt->weight; + } + else { + cur_u = point->uw[i - 1].u; + cur_w = point->uw[i - 1].w; + } + + if (i == point->tot_uw) { + next_u = 1.0f; + next_w = bezt_next->weight; + } + else { + next_u = point->uw[i].u; + next_w = point->uw[i].w; + } + + if (u >= cur_u && u <= next_u) { + break; + } } - if (i == point->tot_uw) { - next_u = 1.0f; - next_w = bezt_next->weight; + fac = (u - cur_u) / (next_u - cur_u); + + if (spline->weight_interp == MASK_SPLINE_INTERP_EASE) { + return cur_w + (next_w - cur_w) * (3.0f * fac * fac - 2.0f * fac * fac * fac); } else { - next_u = point->uw[i].u; - next_w = point->uw[i].w; - } - - if (u >= cur_u && u <= next_u) { - break; + return (1.0f - fac) * cur_w + fac * next_w; } } - - fac = (u - cur_u) / (next_u - cur_u); - - if (spline->weight_interp == MASK_SPLINE_INTERP_EASE) - return cur_w + (next_w - cur_w) * (3.0f * fac * fac - 2.0f * fac * fac * fac); - else - return (1.0f - fac) * cur_w + fac * next_w; } MaskSplinePointUW *BKE_mask_point_sort_uw(MaskSplinePoint *point, MaskSplinePointUW *uw) -- cgit v1.2.3 From f72c8565bf86cd19396a12d4cdf65aaeb35efb74 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 12:22:02 +0000 Subject: change how the weight for feather points are calculated with masking, instead of using absolute weights, multiply by by the weights of the adjacent beziers. without this - there was no way to animate the overall feather influence of the feather. will update tools to account for this next. --- source/blender/blenkernel/intern/mask.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 26e0f14e08b..4104d5f274b 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -777,6 +777,11 @@ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, normalize_v2(n); } +static float mask_point_interp_weight(BezTriple *bezt, BezTriple *bezt_next, const float u) +{ + return (bezt->weight * (1.0f - u)) + (bezt_next->weight * u); +} + float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); @@ -801,7 +806,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) if (i == 0) { cur_u = 0.0f; - cur_w = bezt->weight; + cur_w = 1.0f; /* mask_point_interp_weight will scale it */ } else { cur_u = point->uw[i - 1].u; @@ -810,7 +815,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) if (i == point->tot_uw) { next_u = 1.0f; - next_w = bezt_next->weight; + next_w = 1.0f; /* mask_point_interp_weight will scale it */ } else { next_u = point->uw[i].u; @@ -824,6 +829,9 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) fac = (u - cur_u) / (next_u - cur_u); + cur_w *= mask_point_interp_weight(bezt, bezt_next, cur_u); + next_w *= mask_point_interp_weight(bezt, bezt_next, next_u); + if (spline->weight_interp == MASK_SPLINE_INTERP_EASE) { return cur_w + (next_w - cur_w) * (3.0f * fac * fac - 2.0f * fac * fac * fac); } -- cgit v1.2.3 From fe58f668a122fde73b14d20ffec6cd3f75034eea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 12:51:11 +0000 Subject: mask point slide now accounts for scaled bezier weights, --- source/blender/blenkernel/BKE_mask.h | 1 + source/blender/blenkernel/intern/mask.c | 23 +++++++++++++++++++++- source/blender/editors/mask/mask_add.c | 5 +++++ source/blender/editors/mask/mask_ops.c | 35 ++++++++++++++++++++++----------- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index f426d96cd5e..3ca892604c5 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -98,6 +98,7 @@ float *BKE_mask_point_segment_feather_diff_with_resolution(struct MaskSpline *sp void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]); void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float n[2]); +float BKE_mask_point_weight_scalar(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u); struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 4104d5f274b..102ec454aaa 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -782,7 +782,28 @@ static float mask_point_interp_weight(BezTriple *bezt, BezTriple *bezt_next, con return (bezt->weight * (1.0f - u)) + (bezt_next->weight * u); } -float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, float u) +float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, const float u) +{ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); + BezTriple *bezt = &point->bezt, *bezt_next; + + bezt_next = mask_spline_point_next_bezt(spline, points_array, point); + + if (!bezt_next) { + return bezt->weight; + } + else if (u <= 0.0) { + return bezt->weight; + } + else if (u >= 1.0f) { + return bezt_next->weight; + } + else { + return mask_point_interp_weight(bezt, bezt_next, u); + } +} + +float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const float u) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); BezTriple *bezt = &point->bezt, *bezt_next; diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 82f82862577..f8c36e866d7 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -654,6 +654,11 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) { Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); + float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u); + + if (weight_scalar != 0.0f) { + w = w / weight_scalar; + } BKE_mask_point_add_uw(point, u, w); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index dea5345c69f..c9f2450afc3 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -387,15 +387,18 @@ static int slide_point_check_initial_feather(MaskSpline *spline) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - int j; if (point->bezt.weight != 0.0f) return FALSE; + /* comment for now. if all bezt weights are zero - this is as good-as initial */ +#if 0 + int j; for (j = 0; j < point->tot_uw; j++) { if (point->uw[j].w != 0.0f) return FALSE; } +#endif } return TRUE; @@ -454,25 +457,21 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) if (uw) { float co[2]; - - customdata->weight = point->bezt.weight; + float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u); customdata->weight = uw->w; BKE_mask_point_segment_co(spline, point, uw->u, co); BKE_mask_point_normal(spline, point, uw->u, customdata->no); - customdata->feather[0] = co[0] + customdata->no[0] * uw->w; - customdata->feather[1] = co[1] + customdata->no[1] * uw->w; + madd_v2_v2v2fl(customdata->feather, co, customdata->no, uw->w * weight_scalar); } else { BezTriple *bezt = &point->bezt; + customdata->weight = bezt->weight; BKE_mask_point_normal(spline, point, 0.0f, customdata->no); - customdata->feather[0] = bezt->vec[1][0] + customdata->no[0] * bezt->weight; - customdata->feather[1] = bezt->vec[1][1] + customdata->no[1] * bezt->weight; - - customdata->weight = bezt->weight; + madd_v2_v2v2fl(customdata->feather, bezt->vec[1], customdata->no, bezt->weight); } if (customdata->action == SLIDE_ACTION_FEATHER) @@ -533,17 +532,20 @@ static void slide_point_delta_all_feather(SlidePointData *data, float delta) for (i = 0; i < data->spline->tot_point; i++) { MaskSplinePoint *point = &data->spline->points[i]; MaskSplinePoint *orig_point = &data->orig_spline->points[i]; - int j; point->bezt.weight = orig_point->bezt.weight + delta; if (point->bezt.weight < 0.0f) point->bezt.weight = 0.0f; + /* not needed anymore */ +#if 0 + int j; for (j = 0; j < point->tot_uw; j++) { point->uw[j].w = orig_point->uw[j].w + delta; if (point->uw[j].w < 0.0f) point->uw[j].w = 0.0f; } +#endif } } @@ -645,6 +647,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) else if (data->action == SLIDE_ACTION_FEATHER) { float vec[2], no[2], p[2], c[2], w, offco[2]; float *weight = NULL; + float weight_scalar = 1.0f; int overall_feather = data->overall_feather || data->initial_feather; add_v2_v2v2(offco, data->feather, dco); @@ -679,12 +682,18 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) data->uw = BKE_mask_point_sort_uw(data->point, data->uw); weight = &data->uw->w; + weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u); + if (weight_scalar != 0.0f) { + weight_scalar = 1.0f / weight_scalar; + } + BKE_mask_point_normal(data->spline, data->point, data->uw->u, no); BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); } } else { weight = &bezt->weight; + /* weight_scalar = 1.0f; keep as is */ copy_v2_v2(no, data->no); copy_v2_v2(p, bezt->vec[1]); } @@ -707,7 +716,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) /* restore weight for currently sliding point, so orig_spline would be created * with original weights used */ - *weight = data->weight; + *weight = data->weight * weight_scalar; data->orig_spline = BKE_mask_spline_copy(data->spline); } @@ -726,7 +735,9 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) data->orig_spline = NULL; } - *weight = w; + if (weight_scalar != 0.0f) { + *weight = w * weight_scalar; + } } } } -- cgit v1.2.3 From 8c71157af62825420273435cfebc03ac00f2f05c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 14:13:14 +0000 Subject: shrink/fatten transform for mask - adjusts the feather weight. works in proportional editmode too. --- release/scripts/startup/bl_ui/space_clip.py | 4 ++ source/blender/editors/include/ED_transform.h | 1 + source/blender/editors/mask/mask_edit.c | 4 +- source/blender/editors/transform/transform.c | 72 ++++++++++++++++++++++ source/blender/editors/transform/transform.h | 3 + .../editors/transform/transform_conversions.c | 12 +++- source/blender/editors/transform/transform_ops.c | 1 + 7 files changed, 94 insertions(+), 3 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index d09effc8ff3..dc65a2541b4 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -403,6 +403,8 @@ class CLIP_PT_tools_mask(CLIP_PT_mask_view_panel, Panel): col.operator("transform.translate") col.operator("transform.rotate") col.operator("transform.resize", text="Scale") + props = col.operator("transform.transform", text="Shrink/Fatten") + props.mode = 'MASK_SHRINKFATTEN' col = layout.column(align=True) col.label(text="Spline:") @@ -1253,6 +1255,8 @@ class CLIP_MT_mask_transform(Menu): layout.operator("transform.translate") layout.operator("transform.rotate") layout.operator("transform.resize") + props = layout.operator("transform.transform", text="Shrink/Fatten") + props.mode = 'MASK_SHRINKFATTEN' class CLIP_MT_camera_presets(Menu): diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index d867532b273..c4d7197bfa1 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -71,6 +71,7 @@ enum { TFM_BONESIZE, TFM_BONE_ENVELOPE, TFM_CURVE_SHRINKFATTEN, + TFM_MASK_SHRINKFATTEN, TFM_BONE_ROLL, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 34d297155f9..ffcadbd086f 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -296,7 +296,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0); + // WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0); + /* ... matches curve editmode */ + RNA_enum_set(WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", TFM_MASK_SHRINKFATTEN); /* relationships */ WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 157fe1aa710..786479eceb2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1720,6 +1720,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_CURVE_SHRINKFATTEN: initCurveShrinkFatten(t); break; + case TFM_MASK_SHRINKFATTEN: + initMaskShrinkFatten(t); + break; case TFM_TRACKBALL: initTrackball(t); break; @@ -3925,6 +3928,75 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) return 1; } + +void initMaskShrinkFatten(TransInfo *t) +{ + t->mode = TFM_MASK_SHRINKFATTEN; + t->transform = MaskShrinkFatten; + + initMouseInputMode(t, &t->mouse, INPUT_SPRING); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; + + t->flag |= T_NO_ZERO; + t->num.flag |= NUM_NO_ZERO; + + t->flag |= T_NO_CONSTRAINT; +} + +int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) +{ + TransData *td = t->data; + float ratio; + int i; + char str[50]; + + ratio = t->values[0]; + + snapGrid(t, &ratio); + + applyNumInput(&t->num, &ratio); + + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[20]; + + outputNumInput(&(t->num), c); + sprintf(str, "Shrink/Fatten: %s", c); + } + else { + sprintf(str, "Shrink/Fatten: %3f", ratio); + } + + for (i = 0 ; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + if (td->val) { + *td->val = td->ival * ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + + if (*td->val <= 0.0f) *td->val = 0.001f; + } + } + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} + /* ************************** PUSH/PULL *************************** */ void initPushPull(TransInfo *t) diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 59688f1436e..32a4d4ab1a3 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -494,6 +494,9 @@ int Tilt(TransInfo *t, const int mval[2]); void initCurveShrinkFatten(TransInfo *t); int CurveShrinkFatten(TransInfo *t, const int mval[2]); +void initMaskShrinkFatten(TransInfo *t); +int MaskShrinkFatten(TransInfo *t, const int mval[2]); + void initTrackball(TransInfo *t); int Trackball(TransInfo *t, const int mval[2]); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 746ca9c33a4..4e78138dd1b 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5887,8 +5887,16 @@ static void MaskPointToTransData(SpaceClip *sc, MaskSplinePoint *point, memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; - td->val= NULL; + td->ext = NULL; + + if (i == 1) { + /* scaling weights */ + td->val = &bezt->weight; + td->ival = *td->val; + } + else { + td->val = NULL; + } if (is_sel_any) { td->flag |= TD_SELECTED; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 6fd8e07d34a..9d2a104d8e9 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -135,6 +135,7 @@ EnumPropertyItem transform_mode_types[] = {TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""}, {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""}, {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""}, + {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""}, {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""}, {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""}, {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""}, -- cgit v1.2.3 From 957ea14511053f404c399385953640e2f0333bc0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 14:19:13 +0000 Subject: shrink/fatten now works with proportional editmode on curves. --- source/blender/editors/transform/transform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 786479eceb2..6b96bfdf66c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3915,8 +3915,9 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) continue; if (td->val) { - // *td->val= ratio; *td->val= td->ival*ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); if (*td->val <= 0.0f) *td->val = 0.001f; } } @@ -3985,7 +3986,6 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) *td->val = td->ival * ratio; /* apply PET */ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; } } -- cgit v1.2.3 From da38a0348a37de625296ed527bcae666a0c0fcb0 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 5 Jun 2012 15:40:02 +0000 Subject: Cycles / OSL: * Fixes for r46114, object_fetch_transform missed time argument. * Syntax fixes for Checker texture. --- intern/cycles/kernel/osl/nodes/node_checker_texture.osl | 6 +++--- intern/cycles/kernel/osl/osl_services.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl b/intern/cycles/kernel/osl/nodes/node_checker_texture.osl index 712d51333ad..a80242ad36a 100644 --- a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_checker_texture.osl @@ -42,9 +42,9 @@ float checker(point p) shader node_checker_texture( float Scale = 5.0, point Vector = P, - color Color1 = color(0.8, 0.8, 0.8); - color Color2 = color(0.2, 0.2, 0.2); - output float Fac = 0.0) + color Color1 = color(0.8, 0.8, 0.8), + color Color2 = color(0.2, 0.2, 0.2), + output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { Fac = checker(Vector*Scale); diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index ca9e47c9f77..12f3a377ef4 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -72,7 +72,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr int object = sd->object; if (object != ~0) { - Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, time, OBJECT_TRANSFORM); tfm = transform_transpose(tfm); result = TO_MATRIX44(tfm); @@ -93,7 +93,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform int object = sd->object; if (object != ~0) { - Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, time, OBJECT_INVERSE_TRANSFORM); tfm = transform_transpose(tfm); result = TO_MATRIX44(tfm); -- cgit v1.2.3 From 0d61876ed05af04fa0c19413e669c8b8a255dcf4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 5 Jun 2012 18:38:09 +0000 Subject: Configurable start frame for movie clip datablocks as alternative to automatic start frame number Number of start frame in opened image sequence used to be distinguished automatically in a way that file name used on open would be displayed at scene frame #1. But sometimes it's useful to have it manually configurable (like in cases when you're processing image sequence and replacing clip's filepath to postprocessed image sequence and want new clip to show at the same frame range as it was rendered from). Added Custom Start Frame flag to movie clip (could be accessed from Footage panel in clip editor) and Start Frame which means number of frame from sequence which would be displayed at scene frame #1. For example if you've got clip pointing to file render_00100.png and Start Frame of 100 this file would be displayed at scene frame #1, if Start Frame is 1 then this image would be displayed at scene frame #100, --- release/scripts/startup/bl_ui/space_clip.py | 10 +++++----- source/blender/blenkernel/intern/movieclip.c | 18 +++++++++++++++--- source/blender/editors/space_clip/clip_editor.c | 16 +++++++++++++++- source/blender/makesdna/DNA_movieclip_types.h | 3 +++ source/blender/makesrna/intern/rna_movieclip.c | 13 +++++++++++++ 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index dc65a2541b4..388843f8e70 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -958,11 +958,11 @@ class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): sc = context.space_data clip = sc.clip - if clip: - layout.template_movieclip(sc, "clip", compact=True) - else: - layout.operator("clip.open", icon='FILESEL') - + col = layout.column() + col.template_movieclip(sc, "clip", compact=True) + col.prop(clip, "use_custom_start_frame") + if clip.use_custom_start_frame: + col.prop(clip, "start_frame") class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel): diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index ccf64639967..a90fc28cd1e 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -153,9 +153,15 @@ static void get_sequence_fname(MovieClip *clip, int framenr, char *name) BLI_strncpy(name, clip->name, sizeof(clip->name)); BLI_stringdec(name, head, tail, &numlen); - /* movieclips always points to first image from sequence, - * autoguess offset for now. could be something smarter in the future */ - offset = sequence_guess_offset(clip->name, strlen(head), numlen); + if (clip->flag & MCLIP_CUSTOM_START_FRAME) { + offset = clip->start_frame; + } + else { + /* movieclips always points to first image from sequence, + * autoguess offset for now. could be something smarter in the future + */ + offset = sequence_guess_offset(clip->name, strlen(head), numlen); + } if (numlen) BLI_stringenc(name, head, tail, numlen, offset + framenr - 1); @@ -250,6 +256,10 @@ static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, in dur = IMB_anim_get_duration(clip->anim, tc); fra = framenr - 1; + if (clip->flag & MCLIP_CUSTOM_START_FRAME) { + fra += clip->start_frame - 1; + } + if (fra < 0) fra = 0; @@ -443,6 +453,8 @@ static MovieClip *movieclip_alloc(const char *name) IMB_TC_RECORD_RUN_NO_GAPS; clip->proxy.quality = 90; + clip->start_frame = 1; + return clip; } diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 13e0a3c8b91..24b37bb041f 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -544,7 +544,10 @@ typedef struct SpaceClipDrawContext { struct ImBuf *texture_ibuf; /* image buffer for which texture was created */ int image_width, image_height; /* image width and height for which texture was created */ unsigned last_texture; /* ID of previously used texture, so it'll be restored after clip drawing */ - int framenr; + + /* fields to check if cache is still valid */ + int framenr, start_frame; + short custom_start_frame; } SpaceClipDrawContext; int ED_space_clip_texture_buffer_supported(SpaceClip *sc) @@ -574,6 +577,7 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) SpaceClipDrawContext *context = sc->draw_context; MovieClip *clip = ED_space_clip(sc); int need_rebind = 0; + short custom_start_frame = FALSE; context->last_texture = glaGetOneInteger(GL_TEXTURE_2D); @@ -583,6 +587,14 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) need_rebind |= context->texture_ibuf != ibuf; need_rebind |= context->framenr != sc->user.framenr; + if (clip->flag & MCLIP_CUSTOM_START_FRAME) { + need_rebind |= context->custom_start_frame != TRUE; + need_rebind |= context->start_frame != clip->start_frame; + } + else { + need_rebind |= context->custom_start_frame != FALSE; + } + if (need_rebind) { int width = ibuf->x, height = ibuf->y; int need_recreate = 0; @@ -636,6 +648,8 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) context->image_width = ibuf->x; context->image_height = ibuf->y; context->framenr = sc->user.framenr; + context->start_frame = clip->start_frame; + context->custom_start_frame = (clip->flag & MCLIP_CUSTOM_START_FRAME) ? TRUE : FALSE; } else { /* displaying exactly the same image which was loaded t oa texture, diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index f073a1957dc..81d532fd247 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -85,6 +85,8 @@ typedef struct MovieClip { int flag; int len; /* length of movie */ + + int start_frame, pad; } MovieClip; typedef struct MovieClipScopes { @@ -121,6 +123,7 @@ typedef struct MovieClipScopes { /* MovieClip->flag */ #define MCLIP_USE_PROXY (1<<0) #define MCLIP_USE_PROXY_CUSTOM_DIR (1<<1) +#define MCLIP_CUSTOM_START_FRAME (1<<2) #define MCLIP_TIMECODE_FLAGS (MCLIP_USE_PROXY|MCLIP_USE_PROXY_CUSTOM_DIR) diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 2cbe6946485..70cb0de643e 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -284,6 +284,19 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip"); + + /* use custom offset */ + prop = RNA_def_property(srna, "use_custom_start_frame", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MCLIP_CUSTOM_START_FRAME); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Custom Start Frame", "Use custom first frame offset instead of automatic frame number"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update"); + + /* frame offset */ + prop = RNA_def_property(srna, "start_frame", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "start_frame"); + RNA_def_property_ui_text(prop, "Start Frame", "Number of frame from sequence or movie displaying at scene frame #1"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update"); } void RNA_def_movieclip(BlenderRNA *brna) -- cgit v1.2.3 From 491babf2a7c4306e71945d4847616fbb88d961fd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 5 Jun 2012 19:23:52 +0000 Subject: Enable cuda sm_30 kernels for buildbot --- build_files/buildbot/config/user-config-i686.py | 1 + build_files/buildbot/config/user-config-x86_64.py | 1 + 2 files changed, 2 insertions(+) diff --git a/build_files/buildbot/config/user-config-i686.py b/build_files/buildbot/config/user-config-i686.py index f7190b3dedb..b07dd505369 100644 --- a/build_files/buildbot/config/user-config-i686.py +++ b/build_files/buildbot/config/user-config-i686.py @@ -97,6 +97,7 @@ WITH_BF_JACK = True # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True diff --git a/build_files/buildbot/config/user-config-x86_64.py b/build_files/buildbot/config/user-config-x86_64.py index ac2342057fb..5905a9c29dd 100644 --- a/build_files/buildbot/config/user-config-x86_64.py +++ b/build_files/buildbot/config/user-config-x86_64.py @@ -97,6 +97,7 @@ WITH_BF_JACK = True # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True -- cgit v1.2.3 From 4ce2219901f247ce724bab6015138b4456483815 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 19:24:01 +0000 Subject: edge split modifier now works more like pre-bmesh --- 3+ faces using an edge always split. --- source/blender/modifiers/intern/MOD_edgesplit.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index eb3334d31ce..1b3e3c16486 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -79,7 +79,11 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj if ((l1 = e->l) && (l2 = e->l->radial_next) != l1) { - if (dot_v3v3(l1->f->no, l2->f->no) < threshold) { + if (/* 3+ faces on thsi edge, always split */ + UNLIKELY(l1 != l2->radial_next) || + /* 2 face edge - check angle*/ + (dot_v3v3(l1->f->no, l2->f->no) < threshold)) + { BMO_elem_flag_enable(bm, e, EDGE_MARK); } } -- cgit v1.2.3 From 465b11e971e126790ecd0dffa327a64189d4875e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 19:39:12 +0000 Subject: operator to reset feather weights on all shape keys --- release/scripts/startup/bl_ui/space_clip.py | 16 +++-- source/blender/blenkernel/BKE_mask.h | 8 ++- source/blender/blenkernel/intern/mask.c | 33 +++++----- source/blender/editors/mask/mask_edit.c | 1 + source/blender/editors/mask/mask_intern.h | 1 + source/blender/editors/mask/mask_shapekey.c | 94 +++++++++++++++++++++++++++++ source/blender/makesdna/DNA_mask_types.h | 11 +++- 7 files changed, 140 insertions(+), 24 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 388843f8e70..9f283b70f77 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1224,13 +1224,10 @@ class CLIP_MT_mask(Menu): layout.operator("mask.parent_clear") layout.operator("mask.parent_set") - layout.separator() - layout.operator("mask.shape_key_clear") - layout.operator("mask.shape_key_insert") - layout.separator() layout.menu("CLIP_MT_mask_visibility") layout.menu("CLIP_MT_mask_transform") + layout.menu("CLIP_MT_mask_animation") class CLIP_MT_mask_visibility(Menu): @@ -1259,6 +1256,17 @@ class CLIP_MT_mask_transform(Menu): props.mode = 'MASK_SHRINKFATTEN' +class CLIP_MT_mask_animation(Menu): + bl_label = "Animation" + + def draw(self, context): + layout = self.layout + + layout.operator("mask.shape_key_clear") + layout.operator("mask.shape_key_insert") + layout.operator("mask.shape_key_feather_reset") + + class CLIP_MT_camera_presets(Menu): """Predefined tracking camera intrinsics""" bl_label = "Camera Presets" diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 3ca892604c5..19feb4d8f2e 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -141,11 +141,13 @@ void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape_a, struct MaskLayerShape *masklay_shape_b, const float fac); -struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, int frame); -int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, int frame, +struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, const int frame); +int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const int frame, struct MaskLayerShape **r_masklay_shape_a, struct MaskLayerShape **r_masklay_shape_b); -struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, int frame); +struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame); +void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape); +struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, const int frame); void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); void BKE_mask_layer_shape_sort(struct MaskLayer *masklay); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 102ec454aaa..aaefa558c9b 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -466,10 +466,6 @@ void BKE_mask_point_direction_switch(MaskSplinePoint *point) } } -typedef struct MaskLayerShapeElem { - float value[MASK_OBJECT_SHAPE_ELEM_SIZE]; -} MaskLayerShapeElem; - void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline) { const int tot_point = spline->tot_point; @@ -1008,6 +1004,20 @@ MaskSpline *BKE_mask_spline_copy(MaskSpline *spline) return nspline; } +/* note: does NOT add to the list */ +MaskLayerShape *BKE_mask_layer_shape_alloc(MaskLayer *masklay, const int frame) +{ + MaskLayerShape *masklay_shape; + int tot_vert = BKE_mask_layer_shape_totvert(masklay); + + masklay_shape = MEM_mallocN(sizeof(MaskLayerShape), __func__); + masklay_shape->frame = frame; + masklay_shape->tot_vert = tot_vert; + masklay_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); + + return masklay_shape; +} + void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape) { MEM_freeN(masklay_shape->data); @@ -1696,7 +1706,7 @@ void BKE_mask_layer_shape_to_mask_interp(MaskLayer *masklay, } } -MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, int frame) +MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int frame) { MaskLayerShape *masklay_shape; @@ -1716,7 +1726,7 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, int frame) } /* when returning 2 - the frame isnt found but before/after frames are */ -int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, int frame, +int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const int frame, MaskLayerShape **r_masklay_shape_a, MaskLayerShape **r_masklay_shape_b) { @@ -1751,22 +1761,15 @@ int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, int frame, return 0; } -MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, int frame) +MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, const int frame) { MaskLayerShape *masklay_shape; masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame); if (masklay_shape == NULL) { - int tot_vert = BKE_mask_layer_shape_totvert(masklay); - - masklay_shape = MEM_mallocN(sizeof(MaskLayerShape), __func__); - masklay_shape->frame = frame; - masklay_shape->tot_vert = tot_vert; - masklay_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__); - + masklay_shape = BKE_mask_layer_shape_alloc(masklay, frame); BLI_addtail(&masklay->splines_shapes, masklay_shape); - BKE_mask_layer_shape_sort(masklay); } diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index ffcadbd086f..9bfcd2a9886 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -227,6 +227,7 @@ void ED_operatortypes_mask(void) /* shapekeys */ WM_operatortype_append(MASK_OT_shape_key_insert); WM_operatortype_append(MASK_OT_shape_key_clear); + WM_operatortype_append(MASK_OT_shape_key_feather_reset); } void ED_keymap_mask(wmKeyConfig *keyconf) diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 9ac55f22fd9..fc6089238a1 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -108,5 +108,6 @@ void ED_mask_point_pos__reverse(struct bContext *C, float x, float y, float *xr, /* mask_shapekey.c */ void MASK_OT_shape_key_insert(struct wmOperatorType *ot); void MASK_OT_shape_key_clear(struct wmOperatorType *ot); +void MASK_OT_shape_key_feather_reset(struct wmOperatorType *ot); #endif /* __MASK_INTERN_H__ */ diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 0c01487b2a9..38e8ed627f2 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -35,6 +35,7 @@ #include "BKE_depsgraph.h" #include "BKE_mask.h" +#include "DNA_object_types.h" #include "DNA_mask_types.h" #include "DNA_scene_types.h" @@ -155,3 +156,96 @@ int ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame) return change; } + + +static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + const int frame = CFRA; + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int change = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + if (masklay->splines_shapes.first) { + MaskLayerShape *masklay_shape_reset; + MaskLayerShape *masklay_shape; + + /* get the shapekey of the current state */ + masklay_shape_reset = BKE_mask_layer_shape_alloc(masklay, frame); + /* initialize from mask - as if inseting a keyframe */ + BKE_mask_layer_shape_from_mask(masklay, masklay_shape_reset); + + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + + if (masklay_shape_reset->tot_vert == masklay_shape->tot_vert) { + int i_abs = 0; + int i; + MaskSpline *spline; + MaskLayerShapeElem *shape_ele_src; + MaskLayerShapeElem *shape_ele_dst; + + shape_ele_src = (MaskLayerShapeElem *)masklay_shape_reset->data; + shape_ele_dst = (MaskLayerShapeElem *)masklay_shape->data; + + for (spline = masklay->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + /* TODO - nicer access here */ + shape_ele_dst->value[6] = shape_ele_src->value[6]; + } + + shape_ele_src++; + shape_ele_dst++; + + i_abs++; + } + } + + } + else { + // printf("%s: skipping\n", __func__); + } + + change = TRUE; + } + + BKE_mask_layer_shape_free(masklay_shape_reset); + } + } + + if (change) { + WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); + DAG_id_tag_update(&mask->id, 0); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MASK_OT_shape_key_feather_reset(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Feather Reset Animation"; + ot->description = "Resets fearther weights on all selected points animation values"; + ot->idname = "MASK_OT_shape_key_feather_reset"; + + /* api callbacks */ + ot->exec = mask_shape_key_feather_reset_exec; + ot->poll = ED_maskedit_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 28fc9466613..c036369c692 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -97,6 +97,15 @@ typedef struct MaskLayerShape { char pad[7]; } MaskLayerShape; +/* cast to this for convenience, not saved */ +#define MASK_OBJECT_SHAPE_ELEM_SIZE 8 /* 3x 2D points + weight + radius == 8 */ + +# +# +typedef struct MaskLayerShapeElem { + float value[MASK_OBJECT_SHAPE_ELEM_SIZE]; +} MaskLayerShapeElem; + typedef struct MaskLayer { struct MaskLayer *next, *prev; @@ -129,8 +138,6 @@ typedef struct MaskLayer { #define MASK_SPLINE_INTERP_LINEAR 1 #define MASK_SPLINE_INTERP_EASE 2 -#define MASK_OBJECT_SHAPE_ELEM_SIZE 8 /* 3x 2D points + weight + radius == 8 */ - /* ob->restrictflag */ #define MASK_RESTRICT_VIEW 1 #define MASK_RESTRICT_SELECT 2 -- cgit v1.2.3 From 6cff0b71a770a23847e94520adecf9f8639c7e2b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 21:54:21 +0000 Subject: style cleanup --- source/blender/editors/armature/editarmature.c | 37 +- source/blender/editors/curve/curve_ops.c | 12 +- source/blender/editors/curve/editcurve.c | 14 +- source/blender/editors/curve/lorem.c | 2 +- source/blender/editors/interface/interface_panel.c | 4 +- .../blender/editors/interface/interface_widgets.c | 11 +- source/blender/editors/interface/resources.c | 4 +- source/blender/editors/mesh/editmesh_tools.c | 6 +- source/blender/editors/object/object_edit.c | 38 +- source/blender/editors/object/object_lattice.c | 17 +- source/blender/editors/space_clip/clip_editor.c | 1 - source/blender/editors/space_clip/space_clip.c | 2 +- source/blender/python/bmesh/bmesh_py_types.c | 4 +- .../render/intern/raytrace/rayobject_octree.cpp | 861 ++++++++++----------- source/blender/render/intern/source/envmap.c | 424 +++++----- source/blender/render/intern/source/volumetric.c | 142 ++-- source/blender/render/intern/source/voxeldata.c | 98 ++- 17 files changed, 836 insertions(+), 841 deletions(-) diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 48743c68ff5..ea3c8685525 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -756,7 +756,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) * * TODO, loop over children before parents if multiple bones * at once are to be predictable*/ - CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones) + CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) { float delta_mat[4][4]; @@ -923,7 +923,7 @@ int join_armature_exec(bContext *C, wmOperator *UNUSED(op)) pose = ob->pose; ob->mode &= ~OB_MODE_POSE; - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases) { if ((base->object->type == OB_ARMATURE) && (base->object != ob)) { bArmature *curarm = base->object->data; @@ -1195,7 +1195,7 @@ static int separate_armature_exec(bContext *C, wmOperator *UNUSED(op)) /* 1) only edit-base selected */ // TODO: use context iterators for this? - CTX_DATA_BEGIN (C, Base *, base, visible_bases) + CTX_DATA_BEGIN(C, Base *, base, visible_bases) { if (base->object == obedit) base->flag |= 1; else base->flag &= ~1; @@ -2848,7 +2848,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* loop over all bones, and only consider if visible */ - CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) fill_add_joint(ebone, 0, &points); @@ -3562,7 +3562,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op) /* loop over all editable bones */ // XXX the old code did this in reverse order though! - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { for (i = numcuts + 1; i > 1; i--) { /* compute cut ratio first */ @@ -3851,7 +3851,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op) */ /* parent selected bones to the active one */ - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { if (ELEM(ebone, actbone, actmirb) == 0) { if (ebone->flag & BONE_SELECTED) @@ -3877,7 +3877,7 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEve uiLayout *layout = uiPupMenuLayout(pup); int allchildbones = 0; - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { if (ebone != actbone) { if (ebone->parent != actbone) allchildbones = 1; @@ -3937,7 +3937,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op) bArmature *arm = (bArmature *)ob->data; int val = RNA_enum_get(op->ptr, "type"); - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { editbone_clear_parent(ebone, val); } @@ -3974,7 +3974,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot) static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) { /* Set the flags */ - CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { /* ignore bone if selection can't change */ if ((ebone->flag & BONE_UNSELECTABLE) == 0) { @@ -4017,7 +4017,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) } /* Set the flags */ - CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { /* ignore bone if selection can't change */ if ((ebone->flag & BONE_UNSELECTABLE) == 0) { @@ -4437,7 +4437,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op) */ /* align selected bones to the active one */ - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { if (ELEM(ebone, actbone, actmirb) == 0) { if (ebone->flag & BONE_SELECTED) @@ -4523,7 +4523,9 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor * note, special exception for armature mode so we can do multi-select * we could check for multi-select explicitly but think its fine to * always give predictable behavior in weight paint mode - campbell */ - if ((!extend && !deselect && !toggle)|| ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0))) { + if ((!extend && !deselect && !toggle) || + ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0))) + { ED_pose_deselectall(ob, 0); nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = nearBone; @@ -5134,7 +5136,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, } /* only clear relevant transforms for selected bones */ - CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones) + CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) { /* run provided clearing function */ clear_func(pchan); @@ -5278,7 +5280,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) } /* Set the flags */ - CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) + CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) { /* select pchan only if selectable, but deselect works always */ switch (action) { @@ -5674,7 +5676,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op)) arm = ob->data; /* loop through selected bones, auto-naming them */ - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { flip_side_name(newname, ebone->name, TRUE); // 1 = do strip off number extensions ED_armature_bone_rename(arm, ebone->name, newname); @@ -5719,7 +5721,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op) arm = ob->data; /* loop through selected bones, auto-naming them */ - CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { BLI_strncpy(newname, ebone->name, sizeof(newname)); if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis])) @@ -5742,7 +5744,8 @@ void ARMATURE_OT_autoside_names(wmOperatorType *ot) {0, "XAXIS", 0, "X-Axis", "Left/Right"}, {1, "YAXIS", 0, "Y-Axis", "Front/Back"}, {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "AutoName by Axis"; diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index d642ee57c57..27c40095348 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -141,14 +141,14 @@ void ED_operatormacros_curve(void) wmOperatorTypeMacro *otmacro; ot = WM_operatortype_append_macro("CURVE_OT_duplicate_move", "Add Duplicate", "Duplicate curve and move", - OPTYPE_UNDO|OPTYPE_REGISTER); + OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "CURVE_OT_duplicate"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); RNA_boolean_set(otmacro->ptr, "mirror", FALSE); ot = WM_operatortype_append_macro("CURVE_OT_extrude_move", "Extrude Curve and Move", - "Extrude curve and move result", OPTYPE_UNDO|OPTYPE_REGISTER); + "Extrude curve and move result", OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "CURVE_OT_extrude"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); @@ -189,8 +189,8 @@ void ED_keymap_curve(wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", ENDKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_END); RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_CHAR); RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_CHAR); - RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", PREV_WORD); - RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", NEXT_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)->ptr, "type", PREV_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)->ptr, "type", NEXT_WORD); RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_LINE); RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_LINE); RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_PAGE); @@ -224,9 +224,9 @@ void ED_keymap_curve(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_all", AKEY, KM_PRESS, 0, 0); - RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); + RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); kmi = WM_keymap_add_item(keymap, "CURVE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); - RNA_enum_set(kmi->ptr, "action", SEL_INVERT); + RNA_enum_set(kmi->ptr, "action", SEL_INVERT); WM_keymap_add_item(keymap, "CURVE_OT_select_row", RKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CURVE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index b94d3653f60..2fa7b4b2126 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -3530,7 +3530,8 @@ void CURVE_OT_spline_type_set(wmOperatorType *ot) // {CU_CARDINAL, "CARDINAL", 0, "Cardinal", ""}, // {CU_BSPLINE, "B_SPLINE", 0, "B-Spline", ""}, {CU_NURBS, "NURBS", 0, "NURBS", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "Set Spline Type"; @@ -3573,7 +3574,8 @@ void CURVE_OT_handle_type_set(wmOperatorType *ot) {5, "ALIGNED", 0, "Aligned", ""}, {6, "FREE_ALIGN", 0, "Free", ""}, {3, "TOGGLE_FREE_ALIGN", 0, "Toggle Free/Align", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "Set Handle Type"; @@ -4886,7 +4888,8 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot) static EnumPropertyItem direction_items[] = { {0, "CYCLIC_U", 0, "Cyclic U", ""}, {1, "CYCLIC_V", 0, "Cyclic V", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "Toggle Cyclic"; @@ -6007,7 +6010,8 @@ void CURVE_OT_delete(wmOperatorType *ot) {0, "SELECTED", 0, "Select", ""}, {1, "SEGMENT", 0, "Segment", ""}, {2, "ALL", 0, "All", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "Delete"; @@ -6101,7 +6105,7 @@ int join_curve_exec(bContext *C, wmOperator *UNUSED(op)) /* trasnform all selected curves inverse in obact */ invert_m4_m4(imat, ob->obmat); - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases) { if (base->object->type == ob->type) { if (base->object != ob) { diff --git a/source/blender/editors/curve/lorem.c b/source/blender/editors/curve/lorem.c index 66b358e04e5..7823be3df6d 100644 --- a/source/blender/editors/curve/lorem.c +++ b/source/blender/editors/curve/lorem.c @@ -25,7 +25,7 @@ #include "curve_intern.h" -const char ED_lorem[]= { +const char ED_lorem[] = { 76, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 101, 114, 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 105, 116, 46, 32, 65, 108, 105, 113, 117, 97, 109, 32, 116, 114, 105, 115, 116, 105, 113, 117, 101, 32, 105, 110, 116, 101, 114, 100, 117, 109, 32, 115, 101, 109, 46, 32, 78, 117, 108, diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index fc6f406ab59..7f9a998e6d0 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -167,9 +167,9 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa) static void panels_collapse_all(ScrArea *sa, ARegion *ar) { Panel *pa; - int flag = ((panel_aligned(sa, ar)==BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY); + int flag = ((panel_aligned(sa, ar) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY); - for (pa= ar->panels.first; pa; pa= pa->next) { + for (pa = ar->panels.first; pa; pa = pa->next) { if (pa->type && !(pa->type->flag & PNL_NO_HEADER)) { pa->flag = flag; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 1a7fc98ef74..004c5306d65 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -162,9 +162,10 @@ static unsigned int scroll_circle_face[14][3] = { }; -static float menu_tria_vert[6][2]= { -{-0.33, 0.16}, {0.33, 0.16}, {0, 0.82}, -{0, -0.82}, {-0.33, -0.16}, {0.33, -0.16}}; +static float menu_tria_vert[6][2] = { + {-0.33, 0.16}, {0.33, 0.16}, {0, 0.82}, + {0, -0.82}, {-0.33, -0.16}, {0.33, -0.16} +}; @@ -1168,7 +1169,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b #if 0 ui_rasterpos_safe(x, y, but->aspect); - if (but->type == IDPOIN) transopts = 0; // no translation, of course! + if (but->type == IDPOIN) transopts = 0; // no translation, of course! else transopts = ui_translate_buttons(); #endif @@ -3133,7 +3134,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct if (but->drawflag & UI_BUT_DRAW_ENUM_ARROWS) wt = widget_type(UI_WTYPE_MENU_RADIO); /* with arrows */ else - wt = widget_type(UI_WTYPE_MENU_ICON_RADIO); /* no arrows */ + wt = widget_type(UI_WTYPE_MENU_ICON_RADIO); /* no arrows */ } /* with menu arrows */ else diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index f2ea81abcbf..2e70a941a54 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -783,8 +783,8 @@ void ui_theme_init_default(void) /* space nla */ btheme->tnla = btheme->tact; - rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as for dopesheet; duplicate here for easier reference */ - rgba_char_args_set(btheme->tnla.anim_non_active,153, 135, 97, 77); + rgba_char_args_set(btheme->tnla.anim_active, 204, 112, 26, 102); /* same as for dopesheet; duplicate here for easier reference */ + rgba_char_args_set(btheme->tnla.anim_non_active, 153, 135, 97, 77); rgba_char_args_set(btheme->tnla.nla_tweaking, 77, 243, 26, 77); rgba_char_args_set(btheme->tnla.nla_tweakdupli, 217, 0, 0, 255); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index cad6c23eb74..93ed7d37235 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4830,13 +4830,11 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) mdiff[1] = opdata->mcenter[1] - event->mval[1]; if (opdata->modify_depth) { - amount = opdata->old_depth + (len_v2(mdiff) - - opdata->initial_length) / opdata->initial_length; + amount = opdata->old_depth + (len_v2(mdiff) - opdata->initial_length) / opdata->initial_length; RNA_float_set(op->ptr, "depth", amount); } else { - amount = opdata->old_thickness - (len_v2(mdiff) - - opdata->initial_length) / opdata->initial_length; + amount = opdata->old_thickness - (len_v2(mdiff) - opdata->initial_length) / opdata->initial_length; amount = MAX2(amount, 0.0f); RNA_float_set(op->ptr, "thickness", amount); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 24dd56a4834..3d7dd01bf30 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -180,7 +180,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) short changed = 0; const int unselected = RNA_boolean_get(op->ptr, "unselected"); - CTX_DATA_BEGIN (C, Base *, base, visible_bases) + CTX_DATA_BEGIN(C, Base *, base, visible_bases) { if (!unselected) { if (base->flag & SELECT) { @@ -240,7 +240,7 @@ static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op)) short changed = 0; /* XXX need a context loop to handle such cases */ - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) { if (ob->restrictflag & OB_RESTRICT_RENDER) { ob->restrictflag &= ~OB_RESTRICT_RENDER; @@ -275,7 +275,7 @@ static int object_hide_render_set_exec(bContext *C, wmOperator *op) { const int unselected = RNA_boolean_get(op->ptr, "unselected"); - CTX_DATA_BEGIN (C, Base *, base, visible_bases) + CTX_DATA_BEGIN(C, Base *, base, visible_bases) { if (!unselected) { if (base->flag & SELECT) { @@ -1114,7 +1114,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene) ListBase targets = {NULL, NULL}; /* loop over objects in scene */ - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) { /* set flag to force recalc, then grab path(s) from object */ ob->avs.recalc |= ANIMVIZ_RECALC_PATHS; @@ -1157,7 +1157,7 @@ static int object_calculate_paths_exec(bContext *C, wmOperator *op) int end = RNA_int_get(op->ptr, "end_frame"); /* set up path data for bones being calculated */ - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) { bAnimVizSettings *avs = &ob->avs; @@ -1196,9 +1196,9 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot) /* properties */ RNA_def_int(ot->srna, "start_frame", 1, MINAFRAME, MAXFRAME, "Start", - "First frame to calculate object paths on", MINFRAME, MAXFRAME/2.0); + "First frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0); RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End", - "Last frame to calculate object paths on", MINFRAME, MAXFRAME/2.0); + "Last frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0); } /* --------- */ @@ -1231,7 +1231,7 @@ void OBJECT_OT_paths_update(wmOperatorType *ot) ot->poll = ED_operator_object_active_editable; /* TODO: this should probably check for existing paths */ /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* --------- */ @@ -1240,7 +1240,7 @@ void OBJECT_OT_paths_update(wmOperatorType *ot) void ED_objects_clear_paths(bContext *C) { /* loop over objects in scene */ - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) { if (ob->mpath) { animviz_free_motionpath(ob->mpath); @@ -1288,7 +1288,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) int clear = (strcmp(op->idname, "OBJECT_OT_shade_flat") == 0); int done = FALSE; - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects) { if (ob->type == OB_MESH) { @@ -1666,10 +1666,12 @@ static EnumPropertyItem game_properties_copy_operations[] = { {COPY_PROPERTIES_REPLACE, "REPLACE", 0, "Replace Properties", ""}, {COPY_PROPERTIES_MERGE, "MERGE", 0, "Merge Properties", ""}, {COPY_PROPERTIES_COPY, "COPY", 0, "Copy a Property", ""}, - {0, NULL, 0, NULL, NULL}}; + {0, NULL, 0, NULL, NULL} +}; -static EnumPropertyItem gameprops_items[]= { - {0, NULL, 0, NULL, NULL}}; +static EnumPropertyItem gameprops_items[] = { + {0, NULL, 0, NULL, NULL} +}; static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) { @@ -1706,7 +1708,7 @@ static int game_property_copy_exec(bContext *C, wmOperator *op) prop = BLI_findlink(&ob->prop, propid - 1); if (prop) { - CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { if (ob != ob_iter) set_ob_property(ob_iter, prop); @@ -1715,7 +1717,7 @@ static int game_property_copy_exec(bContext *C, wmOperator *op) } else { - CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { if (ob != ob_iter) { if (type == COPY_PROPERTIES_REPLACE) @@ -1756,7 +1758,7 @@ void OBJECT_OT_game_property_copy(wmOperatorType *ot) static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { free_properties(&ob_iter->prop); } @@ -1786,7 +1788,7 @@ static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_active_context(C); - CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { if (ob != ob_iter) { /* first: free all logic */ @@ -1843,7 +1845,7 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_active_context(C); - CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { if (ob != ob_iter) { ob_iter->gameflag = ob->gameflag; diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index f6e8ccf4ec9..0a9944debe1 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -344,18 +344,17 @@ int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int bp = findnearestLattvert(&vc, mval, 1); if (bp) { - if (extend) { - bp->f1 |= SELECT; - } - else if (deselect) { - bp->f1 &= ~SELECT; - } + if (extend) { + bp->f1 |= SELECT; + } + else if (deselect) { + bp->f1 &= ~SELECT; + } else if (toggle) { bp->f1 ^= SELECT; /* swap */ } - else - { - ED_setflagsLatt(vc.obedit, 0); + else { + ED_setflagsLatt(vc.obedit, 0); bp->f1 |= SELECT; } diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 24b37bb041f..3349a61cd86 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -577,7 +577,6 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) SpaceClipDrawContext *context = sc->draw_context; MovieClip *clip = ED_space_clip(sc); int need_rebind = 0; - short custom_start_frame = FALSE; context->last_texture = glaGetOneInteger(GL_TEXTURE_2D); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index d61dd862096..0cdd7f62c46 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1047,7 +1047,7 @@ static void clip_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0); + keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); keymap = WM_keymap_find(wm->defaultconf, "Clip", SPACE_CLIP, 0); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 6ca4ad15859..053dac71fe6 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -2099,7 +2099,7 @@ static struct PyMethodDef bpy_bmesh_methods[] = { {"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc}, {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc}, {"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc}, - {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_transform_doc}, + {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_transform_doc}, {NULL, NULL, 0, NULL} }; @@ -2141,7 +2141,7 @@ static struct PyMethodDef bpy_bmface_methods[] = { {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc}, {"copy_from_face_interp", (PyCFunction)bpy_bmface_copy_from_face_interp, METH_O, bpy_bmface_copy_from_face_interp_doc}, - {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS|METH_KEYWORDS, bpy_bmface_copy_doc}, + {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS | METH_KEYWORDS, bpy_bmface_copy_doc}, {"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc}, {"calc_perimeter", (PyCFunction)bpy_bmface_calc_perimeter, METH_NOARGS, bpy_bmface_calc_perimeter_doc}, diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index dc7b6dd6e8d..538c5493282 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -51,18 +51,15 @@ #define BRANCH_ARRAY 1024 #define NODE_ARRAY 4096 -typedef struct Branch -{ +typedef struct Branch { struct Branch *b[8]; } Branch; -typedef struct OcVal -{ +typedef struct OcVal { short ocx, ocy, ocz; } OcVal; -typedef struct Node -{ +typedef struct Node { struct RayFace *v[8]; struct OcVal ov[8]; struct Node *next; @@ -73,7 +70,7 @@ typedef struct Octree { struct Branch **adrbranch; struct Node **adrnode; - float ocsize; /* ocsize: mult factor, max size octree */ + float ocsize; /* ocsize: mult factor, max size octree */ float ocfacx, ocfacy, ocfacz; float min[3], max[3]; int ocres; @@ -121,8 +118,8 @@ static RayObjectAPI octree_api = /* **************** ocval method ******************* */ /* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */ -#define OCVALRES 15 -#define BROW16(min, max) (((max)>=OCVALRES? 0xFFFF: (1<<(max+1))-1) - ((min>0)? ((1<<(min))-1):0) ) +#define OCVALRES 15 +#define BROW16(min, max) (((max) >= OCVALRES ? 0xFFFF : (1 << (max + 1)) - 1) - ((min > 0) ? ((1 << (min)) - 1) : 0)) static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov) { @@ -137,17 +134,17 @@ static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, DO_MINMAX(v4, min, max); } - ocmin= OCVALRES*(min[0]-x); - ocmax= OCVALRES*(max[0]-x); - ov->ocx= BROW16(ocmin, ocmax); - - ocmin= OCVALRES*(min[1]-y); - ocmax= OCVALRES*(max[1]-y); - ov->ocy= BROW16(ocmin, ocmax); - - ocmin= OCVALRES*(min[2]-z); - ocmax= OCVALRES*(max[2]-z); - ov->ocz= BROW16(ocmin, ocmax); + ocmin = OCVALRES * (min[0] - x); + ocmax = OCVALRES * (max[0] - x); + ov->ocx = BROW16(ocmin, ocmax); + + ocmin = OCVALRES * (min[1] - y); + ocmax = OCVALRES * (max[1] - y); + ov->ocy = BROW16(ocmin, ocmax); + + ocmin = OCVALRES * (min[2] - z); + ocmax = OCVALRES * (max[2] - z); + ov->ocz = BROW16(ocmin, ocmax); } @@ -155,35 +152,35 @@ static void calc_ocval_ray(OcVal *ov, float xo, float yo, float zo, float *vec1, { int ocmin, ocmax; - if (vec1[0]ocx= BROW16(ocmin, ocmax); + ov->ocx = BROW16(ocmin, ocmax); - if (vec1[1]ocy= BROW16(ocmin, ocmax); + ov->ocy = BROW16(ocmin, ocmax); - if (vec1[2]ocz= BROW16(ocmin, ocmax); + ov->ocz = BROW16(ocmin, ocmax); } /* ************* octree ************** */ @@ -195,17 +192,17 @@ static Branch *addbranch(Octree *oc, Branch *br, short ocb) if (br->b[ocb]) return br->b[ocb]; oc->branchcount++; - index= oc->branchcount>>12; + index = oc->branchcount >> 12; - if (oc->adrbranch[index]==NULL) - oc->adrbranch[index]= (Branch*)MEM_callocN(4096*sizeof(Branch), "new oc branch"); + if (oc->adrbranch[index] == NULL) + oc->adrbranch[index] = (Branch *)MEM_callocN(4096 * sizeof(Branch), "new oc branch"); - if (oc->branchcount>= BRANCH_ARRAY*4096) { + if (oc->branchcount >= BRANCH_ARRAY * 4096) { printf("error; octree branches full\n"); - oc->branchcount=0; + oc->branchcount = 0; } - return br->b[ocb]= oc->adrbranch[index]+(oc->branchcount & 4095); + return br->b[ocb] = oc->adrbranch[index] + (oc->branchcount & 4095); } static Node *addnode(Octree *oc) @@ -213,17 +210,17 @@ static Node *addnode(Octree *oc) int index; oc->nodecount++; - index= oc->nodecount>>12; + index = oc->nodecount >> 12; - if (oc->adrnode[index]==NULL) - oc->adrnode[index]= (Node*)MEM_callocN(4096*sizeof(Node), "addnode"); + if (oc->adrnode[index] == NULL) + oc->adrnode[index] = (Node *)MEM_callocN(4096 * sizeof(Node), "addnode"); - if (oc->nodecount> NODE_ARRAY*NODE_ARRAY) { + if (oc->nodecount > NODE_ARRAY * NODE_ARRAY) { printf("error; octree nodes full\n"); - oc->nodecount=0; + oc->nodecount = 0; } - return oc->adrnode[index]+(oc->nodecount & 4095); + return oc->adrnode[index] + (oc->nodecount & 4095); } static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3]) @@ -234,33 +231,33 @@ static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3] // init static vars if (face) { normal_tri_v3(nor, rtf[0], rtf[1], rtf[2]); - d= -nor[0]*rtf[0][0] - nor[1]*rtf[0][1] - nor[2]*rtf[0][2]; + d = -nor[0] * rtf[0][0] - nor[1] * rtf[0][1] - nor[2] * rtf[0][2]; return 0; } - fx= x; - fy= y; - fz= z; - - if ((fx)*nor[0] + (fy)*nor[1] + (fz)*nor[2] + d > 0.0f) { - if ((fx+1)*nor[0] + (fy )*nor[1] + (fz )*nor[2] + d < 0.0f) return 1; - if ((fx )*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d < 0.0f) return 1; - if ((fx+1)*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d < 0.0f) return 1; - - if ((fx )*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1; - if ((fx+1)*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1; - if ((fx )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1; - if ((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1; + fx = x; + fy = y; + fz = z; + + if ((fx) * nor[0] + (fy) * nor[1] + (fz) * nor[2] + d > 0.0f) { + if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz ) * nor[2] + d < 0.0f) return 1; + if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d < 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d < 0.0f) return 1; + + if ((fx ) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; + if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d < 0.0f) return 1; } else { - if ((fx+1)*nor[0] + (fy )*nor[1] + (fz )*nor[2] + d > 0.0f) return 1; - if ((fx )*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d > 0.0f) return 1; - if ((fx+1)*nor[0] + (fy+1)*nor[1] + (fz )*nor[2] + d > 0.0f) return 1; - - if ((fx )*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1; - if ((fx+1)*nor[0] + (fy )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1; - if ((fx )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1; - if ((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz ) * nor[2] + d > 0.0f) return 1; + if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d > 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz ) * nor[2] + d > 0.0f) return 1; + + if ((fx ) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy ) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; + if ((fx ) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; + if ((fx + 1) * nor[0] + (fy + 1) * nor[1] + (fz + 1) * nor[2] + d > 0.0f) return 1; } return 0; @@ -272,163 +269,163 @@ static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short Node *no; short a, oc0, oc1, oc2, oc3, oc4, oc5; - x<<=2; - y<<=1; + x <<= 2; + y <<= 1; - br= oc->adrbranch[0]; + br = oc->adrbranch[0]; - if (oc->ocres==512) { - oc0= ((x & 1024)+(y & 512)+(z & 256))>>8; - br= addbranch(oc, br, oc0); + if (oc->ocres == 512) { + oc0 = ((x & 1024) + (y & 512) + (z & 256)) >> 8; + br = addbranch(oc, br, oc0); } - if (oc->ocres>=256) { - oc0= ((x & 512)+(y & 256)+(z & 128))>>7; - br= addbranch(oc, br, oc0); + if (oc->ocres >= 256) { + oc0 = ((x & 512) + (y & 256) + (z & 128)) >> 7; + br = addbranch(oc, br, oc0); } - if (oc->ocres>=128) { - oc0= ((x & 256)+(y & 128)+(z & 64))>>6; - br= addbranch(oc, br, oc0); + if (oc->ocres >= 128) { + oc0 = ((x & 256) + (y & 128) + (z & 64)) >> 6; + br = addbranch(oc, br, oc0); } - oc0= ((x & 128)+(y & 64)+(z & 32))>>5; - oc1= ((x & 64)+(y & 32)+(z & 16))>>4; - oc2= ((x & 32)+(y & 16)+(z & 8))>>3; - oc3= ((x & 16)+(y & 8)+(z & 4))>>2; - oc4= ((x & 8)+(y & 4)+(z & 2))>>1; - oc5= ((x & 4)+(y & 2)+(z & 1)); - - br= addbranch(oc, br, oc0); - br= addbranch(oc, br, oc1); - br= addbranch(oc, br, oc2); - br= addbranch(oc, br, oc3); - br= addbranch(oc, br, oc4); - no= (Node *)br->b[oc5]; - if (no==NULL) br->b[oc5]= (Branch *)(no= addnode(oc)); + oc0 = ((x & 128) + (y & 64) + (z & 32)) >> 5; + oc1 = ((x & 64) + (y & 32) + (z & 16)) >> 4; + oc2 = ((x & 32) + (y & 16) + (z & 8)) >> 3; + oc3 = ((x & 16) + (y & 8) + (z & 4)) >> 2; + oc4 = ((x & 8) + (y & 4) + (z & 2)) >> 1; + oc5 = ((x & 4) + (y & 2) + (z & 1)); + + br = addbranch(oc, br, oc0); + br = addbranch(oc, br, oc1); + br = addbranch(oc, br, oc2); + br = addbranch(oc, br, oc3); + br = addbranch(oc, br, oc4); + no = (Node *)br->b[oc5]; + if (no == NULL) br->b[oc5] = (Branch *)(no = addnode(oc)); while (no->next) no = no->next; - a= 0; - if (no->v[7]) { /* node full */ - no->next= addnode(oc); - no= no->next; + a = 0; + if (no->v[7]) { /* node full */ + no->next = addnode(oc); + no = no->next; } else { while (no->v[a] != NULL) a++; } - no->v[a]= (RayFace*) RE_rayobject_align(face); + no->v[a] = (RayFace *) RE_rayobject_align(face); if (quad) - calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]); + calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x >> 2, y >> 1, z, &no->ov[a]); else - calc_ocval_face(rtf[0], rtf[1], rtf[2], NULL, x>>2, y>>1, z, &no->ov[a]); + calc_ocval_face(rtf[0], rtf[1], rtf[2], NULL, x >> 2, y >> 1, z, &no->ov[a]); } static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocface, short rts[][3], float rtf[][3]) { int ocx1, ocx2, ocy1, ocy2; - int x, y, dx=0, dy=0; + int x, y, dx = 0, dy = 0; float ox1, ox2, oy1, oy2; float labda, labdao, labdax, labday, ldx, ldy; - ocx1= rts[b1][c1]; - ocy1= rts[b1][c2]; - ocx2= rts[b2][c1]; - ocy2= rts[b2][c2]; + ocx1 = rts[b1][c1]; + ocy1 = rts[b1][c2]; + ocx2 = rts[b2][c1]; + ocy2 = rts[b2][c2]; - if (ocx1==ocx2 && ocy1==ocy2) { - ocface[oc->ocres*ocx1+ocy1]= 1; + if (ocx1 == ocx2 && ocy1 == ocy2) { + ocface[oc->ocres * ocx1 + ocy1] = 1; return; } - ox1= rtf[b1][c1]; - oy1= rtf[b1][c2]; - ox2= rtf[b2][c1]; - oy2= rtf[b2][c2]; + ox1 = rtf[b1][c1]; + oy1 = rtf[b1][c2]; + ox2 = rtf[b2][c1]; + oy2 = rtf[b2][c2]; - if (ox1!=ox2) { - if (ox2-ox1>0.0f) { - labdax= (ox1-ocx1-1.0f)/(ox1-ox2); - ldx= -1.0f/(ox1-ox2); - dx= 1; + if (ox1 != ox2) { + if (ox2 - ox1 > 0.0f) { + labdax = (ox1 - ocx1 - 1.0f) / (ox1 - ox2); + ldx = -1.0f / (ox1 - ox2); + dx = 1; } else { - labdax= (ox1-ocx1)/(ox1-ox2); - ldx= 1.0f/(ox1-ox2); - dx= -1; + labdax = (ox1 - ocx1) / (ox1 - ox2); + ldx = 1.0f / (ox1 - ox2); + dx = -1; } } else { - labdax=1.0f; - ldx=0; + labdax = 1.0f; + ldx = 0; } - if (oy1!=oy2) { - if (oy2-oy1>0.0f) { - labday= (oy1-ocy1-1.0f)/(oy1-oy2); - ldy= -1.0f/(oy1-oy2); - dy= 1; + if (oy1 != oy2) { + if (oy2 - oy1 > 0.0f) { + labday = (oy1 - ocy1 - 1.0f) / (oy1 - oy2); + ldy = -1.0f / (oy1 - oy2); + dy = 1; } else { - labday= (oy1-ocy1)/(oy1-oy2); - ldy= 1.0f/(oy1-oy2); - dy= -1; + labday = (oy1 - ocy1) / (oy1 - oy2); + ldy = 1.0f / (oy1 - oy2); + dy = -1; } } else { - labday=1.0f; - ldy=0; + labday = 1.0f; + ldy = 0; } - x=ocx1; y=ocy1; - labda= MIN2(labdax, labday); + x = ocx1; y = ocy1; + labda = MIN2(labdax, labday); while (TRUE) { - if (x<0 || y<0 || x>=oc->ocres || y>=oc->ocres); - else ocface[oc->ocres*x+y]= 1; + if (x < 0 || y < 0 || x >= oc->ocres || y >= oc->ocres) ; + else ocface[oc->ocres * x + y] = 1; - labdao=labda; - if (labdax==labday) { - labdax+=ldx; - x+=dx; - labday+=ldy; - y+=dy; + labdao = labda; + if (labdax == labday) { + labdax += ldx; + x += dx; + labday += ldy; + y += dy; } else { - if (labdax=1.0f) break; + labda = MIN2(labdax, labday); + if (labda == labdao) break; + if (labda >= 1.0f) break; } - ocface[oc->ocres*ocx2+ocy2]=1; + ocface[oc->ocres * ocx2 + ocy2] = 1; } static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin, short *ocmax) { int a, x, y, y1, y2; - for (x=ocmin[c1];x<=ocmax[c1];x++) { - a= oc->ocres*x; - for (y=ocmin[c2];y<=ocmax[c2];y++) { - if (ocface[a+y]) { + for (x = ocmin[c1]; x <= ocmax[c1]; x++) { + a = oc->ocres * x; + for (y = ocmin[c2]; y <= ocmax[c2]; y++) { + if (ocface[a + y]) { y++; - while (ocface[a+y] && y!=ocmax[c2]) y++; - for (y1=ocmax[c2];y1>y;y1--) { - if (ocface[a+y1]) { - for (y2=y;y2<=y1;y2++) ocface[a+y2]=1; - y1=0; + while (ocface[a + y] && y != ocmax[c2]) y++; + for (y1 = ocmax[c2]; y1 > y; y1--) { + if (ocface[a + y1]) { + for (y2 = y; y2 <= y1; y2++) ocface[a + y2] = 1; + y1 = 0; } } - y=ocmax[c2]; + y = ocmax[c2]; } } } @@ -436,7 +433,7 @@ static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *oc static void RE_rayobject_octree_free(RayObject *tree) { - Octree *oc= (Octree*)tree; + Octree *oc = (Octree *)tree; #if 0 printf("branches %d nodes %d\n", oc->branchcount, oc->nodecount); @@ -448,28 +445,28 @@ static void RE_rayobject_octree_free(RayObject *tree) MEM_freeN(oc->ocface); if (oc->adrbranch) { - int a= 0; + int a = 0; while (oc->adrbranch[a]) { MEM_freeN(oc->adrbranch[a]); - oc->adrbranch[a]= NULL; + oc->adrbranch[a] = NULL; a++; } MEM_freeN(oc->adrbranch); - oc->adrbranch= NULL; + oc->adrbranch = NULL; } - oc->branchcount= 0; + oc->branchcount = 0; if (oc->adrnode) { - int a= 0; + int a = 0; while (oc->adrnode[a]) { MEM_freeN(oc->adrnode[a]); - oc->adrnode[a]= NULL; + oc->adrnode[a] = NULL; a++; } MEM_freeN(oc->adrnode); - oc->adrnode= NULL; + oc->adrnode = NULL; } - oc->nodecount= 0; + oc->nodecount = 0; MEM_freeN(oc); } @@ -477,29 +474,29 @@ static void RE_rayobject_octree_free(RayObject *tree) RayObject *RE_rayobject_octree_create(int ocres, int size) { - Octree *oc= (Octree*)MEM_callocN(sizeof(Octree), "Octree"); - assert( RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */ + Octree *oc = (Octree *)MEM_callocN(sizeof(Octree), "Octree"); + assert(RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */ oc->rayobj.api = &octree_api; oc->ocres = ocres; - oc->ro_nodes = (RayFace**)MEM_callocN(sizeof(RayFace*)*size, "octree rayobject nodes"); + oc->ro_nodes = (RayFace **)MEM_callocN(sizeof(RayFace *) * size, "octree rayobject nodes"); oc->ro_nodes_size = size; oc->ro_nodes_used = 0; - return RE_rayobject_unalignRayAPI((RayObject*) oc); + return RE_rayobject_unalignRayAPI((RayObject *) oc); } static void RE_rayobject_octree_add(RayObject *tree, RayObject *node) { - Octree *oc = (Octree*)tree; + Octree *oc = (Octree *)tree; - assert( RE_rayobject_isRayFace(node) ); - assert( oc->ro_nodes_used < oc->ro_nodes_size ); - oc->ro_nodes[ oc->ro_nodes_used++ ] = (RayFace*)RE_rayobject_align(node); + assert(RE_rayobject_isRayFace(node) ); + assert(oc->ro_nodes_used < oc->ro_nodes_size); + oc->ro_nodes[oc->ro_nodes_used++] = (RayFace *)RE_rayobject_align(node); } static void octree_fill_rayface(Octree *oc, RayFace *face) @@ -508,14 +505,14 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) float co1[3], co2[3], co3[3], co4[3]; short rts[4][3]; short ocmin[3], ocmax[3]; - char *ocface= oc->ocface; // front, top, size view of face, to fill in + char *ocface = oc->ocface; // front, top, size view of face, to fill in int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2; - ocfac[0]= oc->ocfacx; - ocfac[1]= oc->ocfacy; - ocfac[2]= oc->ocfacz; + ocfac[0] = oc->ocfacx; + ocfac[1] = oc->ocfacy; + ocfac[2] = oc->ocfacz; - ocres2= oc->ocres*oc->ocres; + ocres2 = oc->ocres * oc->ocres; copy_v3_v3(co1, face->v1); copy_v3_v3(co2, face->v2); @@ -523,7 +520,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) if (face->v4) copy_v3_v3(co4, face->v4); - for (c=0;c<3;c++) { + for (c = 0; c < 3; c++) { rtf[0][c] = (co1[c] - oc->min[c]) * ocfac[c]; rts[0][c] = (short)rtf[0][c]; rtf[1][c] = (co2[c] - oc->min[c]) * ocfac[c]; @@ -536,62 +533,62 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) } } - for (c=0;c<3;c++) { - oc1= rts[0][c]; - oc2= rts[1][c]; - oc3= rts[2][c]; + for (c = 0; c < 3; c++) { + oc1 = rts[0][c]; + oc2 = rts[1][c]; + oc3 = rts[2][c]; if (!RE_rayface_isQuad(face)) { - ocmin[c]= MIN3(oc1, oc2, oc3); - ocmax[c]= MAX3(oc1, oc2, oc3); + ocmin[c] = MIN3(oc1, oc2, oc3); + ocmax[c] = MAX3(oc1, oc2, oc3); } else { - oc4= rts[3][c]; - ocmin[c]= MIN4(oc1, oc2, oc3, oc4); - ocmax[c]= MAX4(oc1, oc2, oc3, oc4); + oc4 = rts[3][c]; + ocmin[c] = MIN4(oc1, oc2, oc3, oc4); + ocmax[c] = MAX4(oc1, oc2, oc3, oc4); } - if (ocmax[c]>oc->ocres-1) ocmax[c]=oc->ocres-1; - if (ocmin[c]<0) ocmin[c]=0; + if (ocmax[c] > oc->ocres - 1) ocmax[c] = oc->ocres - 1; + if (ocmin[c] < 0) ocmin[c] = 0; } - if (ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) { + if (ocmin[0] == ocmax[0] && ocmin[1] == ocmax[1] && ocmin[2] == ocmax[2]) { ocwrite(oc, face, RE_rayface_isQuad(face), ocmin[0], ocmin[1], ocmin[2], rtf); } else { - d2dda(oc, 0, 1, 0, 1, ocface+ocres2, rts, rtf); + d2dda(oc, 0, 1, 0, 1, ocface + ocres2, rts, rtf); d2dda(oc, 0, 1, 0, 2, ocface, rts, rtf); - d2dda(oc, 0, 1, 1, 2, ocface+2*ocres2, rts, rtf); - d2dda(oc, 1, 2, 0, 1, ocface+ocres2, rts, rtf); + d2dda(oc, 0, 1, 1, 2, ocface + 2 * ocres2, rts, rtf); + d2dda(oc, 1, 2, 0, 1, ocface + ocres2, rts, rtf); d2dda(oc, 1, 2, 0, 2, ocface, rts, rtf); - d2dda(oc, 1, 2, 1, 2, ocface+2*ocres2, rts, rtf); + d2dda(oc, 1, 2, 1, 2, ocface + 2 * ocres2, rts, rtf); if (!RE_rayface_isQuad(face)) { - d2dda(oc, 2, 0, 0, 1, ocface+ocres2, rts, rtf); + d2dda(oc, 2, 0, 0, 1, ocface + ocres2, rts, rtf); d2dda(oc, 2, 0, 0, 2, ocface, rts, rtf); - d2dda(oc, 2, 0, 1, 2, ocface+2*ocres2, rts, rtf); + d2dda(oc, 2, 0, 1, 2, ocface + 2 * ocres2, rts, rtf); } else { - d2dda(oc, 2, 3, 0, 1, ocface+ocres2, rts, rtf); + d2dda(oc, 2, 3, 0, 1, ocface + ocres2, rts, rtf); d2dda(oc, 2, 3, 0, 2, ocface, rts, rtf); - d2dda(oc, 2, 3, 1, 2, ocface+2*ocres2, rts, rtf); - d2dda(oc, 3, 0, 0, 1, ocface+ocres2, rts, rtf); + d2dda(oc, 2, 3, 1, 2, ocface + 2 * ocres2, rts, rtf); + d2dda(oc, 3, 0, 0, 1, ocface + ocres2, rts, rtf); d2dda(oc, 3, 0, 0, 2, ocface, rts, rtf); - d2dda(oc, 3, 0, 1, 2, ocface+2*ocres2, rts, rtf); + d2dda(oc, 3, 0, 1, 2, ocface + 2 * ocres2, rts, rtf); } /* nothing todo with triangle..., just fills :) */ - filltriangle(oc, 0, 1, ocface+ocres2, ocmin, ocmax); + filltriangle(oc, 0, 1, ocface + ocres2, ocmin, ocmax); filltriangle(oc, 0, 2, ocface, ocmin, ocmax); - filltriangle(oc, 1, 2, ocface+2*ocres2, ocmin, ocmax); + filltriangle(oc, 1, 2, ocface + 2 * ocres2, ocmin, ocmax); /* init static vars here */ face_in_node(face, 0, 0, 0, rtf); - for (x=ocmin[0];x<=ocmax[0];x++) { - a= oc->ocres*x; - for (y=ocmin[1];y<=ocmax[1];y++) { - if (ocface[a+y+ocres2]) { - b= oc->ocres*y+2*ocres2; - for (z=ocmin[2];z<=ocmax[2];z++) { - if (ocface[b+z] && ocface[a+z]) { + for (x = ocmin[0]; x <= ocmax[0]; x++) { + a = oc->ocres * x; + for (y = ocmin[1]; y <= ocmax[1]; y++) { + if (ocface[a + y + ocres2]) { + b = oc->ocres * y + 2 * ocres2; + for (z = ocmin[2]; z <= ocmax[2]; z++) { + if (ocface[b + z] && ocface[a + z]) { if (face_in_node(NULL, x, y, z, rtf)) ocwrite(oc, face, RE_rayface_isQuad(face), x, y, z, rtf); } @@ -601,18 +598,18 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) } /* same loops to clear octree, doubt it can be done smarter */ - for (x=ocmin[0];x<=ocmax[0];x++) { - a= oc->ocres*x; - for (y=ocmin[1];y<=ocmax[1];y++) { + for (x = ocmin[0]; x <= ocmax[0]; x++) { + a = oc->ocres * x; + for (y = ocmin[1]; y <= ocmax[1]; y++) { /* x-y */ - ocface[a+y+ocres2]= 0; + ocface[a + y + ocres2] = 0; - b= oc->ocres*y + 2*ocres2; - for (z=ocmin[2];z<=ocmax[2];z++) { + b = oc->ocres * y + 2 * ocres2; + for (z = ocmin[2]; z <= ocmax[2]; z++) { /* y-z */ - ocface[b+z]= 0; + ocface[b + z] = 0; /* x-z */ - ocface[a+z]= 0; + ocface[a + z] = 0; } } } @@ -621,44 +618,44 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) static void RE_rayobject_octree_done(RayObject *tree) { - Octree *oc = (Octree*)tree; + Octree *oc = (Octree *)tree; int c; float t00, t01, t02; - int ocres2 = oc->ocres*oc->ocres; + int ocres2 = oc->ocres * oc->ocres; INIT_MINMAX(oc->min, oc->max); /* Calculate Bounding Box */ - for (c=0; cro_nodes_used; c++) - RE_rayobject_merge_bb( RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max); + for (c = 0; c < oc->ro_nodes_used; c++) + RE_rayobject_merge_bb(RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max); /* Alloc memory */ - oc->adrbranch= (Branch**)MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); - oc->adrnode= (Node**)MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes"); + oc->adrbranch = (Branch **)MEM_callocN(sizeof(void *) * BRANCH_ARRAY, "octree branches"); + oc->adrnode = (Node **)MEM_callocN(sizeof(void *) * NODE_ARRAY, "octree nodes"); - oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree"); + oc->adrbranch[0] = (Branch *)MEM_callocN(4096 * sizeof(Branch), "makeoctree"); /* the lookup table, per face, for which nodes to fill in */ - oc->ocface= (char*)MEM_callocN( 3*ocres2 + 8, "ocface"); - memset(oc->ocface, 0, 3*ocres2); + oc->ocface = (char *)MEM_callocN(3 * ocres2 + 8, "ocface"); + memset(oc->ocface, 0, 3 * ocres2); - for (c=0;c<3;c++) { /* octree enlarge, still needed? */ - oc->min[c]-= 0.01f; - oc->max[c]+= 0.01f; + for (c = 0; c < 3; c++) { /* octree enlarge, still needed? */ + oc->min[c] -= 0.01f; + oc->max[c] += 0.01f; } - t00= oc->max[0]-oc->min[0]; - t01= oc->max[1]-oc->min[1]; - t02= oc->max[2]-oc->min[2]; + t00 = oc->max[0] - oc->min[0]; + t01 = oc->max[1] - oc->min[1]; + t02 = oc->max[2] - oc->min[2]; /* this minus 0.1 is old safety... seems to be needed? */ - oc->ocfacx= (oc->ocres-0.1)/t00; - oc->ocfacy= (oc->ocres-0.1)/t01; - oc->ocfacz= (oc->ocres-0.1)/t02; + oc->ocfacx = (oc->ocres - 0.1) / t00; + oc->ocfacy = (oc->ocres - 0.1) / t01; + oc->ocfacz = (oc->ocres - 0.1) / t02; - oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */ + oc->ocsize = sqrt(t00 * t00 + t01 * t01 + t02 * t02); /* global, max size octree */ - for (c=0; cro_nodes_used; c++) { + for (c = 0; c < oc->ro_nodes_used; c++) { octree_fill_rayface(oc, oc->ro_nodes[c]); } @@ -667,14 +664,14 @@ static void RE_rayobject_octree_done(RayObject *tree) MEM_freeN(oc->ro_nodes); oc->ro_nodes = NULL; - printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx ); - printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy ); - printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz ); + printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx); + printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy); + printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz); } static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max) { - Octree *oc = (Octree*)tree; + Octree *oc = (Octree *)tree; DO_MINMAX(oc->min, min, max); DO_MINMAX(oc->max, min, max); } @@ -687,7 +684,7 @@ static int testnode(Octree *UNUSED(oc), Isect *is, Node *no, OcVal ocval) /* return on any first hit */ if (is->mode == RE_RAY_SHADOW) { - for ( ; no; no = no->next) { + for (; no; no = no->next) { for (nr = 0; nr < 8; nr++) { RayFace *face = no->v[nr]; OcVal *ov = no->ov + nr; @@ -695,7 +692,7 @@ static int testnode(Octree *UNUSED(oc), Isect *is, Node *no, OcVal ocval) if (!face) break; if ( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if ( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face), is) ) + if (RE_rayobject_intersect(RE_rayobject_unalignRayFace(face), is) ) return 1; } } @@ -703,9 +700,9 @@ static int testnode(Octree *UNUSED(oc), Isect *is, Node *no, OcVal ocval) } else { /* else mirror or glass or shadowtra, return closest face */ - int found= 0; + int found = 0; - for ( ; no; no = no->next) { + for (; no; no = no->next) { for (nr = 0; nr < 8; nr++) { RayFace *face = no->v[nr]; OcVal *ov = no->ov + nr; @@ -713,7 +710,7 @@ static int testnode(Octree *UNUSED(oc), Isect *is, Node *no, OcVal ocval) if (!face) break; if ( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if ( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face), is) ) { + if (RE_rayobject_intersect(RE_rayobject_unalignRayFace(face), is) ) { found = 1; } } @@ -732,49 +729,49 @@ static Node *ocread(Octree *oc, int x, int y, int z) Branch *br; int oc1; - x<<=2; - y<<=1; + x <<= 2; + y <<= 1; - br= oc->adrbranch[0]; + br = oc->adrbranch[0]; - if (oc->ocres==512) { - oc1= ((x & 1024)+(y & 512)+(z & 256))>>8; - br= br->b[oc1]; - if (br==NULL) { + if (oc->ocres == 512) { + oc1 = ((x & 1024) + (y & 512) + (z & 256)) >> 8; + br = br->b[oc1]; + if (br == NULL) { return NULL; } } - if (oc->ocres>=256) { - oc1= ((x & 512)+(y & 256)+(z & 128))>>7; - br= br->b[oc1]; - if (br==NULL) { + if (oc->ocres >= 256) { + oc1 = ((x & 512) + (y & 256) + (z & 128)) >> 7; + br = br->b[oc1]; + if (br == NULL) { return NULL; } } - if (oc->ocres>=128) { - oc1= ((x & 256)+(y & 128)+(z & 64))>>6; - br= br->b[oc1]; - if (br==NULL) { + if (oc->ocres >= 128) { + oc1 = ((x & 256) + (y & 128) + (z & 64)) >> 6; + br = br->b[oc1]; + if (br == NULL) { return NULL; } } - oc1= ((x & 128)+(y & 64)+(z & 32))>>5; - br= br->b[oc1]; + oc1 = ((x & 128) + (y & 64) + (z & 32)) >> 5; + br = br->b[oc1]; if (br) { - oc1= ((x & 64)+(y & 32)+(z & 16))>>4; - br= br->b[oc1]; + oc1 = ((x & 64) + (y & 32) + (z & 16)) >> 4; + br = br->b[oc1]; if (br) { - oc1= ((x & 32)+(y & 16)+(z & 8))>>3; - br= br->b[oc1]; + oc1 = ((x & 32) + (y & 16) + (z & 8)) >> 3; + br = br->b[oc1]; if (br) { - oc1= ((x & 16)+(y & 8)+(z & 4))>>2; - br= br->b[oc1]; + oc1 = ((x & 16) + (y & 8) + (z & 4)) >> 2; + br = br->b[oc1]; if (br) { - oc1= ((x & 8)+(y & 4)+(z & 2))>>1; - br= br->b[oc1]; + oc1 = ((x & 8) + (y & 4) + (z & 2)) >> 1; + br = br->b[oc1]; if (br) { - oc1= ((x & 4)+(y & 2)+(z & 1)); + oc1 = ((x & 4) + (y & 2) + (z & 1)); return (Node *)br->b[oc1]; } } @@ -789,24 +786,24 @@ static int cliptest(float p, float q, float *u1, float *u2) { float r; - if (p<0.0f) { - if (q*u2) return 0; - else if (r>*u1) *u1=r; + if (p < 0.0f) { + if (q < p) return 0; + else if (q < 0.0f) { + r = q / p; + if (r > *u2) return 0; + else if (r > *u1) *u1 = r; } } else { - if (p>0.0f) { - if (q<0.0f) return 0; - else if (q 0.0f) { + if (q < 0.0f) return 0; + else if (q < p) { + r = q / p; + if (r < *u1) return 0; + else if (r < *u2) *u2 = r; } } - else if (q<0.0f) return 0; + else if (q < 0.0f) return 0; } return 1; } @@ -816,16 +813,16 @@ static int cliptest(float p, float q, float *u1, float *u2) #if 0 -in top: static int coh_nodes[16*16*16][6]; -in makeoctree: memset(coh_nodes, 0, sizeof(coh_nodes)); +in top : static int coh_nodes[16 * 16 * 16][6]; +in makeoctree : memset(coh_nodes, 0, sizeof(coh_nodes)); static void add_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2) { short *sp; - sp= coh_nodes[ (ocx2 & 15) + 16*(ocy2 & 15) + 256*(ocz2 & 15) ]; - sp[0]= ocx1; sp[1]= ocy1; sp[2]= ocz1; - sp[3]= ocx2; sp[4]= ocy2; sp[5]= ocz2; + sp = coh_nodes[(ocx2 & 15) + 16 * (ocy2 & 15) + 256 * (ocz2 & 15)]; + sp[0] = ocx1; sp[1] = ocy1; sp[2] = ocz1; + sp[3] = ocx2; sp[4] = ocy2; sp[5] = ocz2; } @@ -833,9 +830,9 @@ static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, i { short *sp; - sp= coh_nodes[ (ocx2 & 15) + 16*(ocy2 & 15) + 256*(ocz2 & 15) ]; - if (sp[0]==ocx1 && sp[1]==ocy1 && sp[2]==ocz1 && - sp[3]==ocx2 && sp[4]==ocy2 && sp[5]==ocz2) return 1; + sp = coh_nodes[(ocx2 & 15) + 16 * (ocy2 & 15) + 256 * (ocz2 & 15)]; + if (sp[0] == ocx1 && sp[1] == ocy1 && sp[2] == ocz1 && + sp[3] == ocx2 && sp[4] == ocy2 && sp[5] == ocz2) return 1; return 0; } @@ -845,7 +842,7 @@ static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, i /* starts with is->orig.face */ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) { - Octree *oc= (Octree*)tree; + Octree *oc = (Octree *)tree; Node *no; OcVal ocval; float vec1[3], vec2[3], start[3], end[3]; @@ -853,47 +850,47 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) float labdao, labdax, ldx, labday, ldy, labdaz, ldz, ddalabda; float olabda = 0; int dx, dy, dz; - int xo, yo, zo, c1=0; + int xo, yo, zo, c1 = 0; int ocx1, ocx2, ocy1, ocy2, ocz1, ocz2; /* clip with octree */ - if (oc->branchcount==0) return 0; + if (oc->branchcount == 0) return 0; /* do this before intersect calls */ #if 0 - is->facecontr= NULL; /* to check shared edge */ - is->obcontr= 0; - is->faceisect= is->isect= 0; /* shared edge, quad half flag */ - is->userdata= oc->userdata; + is->facecontr = NULL; /* to check shared edge */ + is->obcontr = 0; + is->faceisect = is->isect = 0; /* shared edge, quad half flag */ + is->userdata = oc->userdata; #endif - copy_v3_v3( start, is->start ); - madd_v3_v3v3fl( end, is->start, is->dir, is->dist ); - ldx= is->dir[0]*is->dist; + copy_v3_v3(start, is->start); + madd_v3_v3v3fl(end, is->start, is->dir, is->dist); + ldx = is->dir[0] * is->dist; olabda = is->dist; - u1= 0.0f; - u2= 1.0f; + u1 = 0.0f; + u2 = 1.0f; /* clip with octree cube */ - if (cliptest(-ldx, start[0]-oc->min[0], &u1, &u2)) { - if (cliptest(ldx, oc->max[0]-start[0], &u1, &u2)) { - ldy= is->dir[1]*is->dist; - if (cliptest(-ldy, start[1]-oc->min[1], &u1, &u2)) { - if (cliptest(ldy, oc->max[1]-start[1], &u1, &u2)) { - ldz = is->dir[2]*is->dist; - if (cliptest(-ldz, start[2]-oc->min[2], &u1, &u2)) { - if (cliptest(ldz, oc->max[2]-start[2], &u1, &u2)) { - c1=1; - if (u2<1.0f) { - end[0] = start[0]+u2*ldx; - end[1] = start[1]+u2*ldy; - end[2] = start[2]+u2*ldz; + if (cliptest(-ldx, start[0] - oc->min[0], &u1, &u2)) { + if (cliptest(ldx, oc->max[0] - start[0], &u1, &u2)) { + ldy = is->dir[1] * is->dist; + if (cliptest(-ldy, start[1] - oc->min[1], &u1, &u2)) { + if (cliptest(ldy, oc->max[1] - start[1], &u1, &u2)) { + ldz = is->dir[2] * is->dist; + if (cliptest(-ldz, start[2] - oc->min[2], &u1, &u2)) { + if (cliptest(ldz, oc->max[2] - start[2], &u1, &u2)) { + c1 = 1; + if (u2 < 1.0f) { + end[0] = start[0] + u2 * ldx; + end[1] = start[1] + u2 * ldy; + end[2] = start[2] + u2 * ldz; } - if (u1>0.0f) { - start[0] += u1*ldx; - start[1] += u1*ldy; - start[2] += u1*ldz; + if (u1 > 0.0f) { + start[0] += u1 * ldx; + start[1] += u1 * ldy; + start[2] += u1 * ldz; } } } @@ -902,34 +899,34 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) } } - if (c1==0) return 0; + if (c1 == 0) return 0; /* reset static variables in ocread */ //ocread(oc, oc->ocres, 0, 0); /* setup 3dda to traverse octree */ - ox1= (start[0]-oc->min[0])*oc->ocfacx; - oy1= (start[1]-oc->min[1])*oc->ocfacy; - oz1= (start[2]-oc->min[2])*oc->ocfacz; - ox2= (end[0]-oc->min[0])*oc->ocfacx; - oy2= (end[1]-oc->min[1])*oc->ocfacy; - oz2= (end[2]-oc->min[2])*oc->ocfacz; - - ocx1= (int)ox1; - ocy1= (int)oy1; - ocz1= (int)oz1; - ocx2= (int)ox2; - ocy2= (int)oy2; - ocz2= (int)oz2; + ox1 = (start[0] - oc->min[0]) * oc->ocfacx; + oy1 = (start[1] - oc->min[1]) * oc->ocfacy; + oz1 = (start[2] - oc->min[2]) * oc->ocfacz; + ox2 = (end[0] - oc->min[0]) * oc->ocfacx; + oy2 = (end[1] - oc->min[1]) * oc->ocfacy; + oz2 = (end[2] - oc->min[2]) * oc->ocfacz; + + ocx1 = (int)ox1; + ocy1 = (int)oy1; + ocz1 = (int)oz1; + ocx2 = (int)ox2; + ocy2 = (int)oy2; + ocz2 = (int)oz2; - if (ocx1==ocx2 && ocy1==ocy2 && ocz1==ocz2) { - no= ocread(oc, ocx1, ocy1, ocz1); + if (ocx1 == ocx2 && ocy1 == ocy2 && ocz1 == ocz2) { + no = ocread(oc, ocx1, ocy1, ocz1); if (no) { /* exact intersection with node */ - vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1; - vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2; + vec1[0] = ox1; vec1[1] = oy1; vec1[2] = oz1; + vec2[0] = ox2; vec2[1] = oy2; vec2[2] = oz2; calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); - if ( testnode(oc, is, no, ocval) ) return 1; + if (testnode(oc, is, no, ocval) ) return 1; } } else { @@ -939,153 +936,153 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) int eqval; /* calc labda en ld */ - dox= ox1-ox2; - doy= oy1-oy2; - doz= oz1-oz2; - - if (dox<-FLT_EPSILON) { - ldx= -1.0f/dox; - labdax= (ocx1-ox1+1.0f)*ldx; - dx= 1; + dox = ox1 - ox2; + doy = oy1 - oy2; + doz = oz1 - oz2; + + if (dox < -FLT_EPSILON) { + ldx = -1.0f / dox; + labdax = (ocx1 - ox1 + 1.0f) * ldx; + dx = 1; } - else if (dox>FLT_EPSILON) { - ldx= 1.0f/dox; - labdax= (ox1-ocx1)*ldx; - dx= -1; + else if (dox > FLT_EPSILON) { + ldx = 1.0f / dox; + labdax = (ox1 - ocx1) * ldx; + dx = -1; } else { - labdax=1.0f; - ldx=0; - dx= 0; + labdax = 1.0f; + ldx = 0; + dx = 0; } - if (doy<-FLT_EPSILON) { - ldy= -1.0f/doy; - labday= (ocy1-oy1+1.0f)*ldy; - dy= 1; + if (doy < -FLT_EPSILON) { + ldy = -1.0f / doy; + labday = (ocy1 - oy1 + 1.0f) * ldy; + dy = 1; } - else if (doy>FLT_EPSILON) { - ldy= 1.0f/doy; - labday= (oy1-ocy1)*ldy; - dy= -1; + else if (doy > FLT_EPSILON) { + ldy = 1.0f / doy; + labday = (oy1 - ocy1) * ldy; + dy = -1; } else { - labday=1.0f; - ldy=0; - dy= 0; + labday = 1.0f; + ldy = 0; + dy = 0; } - if (doz<-FLT_EPSILON) { - ldz= -1.0f/doz; - labdaz= (ocz1-oz1+1.0f)*ldz; - dz= 1; + if (doz < -FLT_EPSILON) { + ldz = -1.0f / doz; + labdaz = (ocz1 - oz1 + 1.0f) * ldz; + dz = 1; } - else if (doz>FLT_EPSILON) { - ldz= 1.0f/doz; - labdaz= (oz1-ocz1)*ldz; - dz= -1; + else if (doz > FLT_EPSILON) { + ldz = 1.0f / doz; + labdaz = (oz1 - ocz1) * ldz; + dz = -1; } else { - labdaz=1.0f; - ldz=0; - dz= 0; + labdaz = 1.0f; + ldz = 0; + dz = 0; } - xo=ocx1; yo=ocy1; zo=ocz1; - ddalabda= MIN3(labdax, labday, labdaz); + xo = ocx1; yo = ocy1; zo = ocz1; + ddalabda = MIN3(labdax, labday, labdaz); - vec2[0]= ox1; - vec2[1]= oy1; - vec2[2]= oz1; + vec2[0] = ox1; + vec2[1] = oy1; + vec2[2] = oz1; /* this loop has been constructed to make sure the first and last node of ray * are always included, even when ddalabda==1.0f or larger */ while (TRUE) { - no= ocread(oc, xo, yo, zo); + no = ocread(oc, xo, yo, zo); if (no) { /* calculate ray intersection with octree node */ copy_v3_v3(vec1, vec2); // dox, y, z is negative - vec2[0]= ox1-ddalabda*dox; - vec2[1]= oy1-ddalabda*doy; - vec2[2]= oz1-ddalabda*doz; + vec2[0] = ox1 - ddalabda * dox; + vec2[1] = oy1 - ddalabda * doy; + vec2[2] = oz1 - ddalabda * doz; calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); //is->dist = (u1+ddalabda*(u2-u1))*olabda; - if ( testnode(oc, is, no, ocval) ) + if (testnode(oc, is, no, ocval) ) found = 1; - if (is->dist < (u1+ddalabda*(u2-u1))*olabda) + if (is->dist < (u1 + ddalabda * (u2 - u1)) * olabda) return found; } - labdao= ddalabda; + labdao = ddalabda; /* traversing ocree nodes need careful detection of smallest values, with proper * exceptions for equal labdas */ - eqval= (labdax==labday); - if (labday==labdaz) eqval += 2; - if (labdax==labdaz) eqval += 4; - - if (eqval) { // only 4 cases exist! - if (eqval==7) { // x=y=z - xo+=dx; labdax+=ldx; - yo+=dy; labday+=ldy; - zo+=dz; labdaz+=ldz; + eqval = (labdax == labday); + if (labday == labdaz) eqval += 2; + if (labdax == labdaz) eqval += 4; + + if (eqval) { // only 4 cases exist! + if (eqval == 7) { // x=y=z + xo += dx; labdax += ldx; + yo += dy; labday += ldy; + zo += dz; labdaz += ldz; } - else if (eqval==1) { // x=y + else if (eqval == 1) { // x=y if (labday < labdaz) { - xo+=dx; labdax+=ldx; - yo+=dy; labday+=ldy; + xo += dx; labdax += ldx; + yo += dy; labday += ldy; } else { - zo+=dz; labdaz+=ldz; + zo += dz; labdaz += ldz; } } - else if (eqval==2) { // y=z + else if (eqval == 2) { // y=z if (labdax < labday) { - xo+=dx; labdax+=ldx; + xo += dx; labdax += ldx; } else { - yo+=dy; labday+=ldy; - zo+=dz; labdaz+=ldz; + yo += dy; labday += ldy; + zo += dz; labdaz += ldz; } } else { // x=z if (labday < labdax) { - yo+=dy; labday+=ldy; + yo += dy; labday += ldy; } else { - xo+=dx; labdax+=ldx; - zo+=dz; labdaz+=ldz; + xo += dx; labdax += ldx; + zo += dz; labdaz += ldz; } } } - else { // all three different, just three cases exist - eqval= (labdax=1.0f) break; + if (labdao >= 1.0f) break; } } diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 0f3a3111a13..61de4d39585 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -74,49 +74,49 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) /* after lock we test cube[1], if set the other thread has done it fine */ BLI_lock_thread(LOCK_IMAGE); - if (env->cube[1]==NULL) { + if (env->cube[1] == NULL) { BKE_free_envmapdata(env); - dx= ibuf->y; - dx/= 2; - if (3*dx == ibuf->x) { + dx = ibuf->y; + dx /= 2; + if (3 * dx == ibuf->x) { env->type = ENV_CUBE; - env->ok= ENV_OSA; + env->ok = ENV_OSA; } else if (ibuf->x == ibuf->y) { env->type = ENV_PLANE; - env->ok= ENV_OSA; + env->ok = ENV_OSA; } else { printf("Incorrect envmap size\n"); - env->ok= 0; - env->ima->ok= 0; + env->ok = 0; + env->ima->ok = 0; } if (env->ok) { if (env->type == ENV_CUBE) { - for (part=0; part<6; part++) { - env->cube[part]= IMB_allocImBuf(dx, dx, 24, IB_rect|IB_rectfloat); + for (part = 0; part < 6; part++) { + env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect | IB_rectfloat); } IMB_float_from_rect(ibuf); IMB_rectcpy(env->cube[0], ibuf, - 0, 0, 0, 0, dx, dx); + 0, 0, 0, 0, dx, dx); IMB_rectcpy(env->cube[1], ibuf, - 0, 0, dx, 0, dx, dx); + 0, 0, dx, 0, dx, dx); IMB_rectcpy(env->cube[2], ibuf, - 0, 0, 2*dx, 0, dx, dx); + 0, 0, 2 * dx, 0, dx, dx); IMB_rectcpy(env->cube[3], ibuf, - 0, 0, 0, dx, dx, dx); + 0, 0, 0, dx, dx, dx); IMB_rectcpy(env->cube[4], ibuf, - 0, 0, dx, dx, dx, dx); + 0, 0, dx, dx, dx, dx); IMB_rectcpy(env->cube[5], ibuf, - 0, 0, 2*dx, dx, dx, dx); + 0, 0, 2 * dx, dx, dx, dx); } else { /* ENV_PLANE */ - env->cube[1]= IMB_dupImBuf(ibuf); + env->cube[1] = IMB_dupImBuf(ibuf); IMB_float_from_rect(env->cube[1]); } } @@ -134,53 +134,53 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) float viewscale; int cuberes; - envre= RE_NewRender("Envmap"); + envre = RE_NewRender("Envmap"); - env->lastsize= re->r.size; + env->lastsize = re->r.size; cuberes = (env->cuberes * re->r.size) / 100; cuberes &= 0xFFFC; /* this flag has R_ZTRA in it for example */ - envre->flag= re->flag; + envre->flag = re->flag; /* set up renderdata */ - envre->r= re->r; + envre->r = re->r; envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR); - envre->r.layers.first= envre->r.layers.last= NULL; - envre->r.filtertype= 0; - envre->r.xparts= envre->r.yparts= 2; - envre->r.size= 100; - envre->r.yasp= envre->r.xasp= 1; + envre->r.layers.first = envre->r.layers.last = NULL; + envre->r.filtertype = 0; + envre->r.xparts = envre->r.yparts = 2; + envre->r.size = 100; + envre->r.yasp = envre->r.xasp = 1; RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL); - envre->scene= re->scene; /* unsure about this... */ - envre->lay= re->lay; + envre->scene = re->scene; /* unsure about this... */ + envre->lay = re->lay; /* view stuff in env render */ - viewscale= (env->type == ENV_PLANE)? env->viewscale: 1.0f; + viewscale = (env->type == ENV_PLANE) ? env->viewscale : 1.0f; RE_SetEnvmapCamera(envre, env->object, viewscale, env->clipsta, env->clipend); /* callbacks */ - envre->display_draw= re->display_draw; - envre->ddh= re->ddh; - envre->test_break= re->test_break; - envre->tbh= re->tbh; + envre->display_draw = re->display_draw; + envre->ddh = re->ddh; + envre->test_break = re->test_break; + envre->tbh = re->tbh; /* and for the evil stuff; copy the database... */ - envre->totvlak= re->totvlak; - envre->totvert= re->totvert; - envre->tothalo= re->tothalo; - envre->totstrand= re->totstrand; - envre->totlamp= re->totlamp; - envre->sortedhalos= re->sortedhalos; - envre->lights= re->lights; - envre->objecttable= re->objecttable; - envre->customdata_names= re->customdata_names; - envre->raytree= re->raytree; - envre->totinstance= re->totinstance; - envre->instancetable= re->instancetable; - envre->objectinstance= re->objectinstance; - envre->qmcsamplers= re->qmcsamplers; + envre->totvlak = re->totvlak; + envre->totvert = re->totvert; + envre->tothalo = re->tothalo; + envre->totstrand = re->totstrand; + envre->totlamp = re->totlamp; + envre->sortedhalos = re->sortedhalos; + envre->lights = re->lights; + envre->objecttable = re->objecttable; + envre->customdata_names = re->customdata_names; + envre->raytree = re->raytree; + envre->totinstance = re->totinstance; + envre->instancetable = re->instancetable; + envre->objectinstance = re->objectinstance; + envre->qmcsamplers = re->qmcsamplers; return envre; } @@ -188,20 +188,20 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) static void envmap_free_render_copy(Render *envre) { - envre->totvlak= 0; - envre->totvert= 0; - envre->tothalo= 0; - envre->totstrand= 0; - envre->totlamp= 0; - envre->totinstance= 0; - envre->sortedhalos= NULL; - envre->lights.first= envre->lights.last= NULL; - envre->objecttable.first= envre->objecttable.last= NULL; - envre->customdata_names.first= envre->customdata_names.last= NULL; - envre->raytree= NULL; - envre->instancetable.first= envre->instancetable.last= NULL; - envre->objectinstance= NULL; - envre->qmcsamplers= NULL; + envre->totvlak = 0; + envre->totvert = 0; + envre->tothalo = 0; + envre->totstrand = 0; + envre->totlamp = 0; + envre->totinstance = 0; + envre->sortedhalos = NULL; + envre->lights.first = envre->lights.last = NULL; + envre->objecttable.first = envre->objecttable.last = NULL; + envre->customdata_names.first = envre->customdata_names.last = NULL; + envre->raytree = NULL; + envre->instancetable.first = envre->instancetable.last = NULL; + envre->objectinstance = NULL; + envre->qmcsamplers = NULL; RE_FreeRender(envre); } @@ -212,28 +212,28 @@ static void envmap_transmatrix(float mat[][4], int part) { float tmat[4][4], eul[3], rotmat[4][4]; - eul[0]= eul[1]= eul[2]= 0.0; + eul[0] = eul[1] = eul[2] = 0.0; - if (part==0) { /* neg z */ + if (part == 0) { /* neg z */ ; } - else if (part==1) { /* pos z */ - eul[0]= M_PI; + else if (part == 1) { /* pos z */ + eul[0] = M_PI; } - else if (part==2) { /* pos y */ - eul[0]= M_PI/2.0; + else if (part == 2) { /* pos y */ + eul[0] = M_PI / 2.0; } - else if (part==3) { /* neg x */ - eul[0]= M_PI/2.0; - eul[2]= M_PI/2.0; + else if (part == 3) { /* neg x */ + eul[0] = M_PI / 2.0; + eul[2] = M_PI / 2.0; } - else if (part==4) { /* neg y */ - eul[0]= M_PI/2.0; - eul[2]= M_PI; + else if (part == 4) { /* neg y */ + eul[0] = M_PI / 2.0; + eul[2] = M_PI; } - else { /* pos x */ - eul[0]= M_PI/2.0; - eul[2]= -M_PI/2.0; + else { /* pos x */ + eul[0] = M_PI / 2.0; + eul[2] = -M_PI / 2.0; } copy_m4_m4(tmat, mat); @@ -255,7 +255,7 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4]; int a; - if (mode==0) { + if (mode == 0) { invert_m4_m4(tmat, mat); copy_m3_m4(imat, tmat); } @@ -264,13 +264,13 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) copy_m3_m4(imat, mat); } - for (obi=re->instancetable.first; obi; obi=obi->next) { + for (obi = re->instancetable.first; obi; obi = obi->next) { /* append or set matrix depending on dupli */ if (obi->flag & R_DUPLI_TRANSFORMED) { copy_m4_m4(tmpmat, obi->mat); mult_m4_m4m4(obi->mat, tmat, tmpmat); } - else if (mode==1) + else if (mode == 1) copy_m4_m4(obi->mat, tmat); else unit_m4(obi->mat); @@ -280,24 +280,24 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) transpose_m3(obi->nmat); /* indicate the renderer has to use transform matrices */ - if (mode==0) + if (mode == 0) obi->flag &= ~R_ENV_TRANSFORMED; else obi->flag |= R_ENV_TRANSFORMED; } - for (obr=re->objecttable.first; obr; obr=obr->next) { - for (a=0; atothalo; a++) { - if ((a & 255)==0) har= obr->bloha[a>>8]; + for (obr = re->objecttable.first; obr; obr = obr->next) { + for (a = 0; a < obr->tothalo; a++) { + if ((a & 255) == 0) har = obr->bloha[a >> 8]; else har++; mul_m4_v3(tmat, har->co); } } - for (go=re->lights.first; go; go= go->next) { - lar= go->lampren; + for (go = re->lights.first; go; go = go->next) { + lar = go->lampren; /* removed here some horrible code of someone in NaN who tried to fix * prototypes... just solved by introducing a correct cmat[3][3] instead @@ -308,14 +308,14 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) mul_m3_v3(imat, lar->vec); mul_m4_v3(tmat, lar->co); - lar->sh_invcampos[0]= -lar->co[0]; - lar->sh_invcampos[1]= -lar->co[1]; - lar->sh_invcampos[2]= -lar->co[2]; + lar->sh_invcampos[0] = -lar->co[0]; + lar->sh_invcampos[1] = -lar->co[1]; + lar->sh_invcampos[2] = -lar->co[2]; mul_m3_v3(lar->imat, lar->sh_invcampos); - lar->sh_invcampos[2]*= lar->sh_zfac; + lar->sh_invcampos[2] *= lar->sh_zfac; if (lar->shb) { - if (mode==1) { + if (mode == 1) { invert_m4_m4(pmat, mat); mult_m4_m4m4(smat, lar->shb->viewmat, pmat); mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat); @@ -342,12 +342,12 @@ static void env_layerflags(Render *re, unsigned int notlay) * now (face & ~not) is true */ - notlay= ~notlay; + notlay = ~notlay; - for (obr=re->objecttable.first; obr; obr=obr->next) { - if ((obr->lay & notlay)==0) { - for (a=0; atotvlak; a++) { - if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + for (obr = re->objecttable.first; obr; obr = obr->next) { + if ((obr->lay & notlay) == 0) { + for (a = 0; a < obr->totvlak; a++) { + if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; else vlr++; vlr->flag |= R_HIDDEN; @@ -362,9 +362,9 @@ static void env_hideobject(Render *re, Object *ob) VlakRen *vlr = NULL; int a; - for (obr=re->objecttable.first; obr; obr=obr->next) { - for (a=0; atotvlak; a++) { - if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + for (obr = re->objecttable.first; obr; obr = obr->next) { + for (a = 0; a < obr->totvlak; a++) { + if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; else vlr++; if (obr->ob == ob) @@ -379,9 +379,9 @@ static void env_showobjects(Render *re) VlakRen *vlr = NULL; int a; - for (obr=re->objecttable.first; obr; obr=obr->next) { - for (a=0; atotvlak; a++) { - if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + for (obr = re->objecttable.first; obr; obr = obr->next) { + for (a = 0; a < obr->totvlak; a++) { + if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak; else vlr++; vlr->flag &= ~R_HIDDEN; @@ -396,12 +396,12 @@ static void env_set_imats(Render *re) Base *base; float mat[4][4]; - base= re->scene->base.first; + base = re->scene->base.first; while (base) { mult_m4_m4m4(mat, re->viewmat, base->object->obmat); invert_m4_m4(base->object->imat, mat); - base= base->next; + base = base->next; } } @@ -420,7 +420,7 @@ static void render_envmap(Render *re, EnvMap *env) /* need a recalc: ortho-render has no correct viewinv */ invert_m4_m4(oldviewinv, re->viewmat); - envre= envmap_render_copy(re, env); + envre = envmap_render_copy(re, env); /* precalc orthmat for object */ copy_m4_m4(orthmat, env->object->obmat); @@ -431,8 +431,8 @@ static void render_envmap(Render *re, EnvMap *env) invert_m4_m4(tmat, mat); copy_m3_m4(env->obimat, tmat); - for (part=0; part<6; part++) { - if (env->type==ENV_PLANE && part!=1) + for (part = 0; part < 6; part++) { + if (env->type == ENV_PLANE && part != 1) continue; re->display_clear(re->dch, envre->result); @@ -456,7 +456,7 @@ static void render_envmap(Render *re, EnvMap *env) env_hideobject(envre, env->object); env_set_imats(envre); - if (re->test_break(re->tbh)==0) { + if (re->test_break(re->tbh) == 0) { RE_TileProcessor(envre); } @@ -464,23 +464,23 @@ static void render_envmap(Render *re, EnvMap *env) env_showobjects(envre); env_rotate_scene(envre, tmat, 0); - if (re->test_break(re->tbh)==0) { - RenderLayer *rl= envre->result->layers.first; + if (re->test_break(re->tbh) == 0) { + RenderLayer *rl = envre->result->layers.first; int y; float *alpha; - ibuf= IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect|IB_rectfloat); + ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); if (re->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ibuf->profile = IB_PROFILE_LINEAR_RGB; /* envmap renders without alpha */ - alpha= ((float *)ibuf->rect_float)+3; - for (y= ibuf->x*ibuf->y - 1; y>=0; y--, alpha+=4) - *alpha= 1.0; + alpha = ((float *)ibuf->rect_float) + 3; + for (y = ibuf->x * ibuf->y - 1; y >= 0; y--, alpha += 4) + *alpha = 1.0; - env->cube[part]= ibuf; + env->cube[part] = ibuf; } if (re->test_break(re->tbh)) break; @@ -489,9 +489,9 @@ static void render_envmap(Render *re, EnvMap *env) if (re->test_break(re->tbh)) BKE_free_envmapdata(env); else { - if (envre->r.mode & R_OSA) env->ok= ENV_OSA; - else env->ok= ENV_NORMAL; - env->lastframe= re->scene->r.cfra; + if (envre->r.mode & R_OSA) env->ok = ENV_OSA; + else env->ok = ENV_NORMAL; + env->lastframe = re->scene->r.cfra; } /* restore */ @@ -505,27 +505,27 @@ static void render_envmap(Render *re, EnvMap *env) void make_envmaps(Render *re) { Tex *tex; - int do_init = FALSE, depth= 0, trace; + int do_init = FALSE, depth = 0, trace; if (!(re->r.mode & R_ENVMAP)) return; /* we don't raytrace, disabling the flag will cause ray_transp render solid */ - trace= (re->r.mode & R_RAYTRACE); + trace = (re->r.mode & R_RAYTRACE); re->r.mode &= ~R_RAYTRACE; - re->i.infostr= "Creating Environment maps"; + re->i.infostr = "Creating Environment maps"; re->stats_draw(re->sdh, &re->i); /* 5 = hardcoded max recursion level */ - while (depth<5) { - tex= re->main->tex.first; + while (depth < 5) { + tex = re->main->tex.first; while (tex) { - if (tex->id.us && tex->type==TEX_ENVMAP) { + if (tex->id.us && tex->type == TEX_ENVMAP) { if (tex->env && tex->env->object) { - EnvMap *env= tex->env; + EnvMap *env = tex->env; if (env->object->lay & re->lay) { - if (env->stype==ENV_LOAD) { + if (env->stype == ENV_LOAD) { float orthmat[4][4], mat[4][4], tmat[4][4]; /* precalc orthmat for object */ @@ -545,31 +545,31 @@ void make_envmaps(Render *re) /* set 'recalc' to make sure it does an entire loop of recalcs */ if (env->ok) { - /* free when OSA, and old one isn't OSA */ - if ((re->r.mode & R_OSA) && env->ok==ENV_NORMAL) + /* free when OSA, and old one isn't OSA */ + if ((re->r.mode & R_OSA) && env->ok == ENV_NORMAL) BKE_free_envmapdata(env); - /* free when size larger */ + /* free when size larger */ else if (env->lastsize < re->r.size) BKE_free_envmapdata(env); - /* free when env is in recalcmode */ + /* free when env is in recalcmode */ else if (env->recalc) BKE_free_envmapdata(env); } - if (env->ok==0 && depth==0) env->recalc= 1; + if (env->ok == 0 && depth == 0) env->recalc = 1; - if (env->ok==0) { + if (env->ok == 0) { do_init = TRUE; render_envmap(re, env); - if (depth==env->depth) env->recalc= 0; + if (depth == env->depth) env->recalc = 0; } } } } } } - tex= tex->id.next; + tex = tex->id.next; } depth++; } @@ -591,55 +591,55 @@ static int envcube_isect(EnvMap *env, const float vec[3], float answ[2]) float labda; int face; - if (env->type==ENV_PLANE) { - face= 1; + if (env->type == ENV_PLANE) { + face = 1; - labda= 1.0f/vec[2]; - answ[0]= env->viewscale*labda*vec[0]; - answ[1]= -env->viewscale*labda*vec[1]; + labda = 1.0f / vec[2]; + answ[0] = env->viewscale * labda * vec[0]; + answ[1] = -env->viewscale * labda * vec[1]; } else { /* which face */ - if ( vec[2] <= -fabsf(vec[0]) && vec[2] <= -fabsf(vec[1]) ) { - face= 0; - labda= -1.0f/vec[2]; - answ[0]= labda*vec[0]; - answ[1]= labda*vec[1]; + if (vec[2] <= -fabsf(vec[0]) && vec[2] <= -fabsf(vec[1]) ) { + face = 0; + labda = -1.0f / vec[2]; + answ[0] = labda * vec[0]; + answ[1] = labda * vec[1]; } else if (vec[2] >= fabsf(vec[0]) && vec[2] >= fabsf(vec[1])) { - face= 1; - labda= 1.0f/vec[2]; - answ[0]= labda*vec[0]; - answ[1]= -labda*vec[1]; + face = 1; + labda = 1.0f / vec[2]; + answ[0] = labda * vec[0]; + answ[1] = -labda * vec[1]; } else if (vec[1] >= fabsf(vec[0])) { - face= 2; - labda= 1.0f/vec[1]; - answ[0]= labda*vec[0]; - answ[1]= labda*vec[2]; + face = 2; + labda = 1.0f / vec[1]; + answ[0] = labda * vec[0]; + answ[1] = labda * vec[2]; } else if (vec[0] <= -fabsf(vec[1])) { - face= 3; - labda= -1.0f/vec[0]; - answ[0]= labda*vec[1]; - answ[1]= labda*vec[2]; + face = 3; + labda = -1.0f / vec[0]; + answ[0] = labda * vec[1]; + answ[1] = labda * vec[2]; } else if (vec[1] <= -fabsf(vec[0])) { - face= 4; - labda= -1.0f/vec[1]; - answ[0]= -labda*vec[0]; - answ[1]= labda*vec[2]; + face = 4; + labda = -1.0f / vec[1]; + answ[0] = -labda * vec[0]; + answ[1] = labda * vec[2]; } else { - face= 5; - labda= 1.0f/vec[0]; - answ[0]= -labda*vec[1]; - answ[1]= labda*vec[2]; + face = 5; + labda = 1.0f / vec[0]; + answ[0] = -labda * vec[1]; + answ[1] = labda * vec[2]; } } - answ[0]= 0.5f+0.5f*answ[0]; - answ[1]= 0.5f+0.5f*answ[1]; + answ[0] = 0.5f + 0.5f * answ[0]; + answ[1] = 0.5f + 0.5f * answ[1]; return face; } @@ -647,23 +647,23 @@ static int envcube_isect(EnvMap *env, const float vec[3], float answ[2]) static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face) { - if (face==2 || face==4) { - dxts[0]= dxt[0]; - dyts[0]= dyt[0]; - dxts[1]= dxt[2]; - dyts[1]= dyt[2]; + if (face == 2 || face == 4) { + dxts[0] = dxt[0]; + dyts[0] = dyt[0]; + dxts[1] = dxt[2]; + dyts[1] = dyt[2]; } - else if (face==3 || face==5) { - dxts[0]= dxt[1]; - dxts[1]= dxt[2]; - dyts[0]= dyt[1]; - dyts[1]= dyt[2]; + else if (face == 3 || face == 5) { + dxts[0] = dxt[1]; + dxts[1] = dxt[2]; + dyts[0] = dyt[1]; + dyts[1] = dyt[2]; } else { - dxts[0]= dxt[0]; - dyts[0]= dyt[0]; - dxts[1]= dxt[1]; - dyts[1]= dyt[1]; + dxts[0] = dxt[0]; + dyts[0] = dyt[0]; + dxts[1] = dxt[1]; + dyts[1] = dyt[1]; } } @@ -671,34 +671,34 @@ static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int fac int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres) { - extern Render R; /* only in this call */ + extern Render R; /* only in this call */ /* texvec should be the already reflected normal */ EnvMap *env; ImBuf *ibuf; float fac, vec[3], sco[3], dxts[3], dyts[3]; int face, face1; - env= tex->env; - if (env==NULL || (env->stype!=ENV_LOAD && env->object==NULL)) { - texres->tin= 0.0; + env = tex->env; + if (env == NULL || (env->stype != ENV_LOAD && env->object == NULL)) { + texres->tin = 0.0; return 0; } - if (env->stype==ENV_LOAD) { - env->ima= tex->ima; + if (env->stype == ENV_LOAD) { + env->ima = tex->ima; if (env->ima && env->ima->ok) { - if (env->cube[1]==NULL) { - ImBuf *ibuf_ima= BKE_image_get_ibuf(env->ima, NULL); + if (env->cube[1] == NULL) { + ImBuf *ibuf_ima = BKE_image_get_ibuf(env->ima, NULL); if (ibuf_ima) envmap_split_ima(env, ibuf_ima); else - env->ok= 0; + env->ok = 0; } } } - if (env->ok==0) { - texres->tin= 0.0; + if (env->ok == 0) { + texres->tin = 0.0; return 0; } @@ -707,8 +707,8 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe if (env->object) mul_m3_v3(env->obimat, vec); else mul_mat3_m4_v3(R.viewinv, vec); - face= envcube_isect(env, vec, sco); - ibuf= env->cube[face]; + face = envcube_isect(env, vec, sco); + ibuf = env->cube[face]; if (osatex) { if (env->object) { @@ -724,45 +724,45 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe /* edges? */ - if (texres->ta<1.0f) { + if (texres->ta < 1.0f) { TexResult texr1, texr2; - texr1.nor= texr2.nor= NULL; - texr1.talpha= texr2.talpha= texres->talpha; /* boxclip expects this initialized */ + texr1.nor = texr2.nor = NULL; + texr1.talpha = texr2.talpha = texres->talpha; /* boxclip expects this initialized */ add_v3_v3(vec, dxt); - face1= envcube_isect(env, vec, sco); + face1 = envcube_isect(env, vec, sco); sub_v3_v3(vec, dxt); - if (face!=face1) { - ibuf= env->cube[face1]; + if (face != face1) { + ibuf = env->cube[face1]; set_dxtdyt(dxts, dyts, dxt, dyt, face1); imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1); } - else texr1.tr= texr1.tg= texr1.tb= texr1.ta= 0.0; + else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0; /* here was the nasty bug! results were not zero-ed. FPE! */ add_v3_v3(vec, dyt); - face1= envcube_isect(env, vec, sco); + face1 = envcube_isect(env, vec, sco); sub_v3_v3(vec, dyt); - if (face!=face1) { - ibuf= env->cube[face1]; + if (face != face1) { + ibuf = env->cube[face1]; set_dxtdyt(dxts, dyts, dxt, dyt, face1); imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2); } - else texr2.tr= texr2.tg= texr2.tb= texr2.ta= 0.0; + else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0; - fac= (texres->ta+texr1.ta+texr2.ta); - if (fac!=0.0f) { - fac= 1.0f/fac; + fac = (texres->ta + texr1.ta + texr2.ta); + if (fac != 0.0f) { + fac = 1.0f / fac; - texres->tr= fac*(texres->ta*texres->tr + texr1.ta*texr1.tr + texr2.ta*texr2.tr ); - texres->tg= fac*(texres->ta*texres->tg + texr1.ta*texr1.tg + texr2.ta*texr2.tg ); - texres->tb= fac*(texres->ta*texres->tb + texr1.ta*texr1.tb + texr2.ta*texr2.tb ); + texres->tr = fac * (texres->ta * texres->tr + texr1.ta * texr1.tr + texr2.ta * texr2.tr); + texres->tg = fac * (texres->ta * texres->tg + texr1.ta * texr1.tg + texr2.ta * texr2.tg); + texres->tb = fac * (texres->ta * texres->tb + texr1.ta * texr1.tb + texr2.ta * texr2.tb); } - texres->ta= 1.0; + texres->ta = 1.0; } } else { @@ -771,7 +771,3 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe return 1; } - -/* ------------------------------------------------------------------------- */ - -/* eof */ diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index b599da48803..75748696a72 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -71,7 +71,7 @@ extern struct Render R; /* luminance rec. 709 */ BLI_INLINE float luminance(const float col[3]) { - return (0.212671f*col[0] + 0.71516f*col[1] + 0.072169f*col[2]); + return (0.212671f * col[0] + 0.71516f * col[1] + 0.072169f * col[2]); } /* tracing */ @@ -80,7 +80,7 @@ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) float visibility = 1.f; if (lar->shb) { - float dxco[3]={0.f, 0.f, 0.f}, dyco[3]={0.f, 0.f, 0.f}; + float dxco[3] = {0.f, 0.f, 0.f}, dyco[3] = {0.f, 0.f, 0.f}; visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); } @@ -89,7 +89,7 @@ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) Isect is; copy_v3_v3(is.start, co); - if (lar->type==LA_SUN || lar->type==LA_HEMI) { + if (lar->type == LA_SUN || lar->type == LA_HEMI) { is.dir[0] = -lar->vec[0]; is.dir[1] = -lar->vec[1]; is.dir[2] = -lar->vec[2]; @@ -97,17 +97,17 @@ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) } else { sub_v3_v3v3(is.dir, lar->co, is.start); - is.dist = normalize_v3(is.dir ); + is.dist = normalize_v3(is.dir); } is.mode = RE_RAY_MIRROR; is.check = RE_CHECK_VLR_NON_SOLID_MATERIAL; is.skip = 0; - if (lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) - is.lay= lar->lay; + if (lar->mode & (LA_LAYER | LA_LAYER_SHADOW)) + is.lay = lar->lay; else - is.lay= -1; + is.lay = -1; is.orig.ob = NULL; is.orig.face = NULL; @@ -117,7 +117,7 @@ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) visibility = 0.f; } - lar->last_hit[shi->thread]= is.last_hit; + lar->last_hit[shi->thread] = is.last_hit; } return visibility; } @@ -128,26 +128,26 @@ static int vol_get_bounds(ShadeInput *shi, const float co[3], const float vec[3] copy_v3_v3(isect->start, co); copy_v3_v3(isect->dir, vec); isect->dist = FLT_MAX; - isect->mode= RE_RAY_MIRROR; + isect->mode = RE_RAY_MIRROR; isect->last_hit = NULL; - isect->lay= -1; - isect->check= RE_CHECK_VLR_NONE; + isect->lay = -1; + isect->check = RE_CHECK_VLR_NONE; if (intersect_type == VOL_BOUNDS_DEPTH) { isect->skip = RE_SKIP_VLR_NEIGHBOUR; - isect->orig.face = (void*)shi->vlr; - isect->orig.ob = (void*)shi->obi; + isect->orig.face = (void *)shi->vlr; + isect->orig.ob = (void *)shi->obi; } else { // if (intersect_type == VOL_BOUNDS_SS) { - isect->skip= 0; - isect->orig.face= NULL; + isect->skip = 0; + isect->orig.face = NULL; isect->orig.ob = NULL; } if (RE_rayobject_raycast(R.raytree, isect)) { - hitco[0] = isect->start[0] + isect->dist*isect->dir[0]; - hitco[1] = isect->start[1] + isect->dist*isect->dir[1]; - hitco[2] = isect->start[2] + isect->dist*isect->dir[2]; + hitco[0] = isect->start[0] + isect->dist * isect->dir[0]; + hitco[1] = isect->start[1] + isect->dist * isect->dir[1]; + hitco[2] = isect->start[2] + isect->dist * isect->dir[2]; return 1; } else { @@ -162,18 +162,18 @@ static void shade_intersection(ShadeInput *shi, float col_r[4], Isect *is) memset(&shi_new, 0, sizeof(ShadeInput)); - shi_new.mask= shi->mask; - shi_new.osatex= shi->osatex; - shi_new.thread= shi->thread; + shi_new.mask = shi->mask; + shi_new.osatex = shi->osatex; + shi_new.thread = shi->thread; shi_new.depth = shi->depth + 1; - shi_new.volume_depth= shi->volume_depth + 1; - shi_new.xs= shi->xs; - shi_new.ys= shi->ys; - shi_new.lay= shi->lay; - shi_new.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */ - shi_new.combinedflag= 0xFFFFFF; /* ray trace does all options */ - shi_new.light_override= shi->light_override; - shi_new.mat_override= shi->mat_override; + shi_new.volume_depth = shi->volume_depth + 1; + shi_new.xs = shi->xs; + shi_new.ys = shi->ys; + shi_new.lay = shi->lay; + shi_new.passflag = SCE_PASS_COMBINED; /* result of tracing needs no pass info */ + shi_new.combinedflag = 0xFFFFFF; /* ray trace does all options */ + shi_new.light_override = shi->light_override; + shi_new.mat_override = shi->mat_override; copy_v3_v3(shi_new.camera_co, is->start); @@ -196,13 +196,13 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, const float co[3], f copy_v3_v3(isect.dir, shi->view); isect.dist = FLT_MAX; - isect.mode= RE_RAY_MIRROR; + isect.mode = RE_RAY_MIRROR; isect.check = RE_CHECK_VLR_NONE; isect.skip = RE_SKIP_VLR_NEIGHBOUR; - isect.orig.ob = (void*) shi->obi; - isect.orig.face = (void*)vlr; + isect.orig.ob = (void *) shi->obi; + isect.orig.face = (void *)vlr; isect.last_hit = NULL; - isect.lay= -1; + isect.lay = -1; /* check to see if there's anything behind the volume, otherwise shade the sky */ if (RE_rayobject_raycast(R.raytree, &isect)) { @@ -241,11 +241,11 @@ static void vol_get_precached_scattering(Render *re, ShadeInput *shi, float scat /* Meta object density, brute force for now * (might be good enough anyway, don't need huge number of metaobs to model volumetric objects */ -static float metadensity(Object* ob, const float co[3]) +static float metadensity(Object *ob, const float co[3]) { float mat[4][4], imat[4][4], dens = 0.f; - MetaBall* mb = (MetaBall*)ob->data; - MetaElem* ml; + MetaBall *mb = (MetaBall *)ob->data; + MetaElem *ml; /* transform co to meta-element */ float tco[3] = {co[0], co[1], co[2]}; @@ -253,13 +253,13 @@ static float metadensity(Object* ob, const float co[3]) invert_m4_m4(imat, mat); mul_m4_v3(imat, tco); - for (ml = mb->elems.first; ml; ml=ml->next) { + for (ml = mb->elems.first; ml; ml = ml->next) { float bmat[3][3], dist2; /* element rotation transform */ float tp[3] = {ml->x - tco[0], ml->y - tco[1], ml->z - tco[2]}; quat_to_mat3(bmat, ml->quat); - transpose_m3(bmat); // rot.only, so inverse == transpose + transpose_m3(bmat); // rot.only, so inverse == transpose mul_m3_v3(bmat, tp); /* MB_BALL default */ @@ -269,10 +269,10 @@ static float metadensity(Object* ob, const float co[3]) break; case MB_CUBE: tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f); - // no break, xy as plane + // no break, xy as plane case MB_PLANE: tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f); - // no break, x as tube + // no break, x as tube case MB_TUBE: tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f); } @@ -280,7 +280,7 @@ static float metadensity(Object* ob, const float co[3]) /* ml->rad2 is not set */ dist2 = 1.0f - (dot_v3v3(tp, tp) / (ml->rad * ml->rad)); if (dist2 > 0.f) - dens += (ml->flag & MB_NEGATIVE) ? -ml->s*dist2*dist2*dist2 : ml->s*dist2*dist2*dist2; + dens += (ml->flag & MB_NEGATIVE) ? -ml->s * dist2 * dist2 * dist2 : ml->s * dist2 * dist2 * dist2; } dens -= mb->thresh; @@ -299,7 +299,7 @@ float vol_get_density(struct ShadeInput *shi, const float co[3]) if (shi->obi->obr->ob->type == OB_MBALL) { const float md = metadensity(shi->obi->obr->ob, co); if (md < 1.f) density *= md; - } + } return density * density_scale; } @@ -311,11 +311,11 @@ float vol_get_density(struct ShadeInput *shi, const float co[3]) static void vol_get_reflection_color(ShadeInput *shi, float ref_col[3], const float co[3]) { float scatter = shi->mat->vol.scattering; - float reflection= shi->mat->vol.reflection; + float reflection = shi->mat->vol.reflection; copy_v3_v3(ref_col, shi->mat->vol.reflection_col); - if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_REFLECTION_COL)) - do_volume_tex(shi, co, MAP_SCATTERING+MAP_REFLECTION_COL, ref_col, &scatter, &R); + if (shi->mat->mapto_textured & (MAP_SCATTERING + MAP_REFLECTION_COL)) + do_volume_tex(shi, co, MAP_SCATTERING + MAP_REFLECTION_COL, ref_col, &scatter, &R); /* only one single float parameter at a time... :s */ if (shi->mat->mapto_textured & (MAP_REFLECTION)) @@ -333,8 +333,8 @@ static void vol_get_emission(ShadeInput *shi, float emission_col[3], const float float emission = shi->mat->vol.emission; copy_v3_v3(emission_col, shi->mat->vol.emission_col); - if (shi->mat->mapto_textured & (MAP_EMISSION+MAP_EMISSION_COL)) - do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission, &R); + if (shi->mat->mapto_textured & (MAP_EMISSION + MAP_EMISSION_COL)) + do_volume_tex(shi, co, MAP_EMISSION + MAP_EMISSION_COL, emission_col, &emission, &R); emission_col[0] = emission_col[0] * emission; emission_col[1] = emission_col[1] * emission; @@ -353,8 +353,8 @@ static void vol_get_sigma_t(ShadeInput *shi, float sigma_t[3], const float co[3] float transmission_col[3] = {shi->mat->vol.transmission_col[0], shi->mat->vol.transmission_col[1], shi->mat->vol.transmission_col[2]}; float scattering = shi->mat->vol.scattering; - if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_TRANSMISSION_COL)) - do_volume_tex(shi, co, MAP_SCATTERING+MAP_TRANSMISSION_COL, transmission_col, &scattering, &R); + if (shi->mat->mapto_textured & (MAP_SCATTERING + MAP_TRANSMISSION_COL)) + do_volume_tex(shi, co, MAP_SCATTERING + MAP_TRANSMISSION_COL, transmission_col, &scattering, &R); sigma_t[0] = (1.0f - transmission_col[0]) + scattering; sigma_t[1] = (1.0f - transmission_col[1]) + scattering; @@ -378,13 +378,13 @@ static float vol_get_phasefunc(ShadeInput *UNUSED(shi), float g, const float w[3 * until Blender's shading system supports this better. --matt */ - if (g == 0.f) { /* isotropic */ + if (g == 0.f) { /* isotropic */ return normalize * 1.f; } - else { /* schlick */ + else { /* schlick */ const float k = 1.55f * g - .55f * g * g * g; const float kcostheta = k * dot_v3v3(w, wp); - return normalize * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta)); + return normalize * (1.f - k * k) / ((1.f - kcostheta) * (1.f - kcostheta)); } /* not used, but here for reference: */ @@ -395,14 +395,14 @@ static float vol_get_phasefunc(ShadeInput *UNUSED(shi), float g, const float w[3 case MA_VOL_PH_MIEMURKY: return normalize * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)); case MA_VOL_PH_RAYLEIGH: - return normalize * 3.f/4.f * (1 + costheta * costheta); + return normalize * 3.f / 4.f * (1 + costheta * costheta); case MA_VOL_PH_HG: return normalize * (1.f - g * g) / powf(1.f + g * g - 2.f * g * costheta, 1.5f); case MA_VOL_PH_SCHLICK: { const float k = 1.55f * g - .55f * g * g * g; const float kcostheta = k * costheta; - return normalize * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta)); + return normalize * (1.f - k * k) / ((1.f - kcostheta) * (1.f - kcostheta)); } case MA_VOL_PH_ISOTROPIC: default: @@ -471,20 +471,20 @@ static void vol_get_transmittance(ShadeInput *shi, float tr[3], const float co[3 static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const float view[3], LampRen *lar, float lacol[3]) { float visifac, lv[3], lampdist; - float tr[3]={1.0, 1.0, 1.0}; + float tr[3] = {1.0, 1.0, 1.0}; float hitco[3], *atten_co; float p, ref_col[3]; - if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay)==0) return; - if ((lar->lay & shi->lay)==0) return; + if (lar->mode & LA_LAYER) if ((lar->lay & shi->obi->lay) == 0) return; + if ((lar->lay & shi->lay) == 0) return; if (lar->energy == 0.0f) return; - if ((visifac= lamp_get_visibility(lar, co, lv, &lampdist)) == 0.f) return; + if ((visifac = lamp_get_visibility(lar, co, lv, &lampdist)) == 0.f) return; copy_v3_v3(lacol, &lar->r); if (lar->mode & LA_TEXTURE) { - shi->osatex= 0; + shi->osatex = 0; do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE); } @@ -519,7 +519,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const if (ELEM(lar->type, LA_SUN, LA_HEMI)) /* infinite lights, can never be inside volume */ atten_co = hitco; - else if ( lampdist < dist ) { + else if (lampdist < dist) { atten_co = lar->co; } else @@ -558,10 +558,10 @@ void vol_get_scattering(ShadeInput *shi, float scatter_col[3], const float co[3] zero_v3(scatter_col); - lights= get_lights(shi); - for (go=lights->first; go; go= go->next) { + lights = get_lights(shi); + for (go = lights->first; go; go = go->next) { float lacol[3] = {0.f, 0.f, 0.f}; - lar= go->lampren; + lar = go->lampren; if (lar) { vol_shade_one_lamp(shi, co, view, lar, lacol); @@ -598,7 +598,7 @@ static void volumeintegrate(struct ShadeInput *shi, float col[4], const float co float t0 = 0.f; float pt0 = t0; - float t1 = normalize_v3(step_vec); /* returns vector length */ + float t1 = normalize_v3(step_vec); /* returns vector length */ t0 += stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread)); p[0] += t0 * step_vec[0]; @@ -656,7 +656,7 @@ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int in float hitco[3], col[4] = {0.f, 0.f, 0.f, 0.f}; float *startco, *endco; int trace_behind = 1; - const int ztransp= ((shi->depth==0) && (shi->mat->mode & MA_TRANSP) && (shi->mat->mode & MA_ZTRANSP)); + const int ztransp = ((shi->depth == 0) && (shi->mat->mode & MA_TRANSP) && (shi->mat->mode & MA_ZTRANSP)); Isect is; /* check for shading an internal face a volume object directly */ @@ -669,7 +669,7 @@ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int in if (ztransp && inside_volume == VOL_SHADE_INSIDE) { MatInside *mi; - int render_this=0; + int render_this = 0; /* don't render the backfaces of ztransp volume materials. * @@ -683,9 +683,9 @@ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int in * which would otherwise render the volume in between the camera and the backface * --matt */ - for (mi=R.render_volumes_inside.first; mi; mi=mi->next) { + for (mi = R.render_volumes_inside.first; mi; mi = mi->next) { /* weak... */ - if (mi->ma == shi->mat) render_this=1; + if (mi->ma == shi->mat) render_this = 1; } if (!render_this) return; } @@ -733,7 +733,7 @@ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int in } if (ztransp) - col[3] = col[3]>1.f?1.f:col[3]; + col[3] = col[3] > 1.f ? 1.f : col[3]; else col[3] = 1.f; @@ -749,7 +749,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct { float hitco[3]; float tr[3] = {1.0, 1.0, 1.0}; - Isect is= {{0}}; + Isect is = {{0}}; float *startco, *endco; memset(shr, 0, sizeof(ShadeResult)); @@ -825,5 +825,3 @@ void shade_volume_inside(ShadeInput *shi, ShadeResult *shr) shi->obi = obi_backup; shi->obr = obi_backup->obr; } - - diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 90e6594d888..7d54f77fc90 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -66,10 +66,10 @@ static int is_vd_res_ok(VoxelData *vd) { /* arbitrary large value so corrupt headers don't break */ - const int min= 1, max= 100000; - return (vd->resol[0] >= min && vd->resol[0] <= max) && - (vd->resol[1] >= min && vd->resol[1] <= max) && - (vd->resol[2] >= min && vd->resol[2] <= max); + const int min = 1, max = 100000; + return (vd->resol[0] >= min && vd->resol[0] <= max) && + (vd->resol[1] >= min && vd->resol[1] <= max) && + (vd->resol[2] >= min && vd->resol[2] <= max); } /* use size_t because the result may exceed INT_MAX */ @@ -86,10 +86,10 @@ static int load_frame_blendervoxel(VoxelData *vd, FILE *fp, int frame) if (is_vd_res_ok(vd) == FALSE) return 0; - vd->dataset = MEM_mapallocN(sizeof(float)*size, "voxel dataset"); + vd->dataset = MEM_mapallocN(sizeof(float) * size, "voxel dataset"); if (vd->dataset == NULL) return 0; - if (fseek(fp, frame*size*sizeof(float)+offset, 0) == -1) + if (fseek(fp, frame * size * sizeof(float) + offset, 0) == -1) return 0; if (fread(vd->dataset, sizeof(float), size, fp) != size) return 0; @@ -108,29 +108,29 @@ static int load_frame_raw8(VoxelData *vd, FILE *fp, int frame) if (is_vd_res_ok(vd) == FALSE) return 0; - vd->dataset = MEM_mapallocN(sizeof(float)*size, "voxel dataset"); + vd->dataset = MEM_mapallocN(sizeof(float) * size, "voxel dataset"); if (vd->dataset == NULL) return 0; - data_c = (char *)MEM_mallocN(sizeof(char)*size, "temporary voxel file reading storage"); + data_c = (char *)MEM_mallocN(sizeof(char) * size, "temporary voxel file reading storage"); if (data_c == NULL) { MEM_freeN(vd->dataset); - vd->dataset= NULL; + vd->dataset = NULL; return 0; } - if (fseek(fp, (frame-1)*size*sizeof(char), 0) == -1) { + if (fseek(fp, (frame - 1) * size * sizeof(char), 0) == -1) { MEM_freeN(data_c); MEM_freeN(vd->dataset); - vd->dataset= NULL; + vd->dataset = NULL; return 0; } if (fread(data_c, sizeof(char), size, fp) != size) { MEM_freeN(data_c); MEM_freeN(vd->dataset); - vd->dataset= NULL; + vd->dataset = NULL; return 0; } - for (i=0; idataset[i] = (float)data_c[i] / 255.f; } MEM_freeN(data_c); @@ -146,7 +146,7 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) Image *ima = tex->ima; ImageUser *tiuser = &tex->iuser; ImageUser iuser = *(tiuser); - int x=0, y=0, z=0; + int x = 0, y = 0, z = 0; float *rf; if (!ima || !tiuser) return; @@ -157,10 +157,10 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* find the first valid ibuf and use it to initialize the resolution of the data set */ /* need to do this in advance so we know how much memory to allocate */ - ibuf= BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_get_ibuf(ima, &iuser); while (!ibuf && (iuser.framenr < iuser.frames)) { iuser.framenr++; - ibuf= BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_get_ibuf(ima, &iuser); } if (!ibuf) return; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); @@ -169,23 +169,23 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) vd->resol[0] = ibuf->x; vd->resol[1] = ibuf->y; vd->resol[2] = iuser.frames; - vd->dataset = MEM_mapallocN(sizeof(float)*vd_resol_size(vd), "voxel dataset"); + vd->dataset = MEM_mapallocN(sizeof(float) * vd_resol_size(vd), "voxel dataset"); - for (z=0; z < iuser.frames; z++) { + for (z = 0; z < iuser.frames; z++) { /* get a new ibuf for each frame */ if (z > 0) { iuser.framenr++; - ibuf= BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_get_ibuf(ima, &iuser); if (!ibuf) break; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); } rf = ibuf->rect_float; - for (y=0; y < ibuf->y; y++) { - for (x=0; x < ibuf->x; x++) { + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { /* currently averaged to monchrome */ - vd->dataset[ BLI_VOXEL_INDEX(x, y, z, vd->resol) ] = (rf[0] + rf[1] + rf[2]) * 0.333f; - rf +=4; + vd->dataset[BLI_VOXEL_INDEX(x, y, z, vd->resol)] = (rf[0] + rf[1] + rf[2]) * 0.333f; + rf += 4; } } @@ -198,7 +198,7 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) static int read_voxeldata_header(FILE *fp, struct VoxelData *vd) { - VoxelDataHeader *h=(VoxelDataHeader *)MEM_mallocN(sizeof(VoxelDataHeader), "voxel data header"); + VoxelDataHeader *h = (VoxelDataHeader *)MEM_mallocN(sizeof(VoxelDataHeader), "voxel data header"); rewind(fp); if (fread(h, sizeof(VoxelDataHeader), 1, fp) != 1) { @@ -206,9 +206,9 @@ static int read_voxeldata_header(FILE *fp, struct VoxelData *vd) return 0; } - vd->resol[0]=h->resolX; - vd->resol[1]=h->resolY; - vd->resol[2]=h->resolZ; + vd->resol[0] = h->resolX; + vd->resol[1] = h->resolY; + vd->resol[2] = h->resolZ; MEM_freeN(h); return 1; @@ -221,8 +221,8 @@ static void init_frame_smoke(VoxelData *vd, float cfra) ModifierData *md; vd->dataset = NULL; - if (vd->object == NULL) return; - ob= vd->object; + if (vd->object == NULL) return; + ob = vd->object; /* draw code for smoke */ if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke))) { @@ -231,23 +231,23 @@ static void init_frame_smoke(VoxelData *vd, float cfra) if (smd->domain && smd->domain->fluid) { if (cfra < smd->domain->point_cache[0]->startframe) - ; /* don't show smoke before simulation starts, this could be made an option in the future */ + ; /* don't show smoke before simulation starts, this could be made an option in the future */ else if (vd->smoked_type == TEX_VD_SMOKEHEAT) { size_t totRes; size_t i; float *heat; copy_v3_v3_int(vd->resol, smd->domain->res); - totRes= vd_resol_size(vd); + totRes = vd_resol_size(vd); // scaling heat values from -2.0-2.0 to 0.0-1.0 - vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data"); + vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); heat = smoke_get_heat(smd->domain->fluid); - for (i=0; idataset[i] = (heat[i]+2.0f)/4.0f; + for (i = 0; i < totRes; i++) { + vd->dataset[i] = (heat[i] + 2.0f) / 4.0f; } //vd->dataset = smoke_get_heat(smd->domain->fluid); @@ -258,17 +258,17 @@ static void init_frame_smoke(VoxelData *vd, float cfra) float *xvel, *yvel, *zvel; copy_v3_v3_int(vd->resol, smd->domain->res); - totRes= vd_resol_size(vd); + totRes = vd_resol_size(vd); // scaling heat values from -2.0-2.0 to 0.0-1.0 - vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data"); + vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); xvel = smoke_get_velocity_x(smd->domain->fluid); yvel = smoke_get_velocity_y(smd->domain->fluid); zvel = smoke_get_velocity_z(smd->domain->fluid); - for (i=0; idataset[i] = sqrt(xvel[i]*xvel[i] + yvel[i]*yvel[i] + zvel[i]*zvel[i])*3.0f; + for (i = 0; i < totRes; i++) { + vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; } } @@ -286,10 +286,10 @@ static void init_frame_smoke(VoxelData *vd, float cfra) } /* TODO: is_vd_res_ok(rvd) doesnt check this resolution */ - totRes= vd_resol_size(vd); + totRes = vd_resol_size(vd); /* always store copy, as smoke internal data can change */ - vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data"); - memcpy(vd->dataset, density, sizeof(float)*totRes); + vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); + memcpy(vd->dataset, density, sizeof(float) * totRes); } // end of fluid condition } } @@ -300,7 +300,7 @@ static void init_frame_smoke(VoxelData *vd, float cfra) (void)vd; (void)cfra; - vd->dataset= NULL; + vd->dataset = NULL; #endif } @@ -342,7 +342,7 @@ void cache_voxeldata(Tex *tex, int scene_frame) if (!fp) return; if (read_voxeldata_header(fp, vd)) - load_frame_blendervoxel(vd, fp, curframe-1); + load_frame_blendervoxel(vd, fp, curframe - 1); fclose(fp); return; @@ -362,17 +362,17 @@ void make_voxeldata(struct Render *re) { Tex *tex; - re->i.infostr= "Loading voxel datasets"; + re->i.infostr = "Loading voxel datasets"; re->stats_draw(re->sdh, &re->i); /* XXX: should be doing only textures used in this render */ - for (tex= re->main->tex.first; tex; tex= tex->id.next) { - if (tex->id.us && tex->type==TEX_VOXELDATA) { + for (tex = re->main->tex.first; tex; tex = tex->id.next) { + if (tex->id.us && tex->type == TEX_VOXELDATA) { cache_voxeldata(tex, re->r.cfra); } } - re->i.infostr= NULL; + re->i.infostr = NULL; re->stats_draw(re->sdh, &re->i); } @@ -383,7 +383,7 @@ int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texre VoxelData *vd = tex->vd; float co[3], offset[3] = {0.5, 0.5, 0.5}; - if (vd->dataset==NULL) { + if (vd->dataset == NULL) { texres->tin = 0.0f; return 0; } @@ -448,5 +448,3 @@ int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texre return retval; } - - -- cgit v1.2.3 From cb0b3558af3a5544a08513a7a0a7354502af0eaf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 5 Jun 2012 22:12:17 +0000 Subject: style cleanup --- source/blender/blenkernel/intern/library.c | 2 +- .../blender/gpu/shaders/gpu_shader_material.glsl | 39 +++++++++++----------- source/gameengine/GameLogic/SCA_PropertySensor.cpp | 8 ++--- source/gameengine/GameLogic/SCA_RandomActuator.cpp | 9 ++--- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 4 +-- source/gameengine/VideoTexture/FilterColor.h | 6 ++-- 6 files changed, 33 insertions(+), 35 deletions(-) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 0abeb483745..c81e607ce93 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1142,7 +1142,7 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name) * Normally the ID that's being check is already in the ListBase, so ID *id * points at the new entry. The Python Library module needs to know what * the name of a datablock will be before it is appended; in this case ID *id - * id is NULL; + * id is NULL */ static int check_for_dupid(ListBase *lb, ID *id, char *name) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 65c0bcb3c63..b9bd7e961f8 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1105,7 +1105,7 @@ void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal) // It needs to be done because in Blender // the normal used points inward. // Should this ever change this negate must be removed. - vec4 color = texture2D(ima, texco.xy); + vec4 color = texture2D(ima, texco.xy); normal = 2.0*(vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5)); } @@ -1190,7 +1190,7 @@ void mtex_bump_init_viewspace( vec3 surf_pos, vec3 surf_norm, } void mtex_bump_tap3( vec3 texco, sampler2D ima, float hScale, - out float dBs, out float dBt ) + out float dBs, out float dBt ) { vec2 STll = texco.xy; vec2 STlr = texco.xy + dFdx(texco.xy) ; @@ -1945,22 +1945,23 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) { - /* compute fresnel reflectance without explicitly computing - the refracted direction */ - float c = abs(dot(Incoming, Normal)); - float g = eta * eta - 1.0 + c * c; - float result; - - if(g > 0.0) { - g = sqrt(g); - float A =(g - c)/(g + c); - float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0); - result = 0.5 * A * A *(1.0 + B * B); - } - else - result = 1.0; /* TIR (no refracted component) */ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = abs(dot(Incoming, Normal)); + float g = eta * eta - 1.0 + c * c; + float result; + + if(g > 0.0) { + g = sqrt(g); + float A =(g - c)/(g + c); + float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0); + result = 0.5 * A * A *(1.0 + B * B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } - return result; + return result; } float hypot(float x, float y) @@ -2135,13 +2136,13 @@ void node_tex_environment_empty(vec3 co, out vec4 color) void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) { color = texture2D(ima, co.xy); - alpha = color.a; + alpha = color.a; } void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) { color = vec4(0.0); - alpha = 0.0; + alpha = 0.0; } void node_tex_magic(vec3 p, float scale, float distortion, out vec4 color, out float fac) diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index d0d940a2e42..ce183b37498 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -91,10 +91,10 @@ void SCA_PropertySensor::PrecalculateRangeExpression() //The context is needed to retrieve the property at runtime but it creates //loop of references pars.SetContext(this->AddRef()); - STR_String checkstr = "(" + m_checkpropval + " <= " - + m_checkpropname + ") && ( " - + m_checkpropname + " <= " - + m_checkpropmaxval + ")"; + STR_String checkstr = ("(" + m_checkpropval + " <= " + + m_checkpropname + ") && ( " + + m_checkpropname + " <= " + + m_checkpropmaxval + ")"); m_range_expr = pars.ProcessText(checkstr); } diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 40dba3bf03a..b0fc1431482 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -141,8 +141,7 @@ bool SCA_RandomActuator::Update() int res; /* The [0, 1] interval is projected onto the [min, max+1] domain, */ /* and then rounded. */ - res = (int) floor( ((m_parameter2 - m_parameter1 + 1) * m_base->DrawFloat()) - + m_parameter1); + res = (int)floor( ((m_parameter2 - m_parameter1 + 1) * m_base->DrawFloat()) + m_parameter1); tmpval = new CIntValue(res); } break; @@ -172,8 +171,7 @@ bool SCA_RandomActuator::Update() } break; case KX_RANDOMACT_FLOAT_UNIFORM: { - float res = ((m_parameter2 - m_parameter1) * m_base->DrawFloat()) - + m_parameter1; + float res = ((m_parameter2 - m_parameter1) * m_base->DrawFloat()) + m_parameter1; tmpval = new CFloatValue(res); } break; @@ -239,8 +237,7 @@ bool SCA_RandomActuator::Update() /* controlling parameter. Using the 'normal' exponent is not very */ /* intuitive... */ /* tmpval = new CFloatValue( (1.0 / m_parameter1) */ - tmpval = new CFloatValue( (m_parameter1) - * (-log(1.0 - m_base->DrawFloat())) ); + tmpval = new CFloatValue((m_parameter1) * (-log(1.0 - m_base->DrawFloat()))); } break; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 767d99583b8..343cb549337 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -719,8 +719,8 @@ void CcdPhysicsEnvironment::processFhSprings(double curTime,float interval) { if (ctrl->getConstructionInfo().m_do_fh) { - btVector3 lspot = cl_object->getCenterOfMassPosition() - + rayDirLocal * resultCallback.m_closestHitFraction; + btVector3 lspot = cl_object->getCenterOfMassPosition() + + rayDirLocal * resultCallback.m_closestHitFraction; diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h index 9b1976cf40f..cd61900bbda 100644 --- a/source/gameengine/VideoTexture/FilterColor.h +++ b/source/gameengine/VideoTexture/FilterColor.h @@ -91,9 +91,9 @@ protected: /// calculate one color component unsigned char calcColor (unsigned int val, short idx) { - return (((m_matrix[idx][0] * (VT_R(val)) + m_matrix[idx][1] * (VT_G(val)) - + m_matrix[idx][2] * (VT_B(val)) + m_matrix[idx][3] * (VT_A(val)) - + m_matrix[idx][4]) >> 8) & 0xFF); + return (((m_matrix[idx][0] * (VT_R(val)) + m_matrix[idx][1] * (VT_G(val)) + + m_matrix[idx][2] * (VT_B(val)) + m_matrix[idx][3] * (VT_A(val)) + + m_matrix[idx][4]) >> 8) & 0xFF); } /// filter pixel template, source int buffer -- cgit v1.2.3 From c97c6c013538ab453b4947c862ed1781b533185e Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 5 Jun 2012 22:43:29 +0000 Subject: Smoke: Make Smoke density available to python via rna. --- source/blender/makesrna/intern/CMakeLists.txt | 5 +++ source/blender/makesrna/intern/SConscript | 4 ++ source/blender/makesrna/intern/rna_smoke.c | 58 +++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index e7f9977d040..82c0757456d 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -209,6 +209,10 @@ if(WITH_FFTW3) add_definitions(-DWITH_FFTW3) endif() +if(WITH_MOD_SMOKE) + add_definitions(-DWITH_SMOKE) +endif() + if(WITH_MOD_OCEANSIM) add_definitions(-DWITH_OCEANSIM) endif() @@ -253,6 +257,7 @@ blender_include_dirs( ../../../../intern/cycles/blender ../../../../intern/guardedalloc ../../../../intern/memutil + ../../../../intern/smoke/extern ) blender_include_dirs_sys( diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 99fab18b4bf..d26de50fae0 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -35,7 +35,11 @@ incs += ' ../../windowmanager ../../editors/include ../../blenfont' incs += ' ../../render/extern/include ../../bmesh' incs += ' #/intern/audaspace/intern #/intern/cycles/blender' incs += ' #/extern/glew/include ' +incs += ' #/intern/smoke/extern' +if env['WITH_BF_SMOKE']: + defs.append('WITH_SMOKE') + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 19925546de3..f13f9406689 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -51,6 +51,8 @@ #include "BKE_depsgraph.h" #include "BKE_particle.h" +#include "smoke_API.h" + static void rna_Smoke_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { @@ -111,6 +113,35 @@ static char *rna_SmokeCollSettings_path(PointerRNA *ptr) return BLI_sprintfN("modifiers[\"%s\"].coll_settings", md->name); } +static int rna_SmokeModifier_density_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data; + + if (settings->fluid) + { + float *density = smoke_get_density(settings->fluid); + unsigned int size = settings->res[0] * settings->res[1] * settings->res[2]; + + if(density) + length[0] = size; + else + length[0] = 0; + } + else + length[0] = 0; // No smoke domain created yet + + return length[0]; +} + +static void rna_SmokeModifier_density_get(PointerRNA *ptr, float *values) +{ + SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data; + float *density = smoke_get_density(settings->fluid); + unsigned int size = settings->res[0] * settings->res[1] * settings->res[2]; + + memcpy(values, density, size * sizeof(float)); +} + #else static void rna_def_smoke_domain_settings(BlenderRNA *brna) @@ -282,6 +313,33 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE); + RNA_def_property_array(prop, 32); + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_density_get_length"); + RNA_def_property_float_funcs(prop, "rna_SmokeModifier_density_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Density", "Smoke density"); + + prop = RNA_def_property(srna, "dx", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dx"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "dx", "Cell Size"); + + prop = RNA_def_property(srna, "p0", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "p0"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "p0", "Start point"); + + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "scale", "Domain scale factor"); + + prop = RNA_def_property(srna, "res", PROP_INT, PROP_XYZ); + RNA_def_property_int_sdna(prop, NULL, "res"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "res", "Smoke Grid Resolution"); } static void rna_def_smoke_flow_settings(BlenderRNA *brna) -- cgit v1.2.3 From c17d9532aad5d0d98010a0c1cc0029698a31e908 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 5 Jun 2012 22:50:02 +0000 Subject: Smoke: Fix rna names as suggested by Thomas Dinges. --- source/blender/makesrna/intern/rna_smoke.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index f13f9406689..c0efff2d179 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -321,12 +321,12 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_float_funcs(prop, "rna_SmokeModifier_density_get", NULL, NULL); RNA_def_property_ui_text(prop, "Density", "Smoke density"); - prop = RNA_def_property(srna, "dx", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dx"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "dx", "Cell Size"); - prop = RNA_def_property(srna, "p0", PROP_FLOAT, PROP_XYZ); + prop = RNA_def_property(srna, "start_point", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "p0"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "p0", "Start point"); @@ -336,7 +336,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "scale", "Domain scale factor"); - prop = RNA_def_property(srna, "res", PROP_INT, PROP_XYZ); + prop = RNA_def_property(srna, "domain_resolution", PROP_INT, PROP_XYZ); RNA_def_property_int_sdna(prop, NULL, "res"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "res", "Smoke Grid Resolution"); -- cgit v1.2.3 From 3c85e213db1b33c4cf488f388869ae261f6cdec4 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Wed, 6 Jun 2012 00:03:39 +0000 Subject: Enabling smooth modifier for curves --- source/blender/modifiers/intern/MOD_smooth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 99a5dcb5ef5..1313f5aa3ef 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -244,6 +244,7 @@ ModifierTypeInfo modifierType_Smooth = { /* structSize */ sizeof(SmoothModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, -- cgit v1.2.3 From eedaaee072f7b21f9a1e2d4ed463000b2aacb620 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 05:37:38 +0000 Subject: fix for building without smoke. --- source/blender/blenkernel/intern/smoke.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 7a5465edf02..ebc31517524 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -150,6 +150,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype)) { return NULL; } struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(p0)) { return NULL; } void smoke_free(struct FLUID_3D *UNUSED(fluid)) {} +float *smoke_get_density(struct FLUID_3D *UNUSED(fluid)) { return NULL; } void smoke_turbulence_free(struct WTURBULENCE *UNUSED(wt)) {} void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(strength)) {} void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity), int *UNUSED(border_colli)) {} -- cgit v1.2.3 From 2be904b62687bb8ae9316f1bae678c4d66f10c15 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 06:01:51 +0000 Subject: support negative indexing with SequenceElements.pop() - like python does, -1 is default. --- source/blender/makesrna/intern/rna_sequencer_api.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index bdbd153b1e2..2fb882d96a1 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -327,7 +327,12 @@ static void rna_SequenceElements_pop(ID *id, Sequence *seq, ReportList *reports, return; } - if (seq->len <= index) { + /* python style negative indexing */ + if (index < 0) { + index += seq->len; + } + + if (seq->len <= index || index < 0) { BKE_report(reports, RPT_ERROR, "SequenceElements.pop: index out of range"); return; } @@ -335,6 +340,7 @@ static void rna_SequenceElements_pop(ID *id, Sequence *seq, ReportList *reports, new_seq = MEM_callocN(sizeof(StripElem) * (seq->len - 1), "SequenceElements_pop"); seq->len--; + /* TODO - simply use 2 memcpy calls */ for (i = 0, se = seq->strip->stripdata; i < seq->len; i++, se++) { if (i == index) se++; @@ -394,7 +400,7 @@ void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "pop", "rna_SequenceElements_pop"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Pop an image off the collection"); - parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of image to remove", 0, INT_MAX); + parm = RNA_def_int(func, "index", -1, INT_MIN, INT_MAX, "", "Index of image to remove", INT_MIN, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); } -- cgit v1.2.3 From 5caeeec1fe37bd0d027c85749d43fdaa136894a5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 6 Jun 2012 08:08:54 +0000 Subject: Corrected documentation for intersect_point_quad_2d to match exactly how it works in C side: only convex quads without singularities gives predictable results. --- source/blender/python/mathutils/mathutils_geometry.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index c6bfeff1651..4d05b837952 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -807,6 +807,7 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc, "\n" " Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad, \n" " only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n" +" Works only with convex quads without singular edges." "\n" " :arg pt: Point\n" " :type pt: :class:`mathutils.Vector`\n" -- cgit v1.2.3 From 8b7538ce946b5265bcc065e518716b2ffb9fda53 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 6 Jun 2012 08:33:57 +0000 Subject: Adding back Dutch language, as it seems we found a translator for it. :) --- source/blender/makesrna/intern/rna_userdef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 2df69e78233..84723e95e80 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2984,7 +2984,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) {10, "CATALAN", 0, "Catalan (Català)", "ca_AD"}, {16, "CROATIAN", 0, "Croatian (Hrvatski)", "hr_HR"}, {11, "CZECH", 0, "Czech (Český)", "cs_CZ"}, -/* { 3, "DUTCH", 0, "Dutch (Nederlandse taal)", "nl_NL"}, */ /* XXX No po's yet. */ + { 3, "DUTCH", 0, "Dutch (Nederlandse taal)", "nl_NL"}, { 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"}, { 5, "GERMAN", 0, "German (Deutsch)", "de_DE"}, {23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"}, -- cgit v1.2.3 From 8849a789702a9be0c06ecc850845c3bb3af0d0fd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 6 Jun 2012 10:01:17 +0000 Subject: Added example of basic objects ooperations in Python, liek adding object datablock, adding object, linking it to scene and making selected and active. --- doc/python_api/examples/bpy.types.Object.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 doc/python_api/examples/bpy.types.Object.py diff --git a/doc/python_api/examples/bpy.types.Object.py b/doc/python_api/examples/bpy.types.Object.py new file mode 100644 index 00000000000..5301797aae2 --- /dev/null +++ b/doc/python_api/examples/bpy.types.Object.py @@ -0,0 +1,27 @@ +""" +Basic Object Operations Example ++++++++++++++++++++++++++++++++ +This script demonstrates basic operations on object like creating new +object, placing it into scene, selecting it and making it active +""" + +import bpy +from mathutils import Matrix + +scene = bpy.context.scene + +# Create new lamp datablock +lamp_data = bpy.data.lamps.new(name="New Lamp", type="POINT") + +# Create new object with out lamp datablock +lamp_object = bpy.data.objects.new(name="New Lamp", object_data=lamp_data) + +# Link lamp object to the scene so it'll appear in this scene +scene.objects.link(lamp_object) + +# Place lamp to specified location +lamp_object.location = (5.0, 5.0, 5.0) + +# And finally select it make active +lamp_object.select = True +scene.objects.active = lamp_object -- cgit v1.2.3 From 91beb27500c7afe047cad342efc35eaca7f68517 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Wed, 6 Jun 2012 10:41:49 +0000 Subject: Fix scons + smoke not working. it seems like the definition + include file are needed on the higher level dir too. --- source/blender/makesrna/SConscript | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 2bafc586a58..29910121e2a 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -11,12 +11,15 @@ incs += ' ../windowmanager ../editors/include ../gpu ../imbuf ../ikplugin ../ble incs += ' ../render/extern/include #/intern/cycles/blender' incs += ' ../nodes' incs += ' #/extern/glew/include' +incs += ' #/intern/smoke/extern' incs += ' ../bmesh' - defs = [] +if env['WITH_BF_SMOKE']: + defs.append('WITH_SMOKE') + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') -- cgit v1.2.3 From c6d0ebcdf979f7aa5777e5c579b0d8a3e27c080b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 11:40:01 +0000 Subject: - background images now draw in opengl render - fix bug where forground images could be invisible when clipping was enabled. --- source/blender/editors/include/ED_view3d.h | 2 +- source/blender/editors/space_view3d/space_view3d.c | 2 +- source/blender/editors/space_view3d/view3d_draw.c | 126 ++++++++------------- 3 files changed, 52 insertions(+), 78 deletions(-) diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 55210080e01..34892fb3c27 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -282,7 +282,7 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active); int ED_view3d_context_activate(struct bContext *C); void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, - int winx, int winy, float viewmat[][4], float winmat[][4], int draw_background); + int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic); struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256]); struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, int draw_background, char err_out[256]); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 28fd2c8bc74..a6948222d93 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1016,7 +1016,7 @@ static void space_view3d_listener(struct ScrArea *sa, struct wmNotifier *wmn) break; } - // removed since BKE_image_user_frame_calc is now called in draw_bgpic because screen_ops doesnt call the notifier. + // removed since BKE_image_user_frame_calc is now called in view3d_draw_bgpic because screen_ops doesnt call the notifier. #if 0 if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) { View3D *v3d = area->spacedata.first; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 14afcaa855f..4b484b60ad3 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1528,7 +1528,8 @@ exit: /* ************************************************************* */ -static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int foreground) +static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, + const short do_forground, const short do_camera_frame) { RegionView3D *rv3d = ar->regiondata; BGpic *bgpic; @@ -1537,7 +1538,7 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int foreground) ImBuf *ibuf = NULL, *freeibuf; float vec[4], fac, asp, zoomx, zoomy; float x1, y1, x2, y2, cx, cy; - int fg_flag = foreground ? V3D_BGPIC_FOREGROUND : 0; + int fg_flag = do_forground ? V3D_BGPIC_FOREGROUND : 0; for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { @@ -1560,7 +1561,7 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int foreground) BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0); ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser); } - else { + else if (bgpic->source == V3D_BGPIC_MOVIE) { clip = NULL; if (bgpic->flag & V3D_BGPIC_CAMERACLIP) { @@ -1595,14 +1596,21 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int foreground) IMB_rect_from_float(ibuf); if (rv3d->persp == RV3D_CAMOB) { - rctf vb; - - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); - x1 = vb.xmin; - y1 = vb.ymin; - x2 = vb.xmax; - y2 = vb.ymax; + if (do_camera_frame) { + rctf vb; + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); + x1 = vb.xmin; + y1 = vb.ymin; + x2 = vb.xmax; + y2 = vb.ymax; + } + else { + x1 = ar->winrct.xmin; + y1 = ar->winrct.ymin; + x2 = ar->winrct.xmax; + y2 = ar->winrct.ymax; + } } else { float sco[2]; @@ -1696,7 +1704,8 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int foreground) } } -static void draw_bgpics(Scene *scene, ARegion *ar, View3D *v3d, int foreground) +static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, + const short do_forground, const short do_camera_frame) { RegionView3D *rv3d = ar->regiondata; @@ -1708,11 +1717,11 @@ static void draw_bgpics(Scene *scene, ARegion *ar, View3D *v3d, int foreground) if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { if (rv3d->persp == RV3D_CAMOB) { - draw_bgpic(scene, ar, v3d, foreground); + view3d_draw_bgpic(scene, ar, v3d, do_forground, do_camera_frame); } } else { - draw_bgpic(scene, ar, v3d, foreground); + view3d_draw_bgpic(scene, ar, v3d, do_forground, do_camera_frame); } } @@ -2428,14 +2437,13 @@ static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4], - int draw_background) + int do_bgpic) { RegionView3D *rv3d = ar->regiondata; Base *base; float backcol[3]; int bwinx, bwiny; rcti brect; - ImBuf *bg_ibuf = NULL; glPushMatrix(); @@ -2465,66 +2473,21 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) gpu_update_lamps_shadows(scene, v3d); - /* if scene has got active clip, use it for render backdrop */ - if (draw_background && scene->clip && rv3d->persp == RV3D_CAMOB && v3d->camera) { - MovieClipUser user = {0}; - - BKE_movieclip_user_set_frame(&user, CFRA); - bg_ibuf = BKE_movieclip_get_ibuf(scene->clip, &user); + /* set background color, fallback on the view background color + * (if active clip is set but frame is failed to load fallback to horizon color as background) */ + if (scene->world) { + if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); + else + copy_v3_v3(backcol, &scene->world->horr); + glClearColor(backcol[0], backcol[1], backcol[2], 0.0); } - - if (!bg_ibuf) { - /* set background color, fallback on the view background color - * (if active clip is set but frame is failed to load fallback to horizon color as background) */ - if (scene->world) { - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); - else - copy_v3_v3(backcol, &scene->world->horr); - glClearColor(backcol[0], backcol[1], backcol[2], 0.0); - } - else { - UI_ThemeClearColor(TH_BACK); - } + else { + UI_ThemeClearColor(TH_BACK); } - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (bg_ibuf) { - unsigned char *pixels, *cp, *dst_cp; - int i; - - if (bg_ibuf->rect_float && !bg_ibuf->rect) - IMB_rect_from_float(bg_ibuf); - - dst_cp = pixels = MEM_callocN(4 * sizeof(unsigned char) * bg_ibuf->x * bg_ibuf->y, "draw offscreen clip pixels"); - cp = (unsigned char *)bg_ibuf->rect; - for (i = 0; i < bg_ibuf->x * bg_ibuf->y; i++, cp += 4, dst_cp += 4) { - dst_cp[0] = cp[0]; - dst_cp[1] = cp[1]; - dst_cp[2] = cp[2]; - dst_cp[3] = 255; - } - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - ED_region_pixelspace(ar); - - glPixelZoom((float)winx / bg_ibuf->x, (float)winy / bg_ibuf->y); - glaDrawPixelsTex(0, 0, bg_ibuf->x, bg_ibuf->y, GL_UNSIGNED_BYTE, pixels); - - glPixelZoom(1.0, 1.0); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - IMB_freeImBuf(bg_ibuf); - MEM_freeN(pixels); - } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* setup view matrices */ view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); @@ -2540,6 +2503,11 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, else v3d->zbuf = FALSE; + /* important to do before clipping */ + if (do_bgpic) { + view3d_draw_bgpic_test(scene, ar, v3d, FALSE, FALSE); + } + if (rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_set(rv3d); @@ -2581,6 +2549,11 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, if (rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_disable(); + /* important to do after clipping */ + if (do_bgpic) { + view3d_draw_bgpic_test(scene, ar, v3d, TRUE, FALSE); + } + /* cleanup */ if (v3d->zbuf) { v3d->zbuf = FALSE; @@ -2792,7 +2765,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar) /* render result draw */ if (v3d->flag & V3D_DISPBGPICS) - draw_bgpic(scene, ar, v3d, FALSE); + view3d_draw_bgpic(scene, ar, v3d, FALSE, TRUE); else fdrawcheckerboard(0, 0, ar->winx, ar->winy); @@ -2800,7 +2773,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar) type->view_draw(rv3d->render_engine, C); if (v3d->flag & V3D_DISPBGPICS) - draw_bgpic(scene, ar, v3d, TRUE); + view3d_draw_bgpic(scene, ar, v3d, TRUE, TRUE); return 1; } @@ -2896,7 +2869,7 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const } } - draw_bgpics(scene, ar, v3d, FALSE); + view3d_draw_bgpic_test(scene, ar, v3d, FALSE, TRUE); if (rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_set(rv3d); @@ -2955,8 +2928,6 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const } } - draw_bgpics(scene, ar, v3d, TRUE); - // REEB_draw(); if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { @@ -2976,6 +2947,9 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const if (rv3d->rflag & RV3D_CLIPPING) ED_view3d_clipping_disable(); + /* important to do after clipping */ + view3d_draw_bgpic_test(scene, ar, v3d, TRUE, TRUE); + BIF_draw_manipulator(C); #if 0 -- cgit v1.2.3 From d6ebba4c9e1c0239db34a0fda5ca9ad810ef504e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 12:48:02 +0000 Subject: recalc animated mask deformations on load. --- source/blender/blenkernel/intern/depsgraph.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 53bc9c4cb7e..a1e67ebd414 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -54,6 +54,7 @@ #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -2469,6 +2470,15 @@ void DAG_on_visible_update(Main *bmain, const short do_time) /* hack to get objects updating on layer changes */ DAG_id_type_tag(bmain, ID_OB); + + /* so masks update on load */ + if (bmain->mask.first) { + Mask *mask; + + for (mask = bmain->mask.first; mask; mask = mask->id.next) { + DAG_id_tag_update(&mask->id, 0); + } + } } static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin) -- cgit v1.2.3 From 0499200e39204a349fda12fdd44c409c6e4e6fc8 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 6 Jun 2012 13:30:05 +0000 Subject: Cloth: Add support for "Self Collision Vertex Group". Self collision vertex groups enable artists to exclude selected vertices from getting involved in self collisions. This speeds simulations and it also resolves some self collision issues. --- .../startup/bl_ui/properties_physics_cloth.py | 2 ++ source/blender/blenkernel/BKE_cloth.h | 2 +- source/blender/blenkernel/intern/cloth.c | 14 ++++++++++-- source/blender/blenkernel/intern/collision.c | 4 ++++ source/blender/makesdna/DNA_cloth_types.h | 5 ++++- source/blender/makesrna/intern/rna_cloth.c | 26 ++++++++++++++++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index e313112d61a..0240335c98f 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -145,6 +145,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel): cloth = context.cloth.collision_settings md = context.cloth + ob = context.object layout.active = cloth.use_collision and cloth_panel_enabled(md) @@ -163,6 +164,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel): sub.active = cloth.use_self_collision sub.prop(cloth, "self_collision_quality", slider=True, text="Quality") sub.prop(cloth, "self_distance_min", slider=True, text="Distance") + sub.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="") layout.prop(cloth, "group") diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 378cc72beb1..3475ef532da 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -56,7 +56,7 @@ struct CollisionTree; /* Bits to or into the ClothVertex.flags. */ #define CLOTH_VERT_FLAG_PINNED 1 -#define CLOTH_VERT_FLAG_COLLISION 2 +#define CLOTH_VERT_FLAG_NOSELFCOLL 2 /* vertex NOT used for self collisions */ #define CLOTH_VERT_FLAG_PINNED_EM 3 /** diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index e067b7195ce..b681426f8a7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -143,6 +143,7 @@ void cloth_init(ClothModifierData *clmd ) clmd->coll_parms->collision_list = NULL; clmd->coll_parms->self_loop_count = 1.0; clmd->coll_parms->selfepsilon = 0.75; + clmd->coll_parms->vgroup_selfcol = 0; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. @@ -756,10 +757,12 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*verte int cloth_uses_vgroup(ClothModifierData *clmd) { return (((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) || - (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )) && + (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) || + (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF)) && ((clmd->sim_parms->vgroup_mass>0) || (clmd->sim_parms->vgroup_struct>0)|| - (clmd->sim_parms->vgroup_bend>0))); + (clmd->sim_parms->vgroup_bend>0) || + (clmd->coll_parms->vgroup_selfcol>0))); } /** @@ -815,6 +818,13 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) verts->bend_stiff = dvert->dw [j].weight; } } + + if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { + if ( dvert->dw[j].def_nr == (clmd->coll_parms->vgroup_selfcol-1)) { + if( dvert->dw [j].weight > 0.0) + verts->flags |= CLOTH_VERT_FLAG_NOSELFCOLL; + } + } /* // for later if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_weight-1)) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 32e9dd7508b..44f524304d2 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -840,6 +840,10 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo continue; } } + + if( ( cloth->verts[i].flags & CLOTH_VERT_FLAG_NOSELFCOLL ) || + ( cloth->verts[j].flags & CLOTH_VERT_FLAG_NOSELFCOLL ) ) + continue; sub_v3_v3v3(temp, verts[i].tx, verts[j].tx); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index fd8b08e68c6..b214186fee6 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -83,7 +83,7 @@ typedef struct ClothSimSettings short shapekey_rest; /* vertex group for scaling structural stiffness */ short presets; /* used for presets on GUI */ short reset; - short pad; + short pad; struct EffectorWeights *effector_weights; } ClothSimSettings; @@ -101,6 +101,9 @@ typedef struct ClothCollSettings short self_loop_count; /* How many iterations for the selfcollision loop */ short loop_count; /* How many iterations for the collision loop. */ struct Group *group; /* Only use colliders from this group of objects */ + short vgroup_selfcol; /* vgroup to paint which vertices are used for self collisions */ + short pad; + int pad2; } ClothCollSettings; diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 37795edb884..82a838010f6 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -155,6 +155,25 @@ static void rna_ClothSettings_bend_vgroup_set(PointerRNA *ptr, const char *value rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_bend); } + +static void rna_CollSettings_selfcol_vgroup_get(PointerRNA *ptr, char *value) +{ + ClothCollSettings *coll = (ClothCollSettings *)ptr->data; + rna_object_vgroup_name_index_get(ptr, value, coll->vgroup_selfcol); +} + +static int rna_CollSettings_selfcol_vgroup_length(PointerRNA *ptr) +{ + ClothCollSettings *coll = (ClothCollSettings *)ptr->data; + return rna_object_vgroup_name_index_length(ptr, coll->vgroup_selfcol); +} + +static void rna_CollSettings_selfcol_vgroup_set(PointerRNA *ptr, const char *value) +{ + ClothCollSettings *coll = (ClothCollSettings *)ptr->data; + rna_object_vgroup_name_index_set(ptr, value, &coll->vgroup_selfcol); +} + static PointerRNA rna_ClothSettings_rest_shape_key_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; @@ -523,6 +542,13 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group"); RNA_def_property_update(prop, 0, "rna_cloth_update"); + + prop = RNA_def_property(srna, "vertex_group_self_collisions", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_CollSettings_selfcol_vgroup_get", "rna_CollSettings_selfcol_vgroup_length", + "rna_CollSettings_selfcol_vgroup_set"); + RNA_def_property_ui_text(prop, "Selfcollision Vertex Group", + "Vertex group to define vertices which are not used during self collisions."); + RNA_def_property_update(prop, 0, "rna_cloth_update"); } void RNA_def_cloth(BlenderRNA *brna) -- cgit v1.2.3 From 2cb671591bca571a8a5988c087da2e380d395204 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 14:38:47 +0000 Subject: mask mode - only keyframe selected mask layers - fix for crash in deleting animated mask layers (other than the first) --- source/blender/editors/include/ED_mask.h | 3 ++ source/blender/editors/mask/mask_ops.c | 9 ++-- source/blender/editors/mask/mask_shapekey.c | 59 +++++++++++++++------- source/blender/editors/space_view3d/view3d_draw.c | 11 ++-- .../editors/transform/transform_conversions.c | 2 +- 5 files changed, 57 insertions(+), 27 deletions(-) diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 0c4c2f4788c..0c2f6807632 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -32,6 +32,7 @@ #define __ED_MASK_H__ struct wmKeyConfig; +struct MaskLayer; /* mask_editor.c */ void ED_operatortypes_mask(void); @@ -42,6 +43,8 @@ void ED_operatormacros_mask(void); void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type); /* mask_shapekey.c */ +void ED_mask_layer_shape_auto_key(struct MaskLayer *masklay, const int frame); int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame); +int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame); #endif /* ED_TEXT_H */ diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index c9f2450afc3..599f3371cac 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -753,8 +753,11 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) free_slide_point_data(op->customdata); - if (IS_AUTOKEY_ON(scene)) { - ED_mask_layer_shape_auto_key_all(data->mask, CFRA); + /* dont key sliding feather uw's */ + if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) { + if (IS_AUTOKEY_ON(scene)) { + ED_mask_layer_shape_auto_key(data->masklay, CFRA); + } } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); @@ -880,10 +883,10 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; - int mask_layer_shape_ofs = 0; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; + int mask_layer_shape_ofs = 0; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index 38e8ed627f2..8da083ab400 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -141,23 +141,6 @@ void MASK_OT_shape_key_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -int ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame) -{ - MaskLayer *masklay; - int change = FALSE; - - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskLayerShape *masklay_shape; - - masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, frame); - BKE_mask_layer_shape_from_mask(masklay, masklay_shape); - change = TRUE; - } - - return change; -} - - static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); @@ -249,3 +232,45 @@ void MASK_OT_shape_key_feather_reset(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + + +/* *** Shape Key Utils *** */ + +void ED_mask_layer_shape_auto_key(MaskLayer *masklay, const int frame) +{ + MaskLayerShape *masklay_shape; + + masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, frame); + BKE_mask_layer_shape_from_mask(masklay, masklay_shape); +} + +int ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame) +{ + MaskLayer *masklay; + int change = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + ED_mask_layer_shape_auto_key(masklay, frame); + change = TRUE; + } + + return change; +} + +int ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame) +{ + MaskLayer *masklay; + int change = FALSE; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + + if (!ED_mask_layer_select_check(masklay)) { + continue; + } + + ED_mask_layer_shape_auto_key(masklay, frame); + change = TRUE; + } + + return change; +} diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 4b484b60ad3..c42264e4dac 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -508,8 +508,7 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) } /* set variable axis */ - vert[0][1] = vert[1][1] = - vert[2][0] = vert[3][0] = line; + vert[0][1] = vert[1][1] = vert[2][0] = vert[3][0] = line; glDrawArrays(GL_LINES, 0, 4); } @@ -1606,10 +1605,10 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, y2 = vb.ymax; } else { - x1 = ar->winrct.xmin; - y1 = ar->winrct.ymin; - x2 = ar->winrct.xmax; - y2 = ar->winrct.ymax; + x1 = ar->winrct.xmin; + y1 = ar->winrct.ymin; + x2 = ar->winrct.xmax; + y2 = ar->winrct.ymax; } } else { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 4e78138dd1b..fbbb5bdfae8 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4915,7 +4915,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (IS_AUTOKEY_ON(t->scene)) { Scene *scene = t->scene; - ED_mask_layer_shape_auto_key_all(mask, CFRA); + ED_mask_layer_shape_auto_key_select(mask, CFRA); } } } -- cgit v1.2.3 From 1931aac1f760500446aa5084a50f94b3f3ad8727 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 14:48:39 +0000 Subject: style cleanup: (indentation) --- source/blender/blenkernel/intern/editderivedmesh.c | 4 +- source/blender/blenkernel/intern/mesh.c | 4 +- .../blender/blenkernel/intern/navmesh_conversion.c | 12 +- source/blender/blenlib/intern/freetypefont.c | 2 +- source/blender/blenloader/intern/readfile.c | 4 +- source/blender/editors/sculpt_paint/paint_mask.c | 16 +- source/blender/editors/sculpt_paint/paint_stroke.c | 16 +- source/blender/editors/sculpt_paint/sculpt.c | 16 +- source/blender/editors/space_clip/space_clip.c | 2 +- source/blender/editors/space_logic/logic_window.c | 1804 ++++++++++---------- source/blender/editors/space_view3d/drawobject.c | 2 +- source/blender/editors/transform/transform.c | 2 +- .../editors/transform/transform_conversions.c | 4 +- source/blender/makesrna/intern/rna_access.c | 2 +- source/blender/makesrna/intern/rna_brush.c | 14 +- .../nodes/composite/nodes/node_composite_math.c | 4 +- source/blender/python/intern/bpy_rna.c | 2 +- .../blender/render/intern/source/convertblender.c | 2 +- 18 files changed, 956 insertions(+), 956 deletions(-) diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 335758fec11..32c6caffff7 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -1697,8 +1697,8 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, BM_ITER_MESH_INDEX (eve, &iter, bmdm->tc->bm, BM_VERTS_OF_MESH, i) { DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN, - CustomData_bmesh_get(&bm->vdata, eve->head.data, - CD_MVERT_SKIN)); + CustomData_bmesh_get(&bm->vdata, eve->head.data, + CD_MVERT_SKIN)); } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 5db565d343c..ed93f27fe5c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2041,8 +2041,8 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, int totedge_i, int totface_i, int totloop_i, int totpoly_i, MEdge *medge, MFace *mface, - int *totloop_r, int *totpoly_r, - MLoop **mloop_r, MPoly **mpoly_r) + int *totloop_r, int *totpoly_r, + MLoop **mloop_r, MPoly **mpoly_r) { MFace *mf; MLoop *ml, *mloop; diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index 24382b3bf91..a21878d1d7d 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -307,15 +307,15 @@ struct SortContext static int compareByData(void *ctx, const void * a, const void * b) { return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)a]] - - ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)b]] ); + ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)b]] ); } int buildNavMeshData(const int nverts, const float* verts, - const int ntris, const unsigned short *tris, - const int* recastData, const int* trisToFacesMap, - int *ndtris_r, unsigned short **dtris_r, - int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r, - int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r) + const int ntris, const unsigned short *tris, + const int* recastData, const int* trisToFacesMap, + int *ndtris_r, unsigned short **dtris_r, + int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r, + int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r) { int *trisMapping; diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index da07bb156d7..ef2eb25a891 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -614,7 +614,7 @@ font driver produces such outlines. # \ # - Two "on" points + Two "on" points and two "cubic" point between them diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f9200f83997..f1150d8f00a 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3978,7 +3978,7 @@ static void direct_link_latt(FileData *fd, Lattice *lt) /* ************ READ OBJECT ***************** */ static void lib_link_modifiers__linkModifiers(void *userData, Object *ob, - ID **idpoin) + ID **idpoin) { FileData *fd = userData; @@ -8441,7 +8441,7 @@ static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm) } static void expand_object_expandModifiers(void *userData, Object *UNUSED(ob), - ID **idpoin) + ID **idpoin) { struct { FileData *fd; Main *mainvar; } *data= userData; diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 298ecf764d6..e309bdb99cb 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -61,16 +61,16 @@ #include static void mask_flood_fill_set_elem(float *elem, - PaintMaskFloodMode mode, - float value) + PaintMaskFloodMode mode, + float value) { switch (mode) { - case PAINT_MASK_FLOOD_VALUE: - (*elem) = value; - break; - case PAINT_MASK_INVERT: - (*elem) = 1.0f - (*elem); - break; + case PAINT_MASK_FLOOD_VALUE: + (*elem) = value; + break; + case PAINT_MASK_INVERT: + (*elem) = 1.0f - (*elem); + break; } } diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index e36056e0fd9..b53edeadb51 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -203,10 +203,10 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) && !ELEM4(stroke->brush->sculpt_tool, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_SNAKE_HOOK) && + SCULPT_TOOL_GRAB, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_SNAKE_HOOK) && !(stroke->brush->flag & BRUSH_ANCHORED) && !(stroke->brush->flag & BRUSH_RESTORE_MESH)) { @@ -359,12 +359,12 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf) } static void paint_stroke_add_sample(const Paint *paint, - PaintStroke *stroke, - float x, float y) + PaintStroke *stroke, + float x, float y) { PaintSample *sample = &stroke->samples[stroke->cur_sample]; int max_samples = MIN2(PAINT_MAX_INPUT_SAMPLES, - MAX2(paint->num_input_samples, 1)); + MAX2(paint->num_input_samples, 1)); sample->mouse[0] = x; sample->mouse[1] = y; @@ -377,7 +377,7 @@ static void paint_stroke_add_sample(const Paint *paint, } static void paint_stroke_sample_average(const PaintStroke *stroke, - PaintSample *average) + PaintSample *average) { int i; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 7b8337ff957..e069a6b9663 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -981,8 +981,8 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod /* Calculate primary direction of movement for many brushes */ static void calc_sculpt_normal(Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode, - float an[3]) + PBVHNode **nodes, int totnode, + float an[3]) { const Brush *brush = paint_brush(&sd->paint); const SculptSession *ss = ob->sculpt; @@ -990,8 +990,8 @@ static void calc_sculpt_normal(Sculpt *sd, Object *ob, switch (brush->sculpt_plane) { case SCULPT_DISP_DIR_VIEW: ED_view3d_global_to_vector(ss->cache->vc->rv3d, - ss->cache->vc->rv3d->twmat[3], - an); + ss->cache->vc->rv3d->twmat[3], + an); break; case SCULPT_DISP_DIR_X: @@ -1021,7 +1021,7 @@ static void calc_sculpt_normal(Sculpt *sd, Object *ob, } static void update_sculpt_normal(Sculpt *sd, Object *ob, - PBVHNode **nodes, int totnode) + PBVHNode **nodes, int totnode) { const Brush *brush = paint_brush(&sd->paint); StrokeCache *cache = ob->sculpt->cache; @@ -1056,7 +1056,7 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3]) } static void calc_brush_local_mat(const Brush *brush, Object *ob, - float local_mat[4][4]) + float local_mat[4][4]) { const StrokeCache *cache = ob->sculpt->cache; float tmat[4][4]; @@ -1105,10 +1105,10 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob) StrokeCache *cache = ob->sculpt->cache; if (cache->mirror_symmetry_pass == 0 && - cache->radial_symmetry_pass == 0) + cache->radial_symmetry_pass == 0) { calc_brush_local_mat(paint_brush(&sd->paint), ob, - cache->brush_local_mat); + cache->brush_local_mat); } } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 0cdd7f62c46..92ba194c8e1 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -392,7 +392,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) break; } break; - case NC_SCREEN: + case NC_SCREEN: if (wmn->data == ND_ANIMPLAY) { ED_area_tag_redraw(sa); } diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index dd21fca93ce..0eec61f599e 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -1151,155 +1151,155 @@ static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short uiBut *but; short ysize; const char *str; - + /* yco is at the top of the rect, draw downwards */ - + set_col_sensor(sens->type, 0); - + switch (sens->type) { - case SENS_ALWAYS: + case SENS_ALWAYS: { ysize= 24; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + draw_default_sensor_header(sens, block, xco, yco, width); - + yco-= ysize; - + break; } - case SENS_TOUCH: + case SENS_TOUCH: { - ysize= 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + ysize= 48; + + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + draw_default_sensor_header(sens, block, xco, yco, width); - - ts= sens->data; - + + ts= sens->data; + // uiDefBut(block, TEX, 1, "Property:", xco, yco-22, width, 19, &ts->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property"); uiDefIDPoinBut(block, test_matpoin_but, ID_MA, 1, "MA:", (short)(xco + 10), (short)(yco-44), (short)(width - 20), 19, &ts->ma, "Only look for floors with this Material"); // uiDefButF(block, NUM, 1, "Margin:", xco+width/2, yco-44, width/2, 19, &ts->dist, 0.0, 10.0, 100, 0, "Extra margin (distance) for larger sensitivity"); - yco-= ysize; - break; + yco-= ysize; + break; } - case SENS_COLLISION: + case SENS_COLLISION: { ysize= 48; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + draw_default_sensor_header(sens, block, xco, yco, width); cs= sens->data; - + /* The collision sensor will become a generic collision (i.e. it */ /* absorb the old touch sensor). */ uiDefButBitS(block, TOG, SENS_COLLISION_PULSE, B_REDR, "Pulse", (short)(xco + 10), (short)(yco - 44), - (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, - "Changes to the set of colliding objects generated pulses"); - + (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, + "Changes to the set of colliding objects generated pulses"); + uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P", (short)(xco + 10 + (0.20 * (width-20))), (short)(yco - 44), - (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, - "Toggle collision on material or property"); - + (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, + "Toggle collision on material or property"); + if (cs->mode & SENS_COLLISION_MATERIAL) { uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.40 * (width-20)), - (short)(yco-44), (short)(0.6*(width-20)), 19, &cs->materialName, 0, MAX_NAME, 0, 0, - "Only look for Objects with this material"); + (short)(yco-44), (short)(0.6*(width-20)), 19, &cs->materialName, 0, MAX_NAME, 0, 0, + "Only look for Objects with this material"); } else { uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.40 * (width-20)), (short)(yco-44), - (short)(0.6*(width-20)), 19, &cs->name, 0, MAX_NAME, 0, 0, - "Only look for Objects with this property"); + (short)(0.6*(width-20)), 19, &cs->name, 0, MAX_NAME, 0, 0, + "Only look for Objects with this property"); } - + /* uiDefButS(block, NUM, 1, "Damp:", xco+10+width-90, yco-24, 70, 19, &cs->damp, 0, 250, 0, 0, "For 'damp' time don't detect another collision"); */ - + yco-= ysize; break; } - case SENS_NEAR: + case SENS_NEAR: { ysize= 72; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + draw_default_sensor_header(sens, block, xco, yco, width); ns= sens->data; - + uiDefBut(block, TEX, 1, "Property:", (short)(10+xco), (short)(yco-44), (short)(width-20), 19, - &ns->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property"); + &ns->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property"); uiDefButF(block, NUM, 1, "Dist", (short)(10+xco), (short)(yco-68), (short)((width-22)/2), 19, - &ns->dist, 0.0, 1000.0, 1000, 0, "Trigger distance"); + &ns->dist, 0.0, 1000.0, 1000, 0, "Trigger distance"); uiDefButF(block, NUM, 1, "Reset", (short)(10+xco+(width-22)/2), (short)(yco-68), (short)((width-22)/2), 19, - &ns->resetdist, 0.0, 1000.0, 1000, 0, "Reset distance"); + &ns->resetdist, 0.0, 1000.0, 1000, 0, "Reset distance"); yco-= ysize; break; } - case SENS_RADAR: + case SENS_RADAR: { - ysize= 72; - + ysize= 72; + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + draw_default_sensor_header(sens, block, xco, yco, width); - + rs= sens->data; - + uiDefBut(block, TEX, 1, "Prop:", - (short)(10+xco), (short)(yco-44), (short)(0.7 * (width-20)), 19, - &rs->name, 0, MAX_NAME, 0, 0, - "Only look for Objects with this property"); + (short)(10+xco), (short)(yco-44), (short)(0.7 * (width-20)), 19, + &rs->name, 0, MAX_NAME, 0, 0, + "Only look for Objects with this property"); - str = "Type %t|+X axis %x0|+Y axis %x1|+Z axis %x2|-X axis %x3|-Y axis %x4|-Z axis %x5"; + str = "Type %t|+X axis %x0|+Y axis %x1|+Z axis %x2|-X axis %x3|-Y axis %x4|-Z axis %x5"; uiDefButS(block, MENU, B_REDR, str, - (short)(10+xco+0.7 * (width-20)), (short)(yco-44), (short)(0.3 * (width-22)), 19, - &rs->axis, 2.0, 31, 0, 0, - "Specify along which axis the radar cone is cast"); - + (short)(10+xco+0.7 * (width-20)), (short)(yco-44), (short)(0.3 * (width-22)), 19, + &rs->axis, 2.0, 31, 0, 0, + "Specify along which axis the radar cone is cast"); + uiDefButF(block, NUM, 1, "Ang:", - (short)(10+xco), (short)(yco-68), (short)((width-20)/2), 19, - &rs->angle, 0.0, 179.9, 10, 0, - "Opening angle of the radar cone"); + (short)(10+xco), (short)(yco-68), (short)((width-20)/2), 19, + &rs->angle, 0.0, 179.9, 10, 0, + "Opening angle of the radar cone"); uiDefButF(block, NUM, 1, "Dist:", - (short)(xco+10 + (width-20)/2), (short)(yco-68), (short)((width-20)/2), 19, - &rs->range, 0.01, 10000.0, 100, 0, - "Depth of the radar cone"); + (short)(xco+10 + (width-20)/2), (short)(yco-68), (short)((width-20)/2), 19, + &rs->range, 0.01, 10000.0, 100, 0, + "Depth of the radar cone"); yco-= ysize; break; } - case SENS_KEYBOARD: + case SENS_KEYBOARD: { ks= sens->data; - + /* 5 lines: 120 height */ ysize= (ks->type&1) ? 96:120; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + /* header line */ draw_default_sensor_header(sens, block, xco, yco, width); - + /* part of line 1 */ uiDefBut(block, LABEL, 0, "Key", xco, yco-44, 40, 19, NULL, 0, 0, 0, 0, ""); uiDefButBitS(block, TOG, 1, B_REDR, "All keys", xco+40+(width/2), yco-44, (width/2)-50, 19, - &ks->type, 0, 0, 0, 0, ""); - - + &ks->type, 0, 0, 0, 0, ""); + + if ((ks->type&1)==0) { /* is All Keys option off? */ /* line 2: hotkey and allkeys toggle */ but = uiDefKeyevtButS(block, 0, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code"); uiButSetFunc(but, test_keyboard_event, ks, NULL); - + /* line 3: two key modifyers (qual1, qual2) */ uiDefBut(block, LABEL, 0, "Hold", xco, yco-68, 40, 19, NULL, 0, 0, 0, 0, ""); but = uiDefKeyevtButS(block, 0, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code"); @@ -1307,50 +1307,50 @@ static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short but = uiDefKeyevtButS(block, 0, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code"); uiButSetFunc(but, test_keyboard_event, ks, NULL); } - + /* line 4: toggle property for string logging mode */ uiDefBut(block, TEX, 1, "LogToggle: ", - xco+10, yco-((ks->type&1) ? 68:92), (width-20), 19, - ks->toggleName, 0, MAX_NAME, 0, 0, - "Property that indicates whether to log " - "keystrokes as a string"); - + xco+10, yco-((ks->type&1) ? 68:92), (width-20), 19, + ks->toggleName, 0, MAX_NAME, 0, 0, + "Property that indicates whether to log " + "keystrokes as a string"); + /* line 5: target property for string logging mode */ uiDefBut(block, TEX, 1, "Target: ", - xco+10, yco-((ks->type&1) ? 92:116), (width-20), 19, - ks->targetName, 0, MAX_NAME, 0, 0, - "Property that receives the keystrokes in case " - "a string is logged"); - + xco+10, yco-((ks->type&1) ? 92:116), (width-20), 19, + ks->targetName, 0, MAX_NAME, 0, 0, + "Property that receives the keystrokes in case " + "a string is logged"); + yco-= ysize; break; } - case SENS_PROPERTY: + case SENS_PROPERTY: { ysize= 96; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - + (float)xco+width, (float)yco, 1); + draw_default_sensor_header(sens, block, xco, yco, width); ps= sens->data; - - str= "Type %t|Equal %x0|Not Equal %x1|Interval %x2|Changed %x3"; + + str= "Type %t|Equal %x0|Not Equal %x1|Interval %x2|Changed %x3"; /* str= "Type %t|Equal %x0|Not Equal %x1"; */ uiDefButI(block, MENU, B_REDR, str, xco+30, yco-44, width-60, 19, - &ps->type, 0, 31, 0, 0, "Type"); - + &ps->type, 0, 31, 0, 0, "Type"); + if (ps->type != SENS_PROP_EXPRESSION) { uiDefBut(block, TEX, 1, "Prop: ", xco+30, yco-68, width-60, 19, - ps->name, 0, MAX_NAME, 0, 0, "Property name"); + ps->name, 0, MAX_NAME, 0, 0, "Property name"); } - + if (ps->type == SENS_PROP_INTERVAL) { uiDefBut(block, TEX, 1, "Min: ", xco, yco-92, width/2, 19, - ps->value, 0, MAX_NAME, 0, 0, "check for min value"); + ps->value, 0, MAX_NAME, 0, 0, "check for min value"); uiDefBut(block, TEX, 1, "Max: ", xco+width/2, yco-92, width/2, 19, - ps->maxvalue, 0, MAX_NAME, 0, 0, "check for max value"); + ps->maxvalue, 0, MAX_NAME, 0, 0, "check for max value"); } else if (ps->type == SENS_PROP_CHANGED) { /* pass */ @@ -1359,199 +1359,199 @@ static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short uiDefBut(block, TEX, 1, "Value: ", xco+30, yco-92, width-60, 19, ps->value, 0, MAX_NAME, 0, 0, "check for value"); } - + yco-= ysize; break; } - case SENS_ARMATURE: + case SENS_ARMATURE: { ysize= 70; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - + (float)xco+width, (float)yco, 1); + draw_default_sensor_header(sens, block, xco, yco, width); arm= sens->data; if (ob->type == OB_ARMATURE) { uiBlockBeginAlign(block); but = uiDefBut(block, TEX, 1, "Bone: ", - (xco+10), (yco-44), (width-20)/2, 19, - arm->posechannel, 0, MAX_NAME, 0, 0, - "Bone on which you want to check a constraint"); + (xco+10), (yco-44), (width-20)/2, 19, + arm->posechannel, 0, MAX_NAME, 0, 0, + "Bone on which you want to check a constraint"); uiButSetFunc(but, check_armature_sensor, but, arm); but = uiDefBut(block, TEX, 1, "Cons: ", - (xco+10)+(width-20)/2, (yco-44), (width-20)/2, 19, - arm->constraint, 0, MAX_NAME, 0, 0, - "Name of the constraint you want to control"); + (xco+10)+(width-20)/2, (yco-44), (width-20)/2, 19, + arm->constraint, 0, MAX_NAME, 0, 0, + "Name of the constraint you want to control"); uiButSetFunc(but, check_armature_sensor, but, arm); uiBlockEndAlign(block); - str= "Type %t|State changed %x0|Lin error below %x1|Lin error above %x2|Rot error below %x3|Rot error above %x4"; + str= "Type %t|State changed %x0|Lin error below %x1|Lin error above %x2|Rot error below %x3|Rot error above %x4"; uiDefButI(block, MENU, B_REDR, str, xco+10, yco-66, 0.4*(width-20), 19, - &arm->type, 0, 31, 0, 0, "Type"); - + &arm->type, 0, 31, 0, 0, "Type"); + if (arm->type != SENS_ARM_STATE_CHANGED) { uiDefButF(block, NUM, 1, "Value: ", xco+10+0.4*(width-20), yco-66, 0.6*(width-20), 19, - &arm->value, -10000.0, 10000.0, 100, 0, "Test the error against this value"); + &arm->value, -10000.0, 10000.0, 100, 0, "Test the error against this value"); } } yco-= ysize; break; } - case SENS_ACTUATOR: + case SENS_ACTUATOR: { ysize= 48; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - + (float)xco+width, (float)yco, 1); + draw_default_sensor_header(sens, block, xco, yco, width); as= sens->data; - + uiDefBut(block, TEX, 1, "Act: ", xco+30, yco-44, width-60, 19, - as->name, 0, MAX_NAME, 0, 0, "Actuator name, actuator active state modifications will be detected"); + as->name, 0, MAX_NAME, 0, 0, "Actuator name, actuator active state modifications will be detected"); yco-= ysize; break; } - case SENS_DELAY: + case SENS_DELAY: { ysize= 48; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - + (float)xco+width, (float)yco, 1); + draw_default_sensor_header(sens, block, xco, yco, width); ds = sens->data; - + uiDefButS(block, NUM, 0, "Delay", (short)(10+xco), (short)(yco-44), (short)((width-22)*0.4+10), 19, - &ds->delay, 0.0, 5000.0, 0, 0, "Delay in number of logic tics before the positive trigger (default 60 per second)"); + &ds->delay, 0.0, 5000.0, 0, 0, "Delay in number of logic tics before the positive trigger (default 60 per second)"); uiDefButS(block, NUM, 0, "Dur", (short)(10+xco+(width-22)*0.4+10), (short)(yco-44), (short)((width-22)*0.4-10), 19, - &ds->duration, 0.0, 5000.0, 0, 0, "If >0, delay in number of logic tics before the negative trigger following the positive trigger"); + &ds->duration, 0.0, 5000.0, 0, 0, "If >0, delay in number of logic tics before the negative trigger following the positive trigger"); uiDefButBitS(block, TOG, SENS_DELAY_REPEAT, 0, "REP", (short)(xco + 10 + (width-22)*0.8), (short)(yco - 44), - (short)(0.20 * (width-22)), 19, &ds->flag, 0.0, 0.0, 0, 0, - "Toggle repeat option. If selected, the sensor restarts after Delay+Dur logic tics"); + (short)(0.20 * (width-22)), 19, &ds->flag, 0.0, 0.0, 0, 0, + "Toggle repeat option. If selected, the sensor restarts after Delay+Dur logic tics"); yco-= ysize; break; } - case SENS_MOUSE: + case SENS_MOUSE: { ms= sens->data; /* Two lines: 48 pixels high. */ ysize = 48; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + /* line 1: header */ draw_default_sensor_header(sens, block, xco, yco, width); - + /* Line 2: type selection. The number are a bit mangled to get * proper compatibility with older .blend files. */ /* Any sensor type default is 0 but the ms enum starts in 1. * Therefore the mouse sensor is initialized to 1 in sca.c */ str= "Type %t|Left button %x1|Middle button %x2|" - "Right button %x4|Wheel Up %x5|Wheel Down %x6|Movement %x8|Mouse over %x16|Mouse over any%x32"; + "Right button %x4|Wheel Up %x5|Wheel Down %x6|Movement %x8|Mouse over %x16|Mouse over any%x32"; uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, (width*0.8f)-20, 19, - &ms->type, 0, 31, 0, 0, - "Specify the type of event this mouse sensor should trigger on"); - + &ms->type, 0, 31, 0, 0, + "Specify the type of event this mouse sensor should trigger on"); + if (ms->type==32) { uiDefButBitS(block, TOG, SENS_MOUSE_FOCUS_PULSE, B_REDR, "Pulse", (short)(xco + 10) + (width*0.8f)-20, (short)(yco - 44), - (short)(0.20 * (width-20)), 19, &ms->flag, 0.0, 0.0, 0, 0, - "Moving the mouse over a different object generates a pulse"); + (short)(0.20 * (width-20)), 19, &ms->flag, 0.0, 0.0, 0, 0, + "Moving the mouse over a different object generates a pulse"); } - + yco-= ysize; break; } - case SENS_RANDOM: + case SENS_RANDOM: { ysize = 48; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + draw_default_sensor_header(sens, block, xco, yco, width); randomSensor = sens->data; /* some files were wrongly written, avoid crash now */ if (randomSensor) { uiDefButI(block, NUM, 1, "Seed: ", xco+10, yco-44, (width-20), 19, - &randomSensor->seed, 0, 1000, 0, 0, - "Initial seed of the generator. (Choose 0 for not random)"); + &randomSensor->seed, 0, 1000, 0, 0, + "Initial seed of the generator. (Choose 0 for not random)"); } yco-= ysize; break; } - case SENS_RAY: + case SENS_RAY: { ysize = 72; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + draw_default_sensor_header(sens, block, xco, yco, width); raySens = sens->data; - + /* 1. property or material */ uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P", - xco + 10, yco - 44, 0.20 * (width-20), 19, - &raySens->mode, 0.0, 0.0, 0, 0, - "Toggle collision on material or property"); - + xco + 10, yco - 44, 0.20 * (width-20), 19, + &raySens->mode, 0.0, 0.0, 0, 0, + "Toggle collision on material or property"); + if (raySens->mode & SENS_COLLISION_MATERIAL) { uiDefBut(block, TEX, 1, "Material:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19, - &raySens->matname, 0, MAX_NAME, 0, 0, - "Only look for Objects with this material"); + &raySens->matname, 0, MAX_NAME, 0, 0, + "Only look for Objects with this material"); } else { uiDefBut(block, TEX, 1, "Property:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19, - &raySens->propname, 0, MAX_NAME, 0, 0, - "Only look for Objects with this property"); + &raySens->propname, 0, MAX_NAME, 0, 0, + "Only look for Objects with this property"); } /* X-Ray option */ uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X", - xco + 10, yco - 68, 0.10 * (width-20), 19, - &raySens->mode, 0.0, 0.0, 0, 0, - "Toggle X-Ray option (see through objects that don't have the property)"); + xco + 10, yco - 68, 0.10 * (width-20), 19, + &raySens->mode, 0.0, 0.0, 0, 0, + "Toggle X-Ray option (see through objects that don't have the property)"); /* 2. sensing range */ uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19, - &raySens->range, 0.01, 10000.0, 100, 0, - "Sense objects no farther than this distance"); - + &raySens->range, 0.01, 10000.0, 100, 0, + "Sense objects no farther than this distance"); + /* 3. axis choice */ - str = "Type %t|+ X axis %x1|+ Y axis %x0|+ Z axis %x2|- X axis %x3|- Y axis %x4|- Z axis %x5"; + str = "Type %t|+ X axis %x1|+ Y axis %x0|+ Z axis %x2|- X axis %x3|- Y axis %x4|- Z axis %x5"; uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &raySens->axisflag, 2.0, 31, 0, 0, - "Specify along which axis the ray is cast"); - - yco-= ysize; + &raySens->axisflag, 2.0, 31, 0, 0, + "Specify along which axis the ray is cast"); + + yco-= ysize; break; } - case SENS_MESSAGE: + case SENS_MESSAGE: { mes = sens->data; ysize = 2 * 24; /* total number of lines * 24 pixels/line */ - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - + (float)xco+width, (float)yco, 1); + /* line 1: header line */ draw_default_sensor_header(sens, block, xco, yco, width); - + /* line 2: Subject filter */ uiDefBut(block, TEX, 1, "Subject: ", - (xco+10), (yco-44), (width-20), 19, - mes->subject, 0, MAX_NAME, 0, 0, - "Optional subject filter: only accept messages with this subject" - ", or empty for all"); - + (xco+10), (yco-44), (width-20), 19, + mes->subject, 0, MAX_NAME, 0, 0, + "Optional subject filter: only accept messages with this subject" + ", or empty for all"); + yco -= ysize; break; } @@ -1559,96 +1559,96 @@ static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short { ysize = 72; - + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - + /* line 1: header */ draw_default_sensor_header(sens, block, xco, yco, width); joy= sens->data; uiDefButC(block, NUM, 1, "Index:", xco+10, yco-44, 0.33 * (width-20), 19, - &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, - "Specify which joystick to use"); + &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, + "Specify which joystick to use"); - str= "Type %t|Button %x0|Axis %x1|Single Axis %x3|Hat%x2"; + str= "Type %t|Button %x0|Axis %x1|Single Axis %x3|Hat%x2"; uiDefButC(block, MENU, B_REDR, str, xco+87, yco-44, 0.26 * (width-20), 19, - &joy->type, 0, 31, 0, 0, - "The type of event this joystick sensor is triggered on"); - + &joy->type, 0, 31, 0, 0, + "The type of event this joystick sensor is triggered on"); + if (joy->type != SENS_JOY_AXIS_SINGLE) { if (joy->flag & SENS_JOY_ANY_EVENT) { switch (joy->type) { - case SENS_JOY_AXIS: - str = "All Axis Events"; - break; - case SENS_JOY_BUTTON: - str = "All Button Events"; - break; - default: - str = "All Hat Events"; - break; + case SENS_JOY_AXIS: + str = "All Axis Events"; + break; + case SENS_JOY_BUTTON: + str = "All Button Events"; + break; + default: + str = "All Hat Events"; + break; } } else { str = "All"; } - + uiDefButBitS(block, TOG, SENS_JOY_ANY_EVENT, B_REDR, str, - xco+10 + 0.475 * (width-20), yco-68, ((joy->flag & SENS_JOY_ANY_EVENT) ? 0.525 : 0.12) * (width-20), 19, - &joy->flag, 0, 0, 0, 0, - "Triggered by all events on this joysticks current type (axis/button/hat)"); + xco+10 + 0.475 * (width-20), yco-68, ((joy->flag & SENS_JOY_ANY_EVENT) ? 0.525 : 0.12) * (width-20), 19, + &joy->flag, 0, 0, 0, 0, + "Triggered by all events on this joysticks current type (axis/button/hat)"); } if (joy->type == SENS_JOY_BUTTON) { if ((joy->flag & SENS_JOY_ANY_EVENT)==0) { uiDefButI(block, NUM, 1, "Number:", xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &joy->button, 0, 18, 100, 0, - "Specify which button to use"); + &joy->button, 0, 18, 100, 0, + "Specify which button to use"); } } else if (joy->type == SENS_JOY_AXIS) { uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19, - &joy->axis, 1, 8.0, 100, 0, - "Specify which axis pair to use, 1 is useually the main direction input"); + &joy->axis, 1, 8.0, 100, 0, + "Specify which axis pair to use, 1 is useually the main direction input"); uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20), yco-44, 0.4 * (width-20), 19, - &joy->precision, 0, 32768.0, 100, 0, - "Specify the precision of the axis"); + &joy->precision, 0, 32768.0, 100, 0, + "Specify the precision of the axis"); if ((joy->flag & SENS_JOY_ANY_EVENT)==0) { - str = "Type %t|Up Axis %x1 |Down Axis %x3|Left Axis %x2|Right Axis %x0"; + str = "Type %t|Up Axis %x1 |Down Axis %x3|Left Axis %x2|Right Axis %x0"; uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &joy->axisf, 2.0, 31, 0, 0, - "The direction of the axis, use 'All Events' to receive events on any direction"); + &joy->axisf, 2.0, 31, 0, 0, + "The direction of the axis, use 'All Events' to receive events on any direction"); } } else if (joy->type == SENS_JOY_HAT) { uiDefButI(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19, - &joy->hat, 1, 4.0, 100, 0, - "Specify which hat to use"); - + &joy->hat, 1, 4.0, 100, 0, + "Specify which hat to use"); + if ((joy->flag & SENS_JOY_ANY_EVENT)==0) { - str = "Direction%t|Up%x1|Down%x4|Left%x8|Right%x2|%l|Up/Right%x3|Down/Left%x12|Up/Left%x9|Down/Right%x6"; + str = "Direction%t|Up%x1|Down%x4|Left%x8|Right%x2|%l|Up/Right%x3|Down/Left%x12|Up/Left%x9|Down/Right%x6"; uiDefButI(block, MENU, 0, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &joy->hatf, 2.0, 31, 0, 0, - "The direction of the hat, use 'All Events' to receive events on any direction"); + &joy->hatf, 2.0, 31, 0, 0, + "The direction of the hat, use 'All Events' to receive events on any direction"); } } else { /* (joy->type == SENS_JOY_AXIS_SINGLE)*/ uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19, - &joy->axis_single, 1, 16.0, 100, 0, - "Specify a single axis (verticle/horizontal/other) to detect"); - + &joy->axis_single, 1, 16.0, 100, 0, + "Specify a single axis (verticle/horizontal/other) to detect"); + uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20), yco-44, 0.4 * (width-20), 19, - &joy->precision, 0, 32768.0, 100, 0, - "Specify the precision of the axis"); + &joy->precision, 0, 32768.0, 100, 0, + "Specify the precision of the axis"); } yco-= ysize; break; } } - + return yco-4; } @@ -1859,7 +1859,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo set_col_actuator(act->type, 0); switch (act->type) { - case ACT_OBJECT: + case ACT_OBJECT: { oa = act->data; wval = (width-100)/3; @@ -1890,7 +1890,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiDefButBitS(block, TOG, ACT_DLOC_LOCAL, 0, "L", xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); uiDefButBitS(block, TOG, ACT_DROT_LOCAL, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - + if (ob->gameflag & OB_DYNAMIC) { uiDefBut(block, LABEL, 0, "Force", xco, yco-87, 55, 19, NULL, 0, 0, 0, 0, "Sets the force"); uiBlockBeginAlign(block); @@ -1903,7 +1903,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiBlockBeginAlign(block); uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, ""); uiBlockEndAlign(block); } @@ -1914,14 +1914,14 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, ""); uiBlockEndAlign(block); - + uiDefBut(block, LABEL, 0, "AngV", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity"); uiBlockBeginAlign(block); uiDefButF(block, NUM, 0, "", xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, ""); uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, ""); uiBlockEndAlign(block); - + uiDefBut(block, LABEL, 0, "Damp", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity"); uiDefButS(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); @@ -1929,9 +1929,9 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L", xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-129, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); uiDefButBitS(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-148, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - + uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "use_additive", xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV"); - } + } } else if (oa->type == ACT_OBJECT_SERVO) { ysize= 195; @@ -1984,8 +1984,8 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo yco-= ysize; break; } - case ACT_ACTION: - case ACT_SHAPEACTION: + case ACT_ACTION: + case ACT_SHAPEACTION: { /* DrawAct */ #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR @@ -2010,7 +2010,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+10+ (width/3), yco-24, ((width/3)*2) - (20 + 60), 19, &aa->act, "Action name"); uiDefButBitS(block, TOGN, 1, 0, "Continue", xco+((width/3)*2)+20, yco-24, 60, 19, - &aa->end_reset, 0.0, 0.0, 0, 0, "Restore last frame when switching on/off, otherwise play from the start each time"); + &aa->end_reset, 0.0, 0.0, 0, 0, "Restore last frame when switching on/off, otherwise play from the start each time"); if (aa->type == ACT_ACTION_FROM_PROP) { @@ -2020,7 +2020,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiDefButF(block, NUM, 0, "Sta: ", xco+10, yco-44, (width-20)/2, 19, &aa->sta, 1.0, MAXFRAMEF, 0, 0, "Start frame"); uiDefButF(block, NUM, 0, "End: ", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &aa->end, 1.0, MAXFRAMEF, 0, 0, "End frame"); } - + uiDefButS(block, NUM, 0, "Blendin: ", xco+10, yco-64, (width-20)/2, 19, &aa->blendin, 0.0, 32767, 0.0, 0.0, "Number of frames of motion blending"); uiDefButS(block, NUM, 0, "Priority: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers, With 2 or more actions at once, the overriding channels must be lower in the stack"); @@ -2038,7 +2038,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo yco-=ysize; break; } - case ACT_IPO: + case ACT_IPO: { ia= act->data; @@ -2051,55 +2051,55 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, (width-20)/2, 19, &ia->type, 0, 0, 0, 0, ""); - but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, - "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, - &ia->flag, 0, 0, 0, 0, - "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); + but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, + "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, + &ia->flag, 0, 0, 0, 0, + "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); uiButSetFunc(but, change_ipo_actuator, but, ia); - but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, - "Add", xco+3*(width-20)/4, yco-24, (width-20)/4-10, 19, - &ia->flag, 0, 0, 0, 0, - "Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag"); + but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, + "Add", xco+3*(width-20)/4, yco-24, (width-20)/4-10, 19, + &ia->flag, 0, 0, 0, 0, + "Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag"); uiButSetFunc(but, change_ipo_actuator, but, ia); /* Only show the do-force-local toggle if force is requested */ if (ia->flag & (ACT_IPOFORCE|ACT_IPOADD)) { - uiDefButBitS(block, TOG, ACT_IPOLOCAL, 0, - "L", xco+width-30, yco-24, 20, 19, - &ia->flag, 0, 0, 0, 0, - "Let the ipo acts in local coordinates, used in Force and Add mode"); + uiDefButBitS(block, TOG, ACT_IPOLOCAL, 0, + "L", xco+width-30, yco-24, 20, 19, + &ia->flag, 0, 0, 0, 0, + "Let the ipo acts in local coordinates, used in Force and Add mode"); } if (ia->type==ACT_IPO_FROM_PROP) { - uiDefBut(block, TEX, 0, - "Prop: ", xco+10, yco-44, width-80, 19, - ia->name, 0.0, MAX_NAME, 0, 0, - "Use this property to define the Ipo position"); + uiDefBut(block, TEX, 0, + "Prop: ", xco+10, yco-44, width-80, 19, + ia->name, 0.0, MAX_NAME, 0, 0, + "Use this property to define the Ipo position"); } else { - uiDefButF(block, NUM, 0, - "Sta", xco+10, yco-44, (width-80)/2, 19, - &ia->sta, 1.0, MAXFRAMEF, 0, 0, - "Start frame"); - uiDefButF(block, NUM, 0, - "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, - &ia->end, 1.0, MAXFRAMEF, 0, 0, - "End frame"); + uiDefButF(block, NUM, 0, + "Sta", xco+10, yco-44, (width-80)/2, 19, + &ia->sta, 1.0, MAXFRAMEF, 0, 0, + "Start frame"); + uiDefButF(block, NUM, 0, + "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, + &ia->end, 1.0, MAXFRAMEF, 0, 0, + "End frame"); } - uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, - "Child", xco+10+(width-80), yco-44, 60, 19, - &ia->flag, 0, 0, 0, 0, - "Update IPO on all children Objects as well"); - uiDefBut(block, TEX, 0, - "FrameProp: ", xco+10, yco-64, width-20, 19, - ia->frameProp, 0.0, MAX_NAME, 0, 0, - "Assign the action's current frame number to this property"); + uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, + "Child", xco+10+(width-80), yco-44, 60, 19, + &ia->flag, 0, 0, 0, 0, + "Update IPO on all children Objects as well"); + uiDefBut(block, TEX, 0, + "FrameProp: ", xco+10, yco-64, width-20, 19, + ia->frameProp, 0.0, MAX_NAME, 0, 0, + "Assign the action's current frame number to this property"); yco-= ysize; break; } - case ACT_PROPERTY: + case ACT_PROPERTY: { ysize= 68; @@ -2129,7 +2129,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo break; } - case ACT_SOUND: + case ACT_SOUND: { sa = act->data; sa->sndnr = 0; @@ -2193,743 +2193,743 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo } } MEM_freeN((void *)str); - } + } else { uiDefButO(block, BUT, "sound.open", 0, "Load Sound", xco+10, yco-22, width-20, 19, "Load a sound file"); } - + yco-= ysize; break; } - case ACT_CAMERA: + case ACT_CAMERA: - ysize= 48; + ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - ca= act->data; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-24, (width-20)/2, 19, &(ca->ob), "Look at this Object"); - uiDefButF(block, NUM, 0, "Height:", xco+10+(width-20)/2, yco-24, (width-20)/2, 19, &ca->height, 0.0, 20.0, 0, 0, ""); - - uiDefButF(block, NUM, 0, "Min:", xco+10, yco-44, (width-60)/2, 19, &ca->min, 0.0, 20.0, 0, 0, ""); - - if (ca->axis==0) ca->axis= 'x'; - uiDefButS(block, ROW, 0, "X", xco+10+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'x', 0, 0, "Camera tries to get behind the X axis"); - uiDefButS(block, ROW, 0, "Y", xco+30+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'y', 0, 0, "Camera tries to get behind the Y axis"); - - uiDefButF(block, NUM, 0, "Max:", xco+20+(width)/2, yco-44, (width-60)/2, 19, &ca->max, 0.0, 20.0, 0, 0, ""); + ca= act->data; - yco-= ysize; + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-24, (width-20)/2, 19, &(ca->ob), "Look at this Object"); + uiDefButF(block, NUM, 0, "Height:", xco+10+(width-20)/2, yco-24, (width-20)/2, 19, &ca->height, 0.0, 20.0, 0, 0, ""); - break; + uiDefButF(block, NUM, 0, "Min:", xco+10, yco-44, (width-60)/2, 19, &ca->min, 0.0, 20.0, 0, 0, ""); - case ACT_EDIT_OBJECT: - - eoa= act->data; + if (ca->axis==0) ca->axis= 'x'; + uiDefButS(block, ROW, 0, "X", xco+10+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'x', 0, 0, "Camera tries to get behind the X axis"); + uiDefButS(block, ROW, 0, "Y", xco+30+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'y', 0, 0, "Camera tries to get behind the Y axis"); - if (eoa->type==ACT_EDOB_ADD_OBJECT) { - ysize = 92; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + uiDefButF(block, NUM, 0, "Max:", xco+20+(width)/2, yco-44, (width-60)/2, 19, &ca->max, 0.0, 20.0, 0, 0, ""); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object and all its children (cant be on an visible layer)"); - uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives"); - - wval= (width-60)/3; - uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19, - NULL, 0, 0, 0, 0, - "Velocity upon creation"); - uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19, - eoa->linVelocity, -100.0, 100.0, 10, 0, - "Velocity upon creation, x component"); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19, - eoa->linVelocity+1, -100.0, 100.0, 10, 0, - "Velocity upon creation, y component"); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, - eoa->linVelocity+2, -100.0, 100.0, 10, 0, - "Velocity upon creation, z component"); - uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19, - &eoa->localflag, 0.0, 0.0, 0, 0, - "Apply the transformation locally"); - - - uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19, - NULL, 0, 0, 0, 0, - "Angular velocity upon creation"); - uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19, - eoa->angVelocity, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, x component"); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19, - eoa->angVelocity+1, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, y component"); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19, - eoa->angVelocity+2, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, z component"); - uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19, - &eoa->localflag, 0.0, 0.0, 0, 0, - "Apply the rotation locally"); - + yco-= ysize; - } - else if (eoa->type==ACT_EDOB_END_OBJECT) { - ysize= 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (eoa->type==ACT_EDOB_REPLACE_MESH) { - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, 1, "ME:", xco+40, yco-44, (width-80)/2, 19, &(eoa->me), "replace the existing, when left blank 'Phys' will remake the existing physics mesh"); - - uiDefButBitS(block, TOGN, ACT_EDOB_REPLACE_MESH_NOGFX, 0, "Gfx", xco+40 + (width-80)/2, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the display mesh"); - uiDefButBitS(block, TOG, ACT_EDOB_REPLACE_MESH_PHYS, 0, "Phys", xco+40 + (width-80)/2 +(width-80)/4, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the physics mesh (triangle bounds only. compound shapes not supported)"); - } - else if (eoa->type==ACT_EDOB_TRACK_TO) { - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Track to this Object"); - uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes"); - uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking"); - } - else if (eoa->type==ACT_EDOB_DYNAMICS) { - ysize= 69; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3|Set Mass %x4"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, ""); - if (eoa->dyn_operation==4) { - uiDefButF(block, NUM, 0, "", xco+40, yco-63, width-80, 19, - &eoa->mass, 0.0, 10000.0, 10, 0, - "Mass for object"); - } - } - str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, ""); + break; - yco-= ysize; + case ACT_EDIT_OBJECT: - break; + eoa= act->data; - case ACT_CONSTRAINT: - coa= act->data; - - if (coa->type == ACT_CONST_TYPE_LOC) { - ysize= 69; + if (eoa->type==ACT_EDOB_ADD_OBJECT) { + ysize = 92; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object and all its children (cant be on an visible layer)"); + uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives"); + + wval= (width-60)/3; + uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19, + NULL, 0, 0, 0, 0, + "Velocity upon creation"); + uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19, + eoa->linVelocity, -100.0, 100.0, 10, 0, + "Velocity upon creation, x component"); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19, + eoa->linVelocity+1, -100.0, 100.0, 10, 0, + "Velocity upon creation, y component"); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, + eoa->linVelocity+2, -100.0, 100.0, 10, 0, + "Velocity upon creation, z component"); + uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19, + &eoa->localflag, 0.0, 0.0, 0, 0, + "Apply the transformation locally"); + + + uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19, + NULL, 0, 0, 0, 0, + "Angular velocity upon creation"); + uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19, + eoa->angVelocity, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, x component"); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19, + eoa->angVelocity+1, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, y component"); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19, + eoa->angVelocity+2, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, z component"); + uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19, + &eoa->localflag, 0.0, 0.0, 0, 0, + "Apply the rotation locally"); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - /* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */ - /* coa->flag &= ~(63); */ - str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4"; - coa->flag &= 7; - coa->time = 0; - uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, ""); - - uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); - uiDefBut(block, LABEL, 0, "Min", xco+80, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Max", xco+80+(width-90)/2, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, ""); - - if (coa->flag & ACT_CONST_LOCX) fp= coa->minloc; - else if (coa->flag & ACT_CONST_LOCY) fp= coa->minloc+1; - else if (coa->flag & ACT_CONST_LOCZ) fp= coa->minloc+2; - else if (coa->flag & ACT_CONST_ROTX) fp= coa->minrot; - else if (coa->flag & ACT_CONST_ROTY) fp= coa->minrot+1; - else fp= coa->minrot+2; - - uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-90)/2, 19, fp, -2000.0, 2000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+80+(width-90)/2, yco-65, (width-90)/2, 19, fp+3, -2000.0, 2000.0, 10, 0, ""); - } - else if (coa->type == ACT_CONST_TYPE_DIST) { - ysize= 106; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray"); - - uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); - uiDefBut(block, LABEL, 0, "Range", xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray"); - uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist", xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray"); - uiDefButBitS(block, TOG, ACT_CONST_LOCAL, 0, "L", xco+80+(width-115), yco-45, 25, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Set ray along object's axis or global axis"); - - if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc; - else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1; - else fp= coa->minloc+2; - - uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/2, 19, fp+3, 0.0, 2000.0, 10, 0, "Maximum length of ray"); - if (coa->flag & ACT_CONST_DISTANCE) - uiDefButF(block, NUM, 0, "", xco+80+(width-115)/2, yco-65, (width-115)/2, 19, fp, -2000.0, 2000.0, 10, 0, "Keep this distance to target"); - uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Set object axis along (local axis) or parallel (global axis) to the normal at hit position"); - uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property"); - if (coa->flag & ACT_CONST_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detects only Objects with this material"); } - else { - uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detect only Objects with this property"); + else if (eoa->type==ACT_EDOB_END_OBJECT) { + ysize= 28; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); } - uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target"); - uiDefButS(block, NUM, 0, "time", xco+50, yco-103, (width-60)/2, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); - uiDefButS(block, NUM, 0, "rotDamp", xco+50+(width-60)/2, yco-103, (width-60)/2, 19, &(coa->rotdamp), 0.0, 100.0, 0, 0, "Use a different damping for orientation"); - } - else if (coa->type == ACT_CONST_TYPE_ORI) { - ysize= 87; + else if (eoa->type==ACT_EDOB_REPLACE_MESH) { + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Select the axis to be aligned along the reference direction"); - - uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); - uiDefBut(block, LABEL, 0, "X", xco+80, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Y", xco+80+(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Z", xco+80+2*(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/3, 19, &coa->maxrot[0], -2000.0, 2000.0, 10, 0, "X component of reference direction"); - uiDefButF(block, NUM, 0, "", xco+80+(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[1], -2000.0, 2000.0, 10, 0, "Y component of reference direction"); - uiDefButF(block, NUM, 0, "", xco+80+2*(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[2], -2000.0, 2000.0, 10, 0, "Z component of reference direction"); - - uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); - uiDefButF(block, NUM, 0, "min", xco+80, yco-84, (width-115)/2, 19, &(coa->minloc[0]), 0.0, 180.0, 10, 1, "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max"); - uiDefButF(block, NUM, 0, "max", xco+80+(width-115)/2, yco-84, (width-115)/2, 19, &(coa->maxloc[0]), 0.0, 180.0, 10, 1, "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max"); - } - else if (coa->type == ACT_CONST_TYPE_FH) { - ysize= 106; + uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, 1, "ME:", xco+40, yco-44, (width-80)/2, 19, &(eoa->me), "replace the existing, when left blank 'Phys' will remake the existing physics mesh"); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray (in world coordinate)"); - - if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc; - else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1; - else fp= coa->minloc+2; - - uiDefButF(block, NUM, 0, "damp", xco+10, yco-45, (width-70)/2, 19, &coa->maxrot[0], 0.0, 1.0, 1, 0, "Damping factor of the Fh spring force"); - uiDefButF(block, NUM, 0, "dist", xco+10+(width-70)/2, yco-45, (width-70)/2, 19, fp, 0.010, 2000.0, 10, 0, "Height of the Fh area"); - uiDefButBitS(block, TOG, ACT_CONST_DOROTFH, 0, "Rot Fh", xco+10+(width-70), yco-45, 50, 19, &coa->flag, 0.0, 0.0, 0, 0, "Keep object axis parallel to normal"); - - uiDefButF(block, NUMSLI, 0, "Fh ", xco+80, yco-65, (width-115), 19, fp+3, 0.0, 1.0, 0, 0, "Spring force within the Fh area"); - uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Add a horizontal spring force on slopes"); - uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property"); - if (coa->flag & ACT_CONST_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detects only Objects with this material"); + uiDefButBitS(block, TOGN, ACT_EDOB_REPLACE_MESH_NOGFX, 0, "Gfx", xco+40 + (width-80)/2, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the display mesh"); + uiDefButBitS(block, TOG, ACT_EDOB_REPLACE_MESH_PHYS, 0, "Phys", xco+40 + (width-80)/2 +(width-80)/4, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the physics mesh (triangle bounds only. compound shapes not supported)"); } - else { - uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detect only Objects with this property"); + else if (eoa->type==ACT_EDOB_TRACK_TO) { + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Track to this Object"); + uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes"); + uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking"); } - uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target"); - uiDefButS(block, NUM, 0, "time", xco+50, yco-103, 90, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); - uiDefButF(block, NUM, 0, "rotDamp", xco+140, yco-103, (width-150), 19, &coa->maxrot[1], 0.0, 1.0, 1, 0, "Use a different damping for rotation"); - } - str= "Constraint Type %t|Location %x0|Distance %x1|Orientation %x2|Force field %x3"; - but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &coa->type, 0.0, 0.0, 0, 0, ""); - yco-= ysize; - break; + else if (eoa->type==ACT_EDOB_DYNAMICS) { + ysize= 69; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - case ACT_SCENE: - sca= act->data; - - if (sca->type==ACT_SCENE_RESTART) { - ysize= 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (sca->type==ACT_SCENE_CAMERA) { + str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3|Set Mass %x4"; + uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, ""); + if (eoa->dyn_operation==4) { + uiDefButF(block, NUM, 0, "", xco+40, yco-63, width-80, 19, + &eoa->mass, 0.0, 10000.0, 10, 0, + "Mass for object"); + } + } + str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4"; + uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, ""); - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + yco-= ysize; - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+40, yco-44, (width-80), 19, &(sca->camera), "Set this Camera. Leave empty to refer to self object"); - } - else if (sca->type==ACT_SCENE_SET) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + break; - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Set this Scene"); - } - else if (sca->type==ACT_SCENE_ADD_FRONT) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + case ACT_CONSTRAINT: + coa= act->data; - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add an Overlay Scene"); - } - else if (sca->type==ACT_SCENE_ADD_BACK) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + if (coa->type == ACT_CONST_TYPE_LOC) { + ysize= 69; - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add a Background Scene"); - } - else if (sca->type==ACT_SCENE_REMOVE) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Remove a Scene"); - } - else if (sca->type==ACT_SCENE_SUSPEND) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + /* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */ + /* coa->flag &= ~(63); */ + str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4"; + coa->flag &= 7; + coa->time = 0; + uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, ""); + + uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); + uiDefBut(block, LABEL, 0, "Min", xco+80, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Max", xco+80+(width-90)/2, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, ""); + + if (coa->flag & ACT_CONST_LOCX) fp= coa->minloc; + else if (coa->flag & ACT_CONST_LOCY) fp= coa->minloc+1; + else if (coa->flag & ACT_CONST_LOCZ) fp= coa->minloc+2; + else if (coa->flag & ACT_CONST_ROTX) fp= coa->minrot; + else if (coa->flag & ACT_CONST_ROTY) fp= coa->minrot+1; + else fp= coa->minrot+2; + + uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-90)/2, 19, fp, -2000.0, 2000.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "", xco+80+(width-90)/2, yco-65, (width-90)/2, 19, fp+3, -2000.0, 2000.0, 10, 0, ""); + } + else if (coa->type == ACT_CONST_TYPE_DIST) { + ysize= 106; - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Pause a Scene"); - } - else if (sca->type==ACT_SCENE_RESUME) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Unpause a Scene"); - } + str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32"; + uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray"); + + uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); + uiDefBut(block, LABEL, 0, "Range", xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray"); + uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist", xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray"); + uiDefButBitS(block, TOG, ACT_CONST_LOCAL, 0, "L", xco+80+(width-115), yco-45, 25, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Set ray along object's axis or global axis"); + + if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc; + else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1; + else fp= coa->minloc+2; + + uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/2, 19, fp+3, 0.0, 2000.0, 10, 0, "Maximum length of ray"); + if (coa->flag & ACT_CONST_DISTANCE) + uiDefButF(block, NUM, 0, "", xco+80+(width-115)/2, yco-65, (width-115)/2, 19, fp, -2000.0, 2000.0, 10, 0, "Keep this distance to target"); + uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Set object axis along (local axis) or parallel (global axis) to the normal at hit position"); + uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property"); + if (coa->flag & ACT_CONST_MATERIAL) { + uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19, + coa->matprop, 0, MAX_NAME, 0, 0, + "Ray detects only Objects with this material"); + } + else { + uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19, + coa->matprop, 0, MAX_NAME, 0, 0, + "Ray detect only Objects with this property"); + } + uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target"); + uiDefButS(block, NUM, 0, "time", xco+50, yco-103, (width-60)/2, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); + uiDefButS(block, NUM, 0, "rotDamp", xco+50+(width-60)/2, yco-103, (width-60)/2, 19, &(coa->rotdamp), 0.0, 100.0, 0, 0, "Use a different damping for orientation"); + } + else if (coa->type == ACT_CONST_TYPE_ORI) { + ysize= 87; + + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - str= "Scene %t|Restart %x0|Set Scene %x1|Set Camera %x2|Add OverlayScene %x3|Add BackgroundScene %x4|Remove Scene %x5|Suspend Scene %x6|Resume Scene %x7"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &sca->type, 0.0, 0.0, 0, 0, ""); + str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4"; + uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Select the axis to be aligned along the reference direction"); - yco-= ysize; - break; - case ACT_GAME: + uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); + uiDefBut(block, LABEL, 0, "X", xco+80, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Y", xco+80+(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Z", xco+80+2*(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/3, 19, &coa->maxrot[0], -2000.0, 2000.0, 10, 0, "X component of reference direction"); + uiDefButF(block, NUM, 0, "", xco+80+(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[1], -2000.0, 2000.0, 10, 0, "Y component of reference direction"); + uiDefButF(block, NUM, 0, "", xco+80+2*(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[2], -2000.0, 2000.0, 10, 0, "Z component of reference direction"); + + uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); + uiDefButF(block, NUM, 0, "min", xco+80, yco-84, (width-115)/2, 19, &(coa->minloc[0]), 0.0, 180.0, 10, 1, "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max"); + uiDefButF(block, NUM, 0, "max", xco+80+(width-115)/2, yco-84, (width-115)/2, 19, &(coa->maxloc[0]), 0.0, 180.0, 10, 1, "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max"); + } + else if (coa->type == ACT_CONST_TYPE_FH) { + ysize= 106; + + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32"; + uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray (in world coordinate)"); + + if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc; + else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1; + else fp= coa->minloc+2; + + uiDefButF(block, NUM, 0, "damp", xco+10, yco-45, (width-70)/2, 19, &coa->maxrot[0], 0.0, 1.0, 1, 0, "Damping factor of the Fh spring force"); + uiDefButF(block, NUM, 0, "dist", xco+10+(width-70)/2, yco-45, (width-70)/2, 19, fp, 0.010, 2000.0, 10, 0, "Height of the Fh area"); + uiDefButBitS(block, TOG, ACT_CONST_DOROTFH, 0, "Rot Fh", xco+10+(width-70), yco-45, 50, 19, &coa->flag, 0.0, 0.0, 0, 0, "Keep object axis parallel to normal"); + + uiDefButF(block, NUMSLI, 0, "Fh ", xco+80, yco-65, (width-115), 19, fp+3, 0.0, 1.0, 0, 0, "Spring force within the Fh area"); + uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Add a horizontal spring force on slopes"); + uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property"); + if (coa->flag & ACT_CONST_MATERIAL) { + uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19, + coa->matprop, 0, MAX_NAME, 0, 0, + "Ray detects only Objects with this material"); + } + else { + uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19, + coa->matprop, 0, MAX_NAME, 0, 0, + "Ray detect only Objects with this property"); + } + uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19, + &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target"); + uiDefButS(block, NUM, 0, "time", xco+50, yco-103, 90, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); + uiDefButF(block, NUM, 0, "rotDamp", xco+140, yco-103, (width-150), 19, &coa->maxrot[1], 0.0, 1.0, 1, 0, "Use a different damping for rotation"); + } + str= "Constraint Type %t|Location %x0|Distance %x1|Orientation %x2|Force field %x3"; + but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &coa->type, 0.0, 0.0, 0, 0, ""); + yco-= ysize; + break; + + case ACT_SCENE: + sca= act->data; + + if (sca->type==ACT_SCENE_RESTART) { + ysize= 28; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + } + else if (sca->type==ACT_SCENE_CAMERA) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+40, yco-44, (width-80), 19, &(sca->camera), "Set this Camera. Leave empty to refer to self object"); + } + else if (sca->type==ACT_SCENE_SET) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Set this Scene"); + } + else if (sca->type==ACT_SCENE_ADD_FRONT) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add an Overlay Scene"); + } + else if (sca->type==ACT_SCENE_ADD_BACK) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add a Background Scene"); + } + else if (sca->type==ACT_SCENE_REMOVE) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Remove a Scene"); + } + else if (sca->type==ACT_SCENE_SUSPEND) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Pause a Scene"); + } + else if (sca->type==ACT_SCENE_RESUME) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Unpause a Scene"); + } + + str= "Scene %t|Restart %x0|Set Scene %x1|Set Camera %x2|Add OverlayScene %x3|Add BackgroundScene %x4|Remove Scene %x5|Suspend Scene %x6|Resume Scene %x7"; + uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &sca->type, 0.0, 0.0, 0, 0, ""); + + yco-= ysize; + break; + case ACT_GAME: { gma = act->data; if (gma->type == ACT_GAME_LOAD) { //ysize = 68; ysize = 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this blend file, use the \"//\" prefix for a path relative to the current blend file"); -// uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation"); + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this blend file, use the \"//\" prefix for a path relative to the current blend file"); + // uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation"); } #if 0 else if (gma->type == ACT_GAME_START) { - ysize = 68; - glRects(xco, yco-ysize, xco+width, yco); + ysize = 68; + glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this file"); + uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this file"); uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation"); } #endif else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) { - ysize = 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + ysize = 28; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); } //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3"; str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save bge.logic.globalDict %x4|Load bge.logic.globalDict %x5"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); + uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); - yco -= ysize; - break; + yco -= ysize; + break; } - case ACT_GROUP: - ga= act->data; + case ACT_GROUP: + ga= act->data; - ysize= 52; + ysize= 52; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "GroupKey types %t|Set Key %x6|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x5"; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefButS(block, MENU, 1, str, xco+20, yco-24, width-40, 19, &ga->type, 0, 0, 0, 0, ""); - if (ga->type==ACT_GROUP_SET) { - uiDefBut(block, TEX, 0, "Key: ", xco+20, yco-44, (width-10)/2, 19, ga->name, 0.0, MAX_NAME, 0, 0, "This name defines groupkey to be set"); - uiDefButI(block, NUM, 0, "Frame:", xco+20+(width-10)/2, yco-44, (width-70)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Set this frame"); - } - else if (ga->type==ACT_GROUP_FROM_PROP) { - uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-44, width-40, 19, ga->name, 0.0, MAX_NAME, 0, 0, "Use this property to define the Group position"); - } - else { - uiDefButI(block, NUM, 0, "State", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame"); - uiDefButI(block, NUM, 0, "End", xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame"); - } - yco-= ysize; - break; + str= "GroupKey types %t|Set Key %x6|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x5"; - case ACT_VISIBILITY: - ysize = 24; + uiDefButS(block, MENU, 1, str, xco+20, yco-24, width-40, 19, &ga->type, 0, 0, 0, 0, ""); + if (ga->type==ACT_GROUP_SET) { + uiDefBut(block, TEX, 0, "Key: ", xco+20, yco-44, (width-10)/2, 19, ga->name, 0.0, MAX_NAME, 0, 0, "This name defines groupkey to be set"); + uiDefButI(block, NUM, 0, "Frame:", xco+20+(width-10)/2, yco-44, (width-70)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Set this frame"); + } + else if (ga->type==ACT_GROUP_FROM_PROP) { + uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-44, width-40, 19, ga->name, 0.0, MAX_NAME, 0, 0, "Use this property to define the Group position"); + } + else { + uiDefButI(block, NUM, 0, "State", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame"); + uiDefButI(block, NUM, 0, "End", xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame"); + } + yco-= ysize; + break; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, - (float)yco-ysize, (float)xco+width, (float)yco, 1); - - visAct = act->data; + case ACT_VISIBILITY: + ysize = 24; - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGN, ACT_VISIBILITY_INVISIBLE, B_REDR, - "Visible", - xco + 10, yco - 20, (width - 20)/3, 19, &visAct->flag, - 0.0, 0.0, 0, 0, - "Set the objects visible. Initialized from the objects render restriction toggle (access in the outliner)"); - uiDefButBitI(block, TOG, ACT_VISIBILITY_OCCLUSION, B_REDR, - "Occlusion", - xco + 10 + ((width - 20)/3), yco - 20, (width - 20)/3, 19, &visAct->flag, - 0.0, 0.0, 0, 0, - "Set the object to occlude objects behind it. Initialized from the object type in physics button"); - uiBlockEndAlign(block); - - uiDefButBitI(block, TOG, ACT_VISIBILITY_RECURSIVE, 0, - "Children", - xco + 10 + (((width - 20)/3)*2)+10, yco - 20, ((width - 20)/3)-10, 19, &visAct->flag, - 0.0, 0.0, 0, 0, - "Sets all the children of this object to the same visibility/occlusion recursively"); + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, + (float)yco-ysize, (float)xco+width, (float)yco, 1); - yco-= ysize; + visAct = act->data; - break; - - case ACT_STATE: - ysize = 34; + uiBlockBeginAlign(block); + uiDefButBitI(block, TOGN, ACT_VISIBILITY_INVISIBLE, B_REDR, + "Visible", + xco + 10, yco - 20, (width - 20)/3, 19, &visAct->flag, + 0.0, 0.0, 0, 0, + "Set the objects visible. Initialized from the objects render restriction toggle (access in the outliner)"); + uiDefButBitI(block, TOG, ACT_VISIBILITY_OCCLUSION, B_REDR, + "Occlusion", + xco + 10 + ((width - 20)/3), yco - 20, (width - 20)/3, 19, &visAct->flag, + 0.0, 0.0, 0, 0, + "Set the object to occlude objects behind it. Initialized from the object type in physics button"); + uiBlockEndAlign(block); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, - (float)yco-ysize, (float)xco+width, (float)yco, 1); - - staAct = act->data; + uiDefButBitI(block, TOG, ACT_VISIBILITY_RECURSIVE, 0, + "Children", + xco + 10 + (((width - 20)/3)*2)+10, yco - 20, ((width - 20)/3)-10, 19, &visAct->flag, + 0.0, 0.0, 0, 0, + "Sets all the children of this object to the same visibility/occlusion recursively"); - str= "Operation %t|Cpy %x0|Add %x1|Sub %x2|Inv %x3"; + yco-= ysize; - uiDefButI(block, MENU, B_REDR, str, - xco + 10, yco - 24, 65, 19, &staAct->type, - 0.0, 0.0, 0, 0, - "Select the bit operation on object state mask"); + break; - for (wval=0; wval<15; wval+=5) { - uiBlockBeginAlign(block); - for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, TOG, 1<<(stbit+wval), stbit+wval, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval))); - uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); - } - for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, TOG, 1<<(stbit+wval+15), stbit+wval+15, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval+15))); - uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); - } - } - uiBlockEndAlign(block); + case ACT_STATE: + ysize = 34; - yco-= ysize; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, + (float)yco-ysize, (float)xco+width, (float)yco, 1); - break; + staAct = act->data; - case ACT_RANDOM: - ysize = 69; + str= "Operation %t|Cpy %x0|Add %x1|Sub %x2|Inv %x3"; + + uiDefButI(block, MENU, B_REDR, str, + xco + 10, yco - 24, 65, 19, &staAct->type, + 0.0, 0.0, 0, 0, + "Select the bit operation on object state mask"); + + for (wval=0; wval<15; wval+=5) { + uiBlockBeginAlign(block); + for (stbit=0; stbit<5; stbit++) { + but = uiDefButBitI(block, TOG, 1<<(stbit+wval), stbit+wval, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval))); + uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); + } + for (stbit=0; stbit<5; stbit++) { + but = uiDefButBitI(block, TOG, 1<<(stbit+wval+15), stbit+wval+15, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval+15))); + uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); + } + } + uiBlockEndAlign(block); + + yco-= ysize; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, - (float)yco-ysize, (float)xco+width, (float)yco, 1); - - randAct = act->data; - - /* 1. seed */ - uiDefButI(block, NUM, 1, "Seed: ", (xco+10), yco-24, 0.4 *(width-20), 19, - &randAct->seed, 0, 1000, 0, 0, - "Initial seed of the random generator. Use Python for more freedom. " - " (Choose 0 for not random)"); - - /* 2. distribution type */ - /* One pick per distribution. These numbers MUST match the #defines */ - /* in game.h !!! */ - str= "Distribution %t|Bool Constant %x0|Bool Uniform %x1" - "|Bool Bernoulli %x2|Int Constant %x3|Int Uniform %x4" - "|Int Poisson %x5|Float Constant %x6|Float Uniform %x7" - "|Float Normal %x8|Float Neg. Exp. %x9"; - uiDefButI(block, MENU, B_REDR, str, (xco+10) + 0.4 * (width-20), yco-24, 0.6 * (width-20), 19, - &randAct->distribution, 0.0, 0.0, 0, 0, - "Choose the type of distribution"); - - /* 3. property */ - uiDefBut(block, TEX, 1, "Property:", (xco+10), yco-44, (width-20), 19, - &randAct->propname, 0, MAX_NAME, 0, 0, - "Assign the random value to this property"); - - /*4. and 5. arguments for the distribution*/ - switch (randAct->distribution) { - case ACT_RANDOM_BOOL_CONST: - uiDefButBitI(block, TOG, 1, 1, "Always true", (xco+10), yco-64, (width-20), 19, - &randAct->int_arg_1, 2.0, 1, 0, 0, - "Always false or always true"); - break; - case ACT_RANDOM_BOOL_UNIFORM: - uiDefBut(block, LABEL, 0, " Do a 50-50 pick", (xco+10), yco-64, (width-20), 19, - NULL, 0, 0, 0, 0, - "Choose between true and false, 50% chance each"); - break; - case ACT_RANDOM_BOOL_BERNOUILLI: - uiDefButF(block, NUM, 1, "Chance", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.0, 1.0, 0, 0, - "Pick a number between 0 and 1. Success if you stay " - "below this value"); - break; - case ACT_RANDOM_INT_CONST: - uiDefButI(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19, - &randAct->int_arg_1, -1000, 1000, 0, 0, - "Always return this number"); - break; - case ACT_RANDOM_INT_UNIFORM: - uiDefButI(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19, - &randAct->int_arg_1, -1000, 1000, 0, 0, - "Choose a number from a range. " - "Lower boundary of the range"); - uiDefButI(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, - &randAct->int_arg_2, -1000, 1000, 0, 0, - "Choose a number from a range. " - "Upper boundary of the range"); - break; - case ACT_RANDOM_INT_POISSON: - uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.01, 100.0, 0, 0, - "Expected mean value of the distribution"); - break; - case ACT_RANDOM_FLOAT_CONST: - uiDefButF(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.0, 1.0, 0, 0, - "Always return this number"); - break; - case ACT_RANDOM_FLOAT_UNIFORM: - uiDefButF(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19, - &randAct->float_arg_1, -10000.0, 10000.0, 0, 0, - "Choose a number from a range" - "Lower boundary of the range"); - uiDefButF(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, - &randAct->float_arg_2, -10000.0, 10000.0, 0, 0, - "Choose a number from a range" - "Upper boundary of the range"); - break; - case ACT_RANDOM_FLOAT_NORMAL: - uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20)/2, 19, - &randAct->float_arg_1, -10000.0, 10000.0, 0, 0, - "A normal distribution. Mean of the distribution"); - uiDefButF(block, NUM, 1, "SD: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, - &randAct->float_arg_2, 0.0, 10000.0, 0, 0, - "A normal distribution. Standard deviation of the " - "distribution"); - break; - case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL: - uiDefButF(block, NUM, 1, "Half-life time: ", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.001, 10000.0, 0, 0, - "Negative exponential dropoff"); break; - default: - ; /* don't know what this distro is... can be useful for testing */ - /* though :) */ - } - yco-= ysize; - break; - case ACT_MESSAGE: - ma = act->data; + case ACT_RANDOM: + ysize = 69; - ysize = 4 + (3 * 24); /* footer + number of lines * 24 pixels/line */ - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - myline=1; - - /* line 1: To */ - uiDefBut(block, TEX, 1, "To: ", - (xco+10), (yco-(myline++*24)), (width-20), 19, - &ma->toPropName, 0, MAX_NAME, 0, 0, - "Optional send message to objects with this name only, or empty to broadcast"); - - /* line 2: Message Subject */ - uiDefBut(block, TEX, 1, "Subject: ", - (xco+10), (yco-(myline++*24)), (width-20), 19, - &ma->subject, 0, MAX_NAME, 0, 0, - "Optional message subject. This is what can be filtered on"); - - /* line 3: Text/Property */ - uiDefButBitS(block, TOG, 1, B_REDR, "T/P", - (xco+10), (yco-(myline*24)), (0.20 * (width-20)), 19, - &ma->bodyType, 0.0, 0.0, 0, 0, - "Toggle message type: either Text or a PropertyName"); - - if (ma->bodyType == ACT_MESG_MESG) { - /* line 3: Message Body */ - uiDefBut(block, TEX, 1, "Body: ", - (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19, - &ma->body, 0, MAX_NAME, 0, 0, - "Optional message body Text"); - } - else { - /* line 3: Property body (set by property) */ - uiDefBut(block, TEX, 1, "Propname: ", - (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19, - &ma->body, 0, MAX_NAME, 0, 0, - "The message body will be set by the Property Value"); - } - - yco -= ysize; - break; - case ACT_2DFILTER: - tdfa = act->data; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, + (float)yco-ysize, (float)xco+width, (float)yco, 1); + + randAct = act->data; + + /* 1. seed */ + uiDefButI(block, NUM, 1, "Seed: ", (xco+10), yco-24, 0.4 *(width-20), 19, + &randAct->seed, 0, 1000, 0, 0, + "Initial seed of the random generator. Use Python for more freedom. " + " (Choose 0 for not random)"); + + /* 2. distribution type */ + /* One pick per distribution. These numbers MUST match the #defines */ + /* in game.h !!! */ + str= "Distribution %t|Bool Constant %x0|Bool Uniform %x1" + "|Bool Bernoulli %x2|Int Constant %x3|Int Uniform %x4" + "|Int Poisson %x5|Float Constant %x6|Float Uniform %x7" + "|Float Normal %x8|Float Neg. Exp. %x9"; + uiDefButI(block, MENU, B_REDR, str, (xco+10) + 0.4 * (width-20), yco-24, 0.6 * (width-20), 19, + &randAct->distribution, 0.0, 0.0, 0, 0, + "Choose the type of distribution"); + + /* 3. property */ + uiDefBut(block, TEX, 1, "Property:", (xco+10), yco-44, (width-20), 19, + &randAct->propname, 0, MAX_NAME, 0, 0, + "Assign the random value to this property"); + + /*4. and 5. arguments for the distribution*/ + switch (randAct->distribution) { + case ACT_RANDOM_BOOL_CONST: + uiDefButBitI(block, TOG, 1, 1, "Always true", (xco+10), yco-64, (width-20), 19, + &randAct->int_arg_1, 2.0, 1, 0, 0, + "Always false or always true"); + break; + case ACT_RANDOM_BOOL_UNIFORM: + uiDefBut(block, LABEL, 0, " Do a 50-50 pick", (xco+10), yco-64, (width-20), 19, + NULL, 0, 0, 0, 0, + "Choose between true and false, 50% chance each"); + break; + case ACT_RANDOM_BOOL_BERNOUILLI: + uiDefButF(block, NUM, 1, "Chance", (xco+10), yco-64, (width-20), 19, + &randAct->float_arg_1, 0.0, 1.0, 0, 0, + "Pick a number between 0 and 1. Success if you stay " + "below this value"); + break; + case ACT_RANDOM_INT_CONST: + uiDefButI(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19, + &randAct->int_arg_1, -1000, 1000, 0, 0, + "Always return this number"); + break; + case ACT_RANDOM_INT_UNIFORM: + uiDefButI(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19, + &randAct->int_arg_1, -1000, 1000, 0, 0, + "Choose a number from a range. " + "Lower boundary of the range"); + uiDefButI(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, + &randAct->int_arg_2, -1000, 1000, 0, 0, + "Choose a number from a range. " + "Upper boundary of the range"); + break; + case ACT_RANDOM_INT_POISSON: + uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20), 19, + &randAct->float_arg_1, 0.01, 100.0, 0, 0, + "Expected mean value of the distribution"); + break; + case ACT_RANDOM_FLOAT_CONST: + uiDefButF(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19, + &randAct->float_arg_1, 0.0, 1.0, 0, 0, + "Always return this number"); + break; + case ACT_RANDOM_FLOAT_UNIFORM: + uiDefButF(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19, + &randAct->float_arg_1, -10000.0, 10000.0, 0, 0, + "Choose a number from a range" + "Lower boundary of the range"); + uiDefButF(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, + &randAct->float_arg_2, -10000.0, 10000.0, 0, 0, + "Choose a number from a range" + "Upper boundary of the range"); + break; + case ACT_RANDOM_FLOAT_NORMAL: + uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20)/2, 19, + &randAct->float_arg_1, -10000.0, 10000.0, 0, 0, + "A normal distribution. Mean of the distribution"); + uiDefButF(block, NUM, 1, "SD: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, + &randAct->float_arg_2, 0.0, 10000.0, 0, 0, + "A normal distribution. Standard deviation of the " + "distribution"); + break; + case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL: + uiDefButF(block, NUM, 1, "Half-life time: ", (xco+10), yco-64, (width-20), 19, + &randAct->float_arg_1, 0.001, 10000.0, 0, 0, + "Negative exponential dropoff"); + break; + default: + ; /* don't know what this distro is... can be useful for testing */ + /* though :) */ + } - ysize = 50; - if (tdfa->type == ACT_2DFILTER_CUSTOMFILTER) { - ysize +=20; - } - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + yco-= ysize; + break; + case ACT_MESSAGE: + ma = act->data; - switch (tdfa->type) { - case ACT_2DFILTER_MOTIONBLUR: - if (!tdfa->flag) { - uiDefButS(block, TOG, B_REDR, "D", xco+30, yco-44, 19, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Disable Motion Blur"); - uiDefButF(block, NUM, B_REDR, "Value:", xco+52, yco-44, width-82, 19, &tdfa->float_arg, 0.0, 1.0, 0.0, 0.0, "Set motion blur value"); - } - else { - uiDefButS(block, TOG, B_REDR, "Disabled", xco+30, yco-44, width-60, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Enable Motion Blur"); - } - break; - case ACT_2DFILTER_BLUR: - case ACT_2DFILTER_SHARPEN: - case ACT_2DFILTER_DILATION: - case ACT_2DFILTER_EROSION: - case ACT_2DFILTER_LAPLACIAN: - case ACT_2DFILTER_SOBEL: - case ACT_2DFILTER_PREWITT: - case ACT_2DFILTER_GRAYSCALE: - case ACT_2DFILTER_SEPIA: - case ACT_2DFILTER_INVERT: - case ACT_2DFILTER_NOFILTER: - case ACT_2DFILTER_DISABLED: - case ACT_2DFILTER_ENABLED: - uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order"); - break; - case ACT_2DFILTER_CUSTOMFILTER: - uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order"); - uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30, yco-64, width-60, 19, &tdfa->text, ""); - break; - } - - str= "2D Filter %t|Motion Blur %x1|Blur %x2|Sharpen %x3|Dilation %x4|Erosion %x5|" - "Laplacian %x6|Sobel %x7|Prewitt %x8|Gray Scale %x9|Sepia %x10|Invert %x11|Custom Filter %x12|" - "Enable Filter %x-2|Disable Filter %x-1|Remove Filter %x0|"; - uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &tdfa->type, 0.0, 0.0, 0.0, 0.0, "2D filter type"); - - yco -= ysize; - break; - case ACT_PARENT: - parAct = act->data; + ysize = 4 + (3 * 24); /* footer + number of lines * 24 pixels/line */ - if (parAct->type==ACT_PARENT_SET) { - - ysize= 48; glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+95, yco-24, (width-100), 19, &(parAct->ob), "Set this object as parent"); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOGN, ACT_PARENT_COMPOUND, B_REDR, - "Compound", - xco + 5, yco - 44, (width - 10)/2, 19, &parAct->flag, - 0.0, 0.0, 0, 0, - "Add this object shape to the parent shape (only if the parent shape is already compound)"); - uiDefButBitS(block, TOGN, ACT_PARENT_GHOST, B_REDR, - "Ghost", - xco + 5 + ((width - 10)/2), yco - 44, (width - 10)/2, 19, &parAct->flag, - 0.0, 0.0, 0, 0, - "Make this object ghost while parented (only if not compound)"); - uiBlockEndAlign(block); - } - else if (parAct->type==ACT_PARENT_REMOVE) { + uiEmboss((float)xco, (float)yco-ysize, + (float)xco+width, (float)yco, 1); + + myline=1; + + /* line 1: To */ + uiDefBut(block, TEX, 1, "To: ", + (xco+10), (yco-(myline++*24)), (width-20), 19, + &ma->toPropName, 0, MAX_NAME, 0, 0, + "Optional send message to objects with this name only, or empty to broadcast"); + + /* line 2: Message Subject */ + uiDefBut(block, TEX, 1, "Subject: ", + (xco+10), (yco-(myline++*24)), (width-20), 19, + &ma->subject, 0, MAX_NAME, 0, 0, + "Optional message subject. This is what can be filtered on"); + + /* line 3: Text/Property */ + uiDefButBitS(block, TOG, 1, B_REDR, "T/P", + (xco+10), (yco-(myline*24)), (0.20 * (width-20)), 19, + &ma->bodyType, 0.0, 0.0, 0, 0, + "Toggle message type: either Text or a PropertyName"); + + if (ma->bodyType == ACT_MESG_MESG) { + /* line 3: Message Body */ + uiDefBut(block, TEX, 1, "Body: ", + (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19, + &ma->body, 0, MAX_NAME, 0, 0, + "Optional message body Text"); + } + else { + /* line 3: Property body (set by property) */ + uiDefBut(block, TEX, 1, "Propname: ", + (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19, + &ma->body, 0, MAX_NAME, 0, 0, + "The message body will be set by the Property Value"); + } + + yco -= ysize; + break; + case ACT_2DFILTER: + tdfa = act->data; - ysize= 28; + ysize = 50; + if (tdfa->type == ACT_2DFILTER_CUSTOMFILTER) { + ysize +=20; + } glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - str= "Parent %t|Set Parent %x0|Remove Parent %x1"; - uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, parAct->type==1?(width-80):90, 19, &parAct->type, 0.0, 0.0, 0, 0, ""); + switch (tdfa->type) { + case ACT_2DFILTER_MOTIONBLUR: + if (!tdfa->flag) { + uiDefButS(block, TOG, B_REDR, "D", xco+30, yco-44, 19, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Disable Motion Blur"); + uiDefButF(block, NUM, B_REDR, "Value:", xco+52, yco-44, width-82, 19, &tdfa->float_arg, 0.0, 1.0, 0.0, 0.0, "Set motion blur value"); + } + else { + uiDefButS(block, TOG, B_REDR, "Disabled", xco+30, yco-44, width-60, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Enable Motion Blur"); + } + break; + case ACT_2DFILTER_BLUR: + case ACT_2DFILTER_SHARPEN: + case ACT_2DFILTER_DILATION: + case ACT_2DFILTER_EROSION: + case ACT_2DFILTER_LAPLACIAN: + case ACT_2DFILTER_SOBEL: + case ACT_2DFILTER_PREWITT: + case ACT_2DFILTER_GRAYSCALE: + case ACT_2DFILTER_SEPIA: + case ACT_2DFILTER_INVERT: + case ACT_2DFILTER_NOFILTER: + case ACT_2DFILTER_DISABLED: + case ACT_2DFILTER_ENABLED: + uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order"); + break; + case ACT_2DFILTER_CUSTOMFILTER: + uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order"); + uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30, yco-64, width-60, 19, &tdfa->text, ""); + break; + } - yco-= ysize; - break; - case ACT_ARMATURE: - armAct = act->data; + str= "2D Filter %t|Motion Blur %x1|Blur %x2|Sharpen %x3|Dilation %x4|Erosion %x5|" + "Laplacian %x6|Sobel %x7|Prewitt %x8|Gray Scale %x9|Sepia %x10|Invert %x11|Custom Filter %x12|" + "Enable Filter %x-2|Disable Filter %x-1|Remove Filter %x0|"; + uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &tdfa->type, 0.0, 0.0, 0.0, 0.0, "2D filter type"); - if (ob->type == OB_ARMATURE) { - str= "Constraint %t|Run armature %x0|Enable %x1|Disable %x2|Set target %x3|Set weight %x4"; - uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, (width-10)*0.35, 19, &armAct->type, 0.0, 0.0, 0, 0, ""); + yco -= ysize; + break; + case ACT_PARENT: + parAct = act->data; - switch (armAct->type) { - case ACT_ARM_RUN: - ysize = 28; - break; - default: + if (parAct->type==ACT_PARENT_SET) { + + ysize= 48; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+95, yco-24, (width-100), 19, &(parAct->ob), "Set this object as parent"); uiBlockBeginAlign(block); - but = uiDefBut(block, TEX, 1, "Bone: ", - (xco+5), (yco-44), (width-10)/2, 19, - armAct->posechannel, 0, MAX_NAME, 0, 0, - "Bone on which the constraint is defined"); - uiButSetFunc(but, check_armature_actuator, but, armAct); - but = uiDefBut(block, TEX, 1, "Cons: ", - (xco+5)+(width-10)/2, (yco-44), (width-10)/2, 19, - armAct->constraint, 0, MAX_NAME, 0, 0, - "Name of the constraint you want to control"); - uiButSetFunc(but, check_armature_actuator, but, armAct); + uiDefButBitS(block, TOGN, ACT_PARENT_COMPOUND, B_REDR, + "Compound", + xco + 5, yco - 44, (width - 10)/2, 19, &parAct->flag, + 0.0, 0.0, 0, 0, + "Add this object shape to the parent shape (only if the parent shape is already compound)"); + uiDefButBitS(block, TOGN, ACT_PARENT_GHOST, B_REDR, + "Ghost", + xco + 5 + ((width - 10)/2), yco - 44, (width - 10)/2, 19, &parAct->flag, + 0.0, 0.0, 0, 0, + "Make this object ghost while parented (only if not compound)"); uiBlockEndAlign(block); - ysize = 48; + } + else if (parAct->type==ACT_PARENT_REMOVE) { + + ysize= 28; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + } + + str= "Parent %t|Set Parent %x0|Remove Parent %x1"; + uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, parAct->type==1?(width-80):90, 19, &parAct->type, 0.0, 0.0, 0, 0, ""); + + yco-= ysize; + break; + case ACT_ARMATURE: + armAct = act->data; + + if (ob->type == OB_ARMATURE) { + str= "Constraint %t|Run armature %x0|Enable %x1|Disable %x2|Set target %x3|Set weight %x4"; + uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, (width-10)*0.35, 19, &armAct->type, 0.0, 0.0, 0, 0, ""); + switch (armAct->type) { - case ACT_ARM_SETTARGET: - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Target: ", xco+5, yco-64, (width-10), 19, &(armAct->target), "Set this object as the target of the constraint"); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Secondary Target: ", xco+5, yco-84, (width-10), 19, &(armAct->subtarget), "Set this object as the secondary target of the constraint (only IK polar target at the moment)"); - ysize += 40; - break; - case ACT_ARM_SETWEIGHT: - uiDefButF(block, NUM, B_REDR, "Weight:", xco+5+(width-10)*0.35, yco-24, (width-10)*0.65, 19, &armAct->weight, 0.0, 1.0, 0.0, 0.0, "Set weight of this constraint"); - break; + case ACT_ARM_RUN: + ysize = 28; + break; + default: + uiBlockBeginAlign(block); + but = uiDefBut(block, TEX, 1, "Bone: ", + (xco+5), (yco-44), (width-10)/2, 19, + armAct->posechannel, 0, MAX_NAME, 0, 0, + "Bone on which the constraint is defined"); + uiButSetFunc(but, check_armature_actuator, but, armAct); + but = uiDefBut(block, TEX, 1, "Cons: ", + (xco+5)+(width-10)/2, (yco-44), (width-10)/2, 19, + armAct->constraint, 0, MAX_NAME, 0, 0, + "Name of the constraint you want to control"); + uiButSetFunc(but, check_armature_actuator, but, armAct); + uiBlockEndAlign(block); + ysize = 48; + switch (armAct->type) { + case ACT_ARM_SETTARGET: + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Target: ", xco+5, yco-64, (width-10), 19, &(armAct->target), "Set this object as the target of the constraint"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Secondary Target: ", xco+5, yco-84, (width-10), 19, &(armAct->subtarget), "Set this object as the secondary target of the constraint (only IK polar target at the moment)"); + ysize += 40; + break; + case ACT_ARM_SETWEIGHT: + uiDefButF(block, NUM, B_REDR, "Weight:", xco+5+(width-10)*0.35, yco-24, (width-10)*0.65, 19, &armAct->weight, 0.0, 1.0, 0.0, 0.0, "Set weight of this constraint"); + break; + } } } - } - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - yco-= ysize; - break; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + yco-= ysize; + break; - default: - ysize= 4; + default: + ysize= 4; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - yco-= ysize; - break; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + + yco-= ysize; + break; } uiBlockSetEmboss(block, UI_EMBOSS); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f60c46fed9a..45c1f5ccee4 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2451,7 +2451,7 @@ static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], } static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act, - RegionView3D *rv3d) + RegionView3D *rv3d) { drawDMVerts_userData data; data.sel = sel; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 6b96bfdf66c..0abc4f00c54 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -713,7 +713,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm } else { short orientation = (t->current_orientation != V3D_MANIP_GLOBAL ? - t->current_orientation : V3D_MANIP_LOCAL); + t->current_orientation : V3D_MANIP_LOCAL); if (!(t->modifiers & MOD_CONSTRAINT_PLANE)) setUserConstraint(t, orientation, constraint_axis, msg2); else if (t->modifiers & MOD_CONSTRAINT_PLANE) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fbbb5bdfae8..19d97b64f54 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1336,7 +1336,7 @@ static void createTransCurveVerts(bContext *C, TransInfo *t) Object *obedit= CTX_data_edit_object(C); Curve *cu= obedit->data; TransData *td = NULL; - Nurb *nu; + Nurb *nu; BezTriple *bezt; BPoint *bp; float mtx[3][3], smtx[3][3]; @@ -1889,7 +1889,7 @@ static void get_edge_center(float cent_r[3], BMVert *eve) /* way to overwrite what data is edited with transform */ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx, - BMEditMesh *em, BMVert *eve, float *bweight) + BMEditMesh *em, BMVert *eve, float *bweight) { td->flag = 0; //if (key) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 6f26763fc0e..5e8c6b33b0d 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1519,7 +1519,7 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper * * The cache is structured with a dual-layer structure * - L1 = PointerRNA used as key; id.data is used (it should always be defined, - * and most updates end up using just that anyways) + * and most updates end up using just that anyways) * - L2 = Update functions to be called on those PointerRNA's */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index d14675b77c8..e96ed4f38d3 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -173,8 +173,8 @@ static int rna_SculptCapabilities_has_random_texture_angle_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return (ELEM(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_AREA) && + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA) && !(br->flag & BRUSH_ANCHORED) && !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, @@ -236,17 +236,17 @@ static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM3(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_AREA, - MTEX_MAP_MODE_TILED); + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA, + MTEX_MAP_MODE_TILED); } static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_AREA); + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA); } static PointerRNA rna_Brush_sculpt_capabilities_get(PointerRNA *ptr) diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index 9ceee3feab1..7cf337f2f88 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -180,12 +180,12 @@ static void node_composit_exec_math(void *UNUSED(data), bNode *node, bNodeStack return; } - /*create output based on first input */ + /* create output based on first input */ if (cbuf) { stackbuf=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); } /* and if it doesn't exist use the second input since we - know that one of them must exist at this point*/ + * know that one of them must exist at this point*/ else { stackbuf=alloc_compbuf(cbuf2->x, cbuf2->y, CB_VAL, 1); } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 6ad1874297f..873f5353bff 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -591,7 +591,7 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_ /* note that PROP_NONE is included as a vector subtype. this is because its handy to * have x/y access to fcurve keyframes and other fixed size float arrays of length 2-4. */ #define PROP_ALL_VECTOR_SUBTYPES \ - PROP_COORDS: \ + PROP_COORDS: \ case PROP_TRANSLATION: \ case PROP_DIRECTION: \ case PROP_VELOCITY: \ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index a2e99300be7..a2b911911d0 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -5646,7 +5646,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned ok= 1; } if (ok==0) { - printf("speed table: missing object %s\n", obi->ob->id.name+2); + printf("speed table: missing object %s\n", obi->ob->id.name+2); continue; } -- cgit v1.2.3 From 47c96b6e402f23afeb2ee577745b1e9f0e1ae085 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 6 Jun 2012 16:00:21 +0000 Subject: Cycles / OSL: * Fixes for some silly typos in the checker shader. * Added missing GPL licence block to node_fresnel.h. --- intern/cycles/kernel/osl/nodes/node_checker_texture.osl | 12 ++++++------ intern/cycles/kernel/osl/nodes/node_fresnel.h | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl b/intern/cycles/kernel/osl/nodes/node_checker_texture.osl index a80242ad36a..306798b645f 100644 --- a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_checker_texture.osl @@ -23,13 +23,13 @@ float checker(point p) { - p[0] = (p[0] + 0.00001)*0.9999); - p[1] = (p[1] + 0.00001)*0.9999); - p[2] = (p[2] + 0.00001)*0.9999); + p[0] = (p[0] + 0.00001)*0.9999; + p[1] = (p[1] + 0.00001)*0.9999; + p[2] = (p[2] + 0.00001)*0.9999; - int xi = fabs(floor(p[0])); - int yi = fabs(floor(p[1])); - int zi = fabs(floor(p[2])); + int xi = (int)fabs(floor(p[0])); + int yi = (int)fabs(floor(p[1])); + int zi = (int)fabs(floor(p[2])); if((xi % 2 == yi % 2) == (zi % 2)) { return 1.0; diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.h b/intern/cycles/kernel/osl/nodes/node_fresnel.h index 0368c1910aa..de5d29a3c18 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.h +++ b/intern/cycles/kernel/osl/nodes/node_fresnel.h @@ -1,4 +1,19 @@ - +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + float fresnel_dielectric(vector Incoming, normal Normal, float eta) { /* compute fresnel reflectance without explicitly computing -- cgit v1.2.3 From b53b03ac1c9bbc194c2ac1f255f8017f1a78bdd2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 18:00:08 +0000 Subject: pass the object wire color along to drawing functions, too many places would use glGetFloatv(GL_CURRENT_COLOR, curcol), which also become confusing to debug if in some cases the color was set beforehand. --- source/blender/blenlib/intern/math_color_inline.c | 7 + source/blender/editors/space_view3d/drawarmature.c | 29 +-- source/blender/editors/space_view3d/drawobject.c | 290 +++++++++++---------- source/blender/editors/space_view3d/view3d_draw.c | 2 +- .../blender/editors/space_view3d/view3d_intern.h | 6 +- 5 files changed, 180 insertions(+), 154 deletions(-) diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 243e9fc8a57..b2a87a91433 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -215,4 +215,11 @@ MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, co } } +MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack) +{ + r_col[0] = ((pack) >> 0) & 0xFF; + r_col[1] = ((pack) >> 8) & 0xFF; + r_col[2] = ((pack) >> 16) & 0xFF; +} + #endif /* __MATH_COLOR_INLINE_C__ */ diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 0de7e2569c0..0803654fd68 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1656,7 +1656,8 @@ static void bone_matrix_translate_y(float mat[][4], float y) } /* assumes object is Armature with pose */ -static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, +static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, + int dt, const unsigned char ob_wire_col[4], const short is_ghost, const short is_outline) { RegionView3D *rv3d = ar->regiondata; @@ -1833,14 +1834,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else if (arm->flag & ARM_POSEMODE) set_pchan_colorset(ob, pchan); else { - if ((scene->basact) == base) { - if (base->flag & (SELECT + BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE); - else UI_ThemeColor(TH_WIRE); - } - else { - if (base->flag & (SELECT + BA_WAS_SEL)) UI_ThemeColor(TH_SELECT); - else UI_ThemeColor(TH_WIRE); - } + glColor3ubv(ob_wire_col); } /* catch exception for bone with hidden parent */ @@ -2353,7 +2347,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2432,7 +2426,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2502,7 +2496,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE); } } @@ -2517,7 +2511,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL); BKE_pose_where_is(scene, ob); - draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE); + draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE); } } } @@ -2537,8 +2531,11 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) /* ********************************** Armature Drawing - Main ************************* */ -/* called from drawobject.c, return 1 if nothing was drawn */ -int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag, const short is_outline) +/* called from drawobject.c, return 1 if nothing was drawn + * (ob_wire_col == NULL) when drawing ghost */ +int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, + int dt, int flag, const unsigned char ob_wire_col[4], + const short is_outline) { Object *ob = base->object; bArmature *arm = ob->data; @@ -2605,7 +2602,7 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, in } } } - draw_pose_bones(scene, v3d, ar, base, dt, FALSE, is_outline); + draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, FALSE, is_outline); arm->flag &= ~ARM_POSEMODE; if (ob->mode & OB_MODE_POSE) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 45c1f5ccee4..63dc6c21863 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1189,14 +1189,17 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z) glCullFace(GL_BACK); } -static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag) +static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + int dt, int flag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); Lamp *la = ob->data; float vec[3], lvec[3], vvec[3], circrad, x, y, z; float lampsize; - float imat[4][4], curcol[4]; + float imat[4][4]; + + unsigned char curcol[4]; unsigned char col[4]; /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */ /* the moment of view3d_draw_transp() call */ @@ -1230,10 +1233,12 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, copy_v3_v3(vec, ob->obmat[3]); /* for AA effects */ - glGetFloatv(GL_CURRENT_COLOR, curcol); - curcol[3] = 0.6; - glColor4fv(curcol); - + curcol[0] = ob_wire_col[0]; + curcol[1] = ob_wire_col[1]; + curcol[2] = ob_wire_col[2]; + curcol[3] = 154; + glColor4ubv(curcol); + if (lampsize > 0.0f) { if (ob->id.us > 1) { @@ -1249,7 +1254,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, /* restore */ if (ob->id.us > 1) - glColor4fv(curcol); + glColor4ubv(curcol); /* Outer circle */ circrad = 3.0f * lampsize; @@ -1482,7 +1487,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, glDisable(GL_BLEND); /* restore for drawing extra stuff */ - glColor3fv(curcol); + glColor3ubv(ob_wire_col); } @@ -1516,7 +1521,7 @@ static void draw_focus_cross(float dist, float size) } #ifdef VIEW3D_CAMERA_BORDER_HACK -float view3d_camera_border_hack_col[4]; +unsigned char view3d_camera_border_hack_col[3]; short view3d_camera_border_hack_test = FALSE; #endif @@ -1701,11 +1706,11 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D } static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, - int flag, int draw_selected) + int flag, const unsigned char ob_wire_col[4], + int draw_selected) { MovieTracking *tracking = &clip->tracking; MovieTrackingObject *tracking_object; - float curcol[4]; int global_track_index = 1; if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0) @@ -1714,8 +1719,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, if (v3d->flag2 & V3D_RENDER_OVERRIDE) return; - glGetFloatv(GL_CURRENT_COLOR, curcol); - glEnable(GL_LIGHTING); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); @@ -1734,14 +1737,15 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); - glColor4fv(curcol); + glColor3ubv(ob_wire_col); if (flag & DRAW_PICKING) glLoadName(base->selcol); } /* flag similar to draw_object() */ -static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag) +static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + int flag, const unsigned char ob_wire_col[4]) { /* a standing up pyramid with (0,0,0) as top */ Camera *cam; @@ -1755,13 +1759,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base /* draw data for movie clip set as active for scene */ if (clip) { - draw_viewport_reconstruction(scene, base, v3d, clip, flag, FALSE); - draw_viewport_reconstruction(scene, base, v3d, clip, flag, TRUE); + draw_viewport_reconstruction(scene, base, v3d, clip, flag, ob_wire_col, FALSE); + draw_viewport_reconstruction(scene, base, v3d, clip, flag, ob_wire_col, TRUE); } #ifdef VIEW3D_CAMERA_BORDER_HACK if (is_view && !(G.f & G_PICKSEL)) { - glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col); + view3d_camera_border_hack_col[0] = ob_wire_col[0]; + view3d_camera_border_hack_col[1] = ob_wire_col[1]; + view3d_camera_border_hack_col[2] = ob_wire_col[2]; view3d_camera_border_hack_test = TRUE; return; } @@ -3778,17 +3784,15 @@ static int drawDispListwire(ListBase *dlbase) return 0; } -static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) +static void drawDispListsolid(ListBase *lb, Object *ob, + const unsigned char ob_wire_col[4], int use_glsl) { DispList *dl; GPUVertexAttribs gattribs; - float *data, curcol[4]; + float *data; float *ndata; if (lb == NULL) return; - - /* for drawing wire */ - glGetFloatv(GL_CURRENT_COLOR, curcol); glEnable(GL_LIGHTING); glEnableClientState(GL_VERTEX_ARRAY); @@ -3811,7 +3815,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) int nr; glDisable(GL_LIGHTING); - glColor3fv(curcol); + glColor3ubv(ob_wire_col); // glVertexPointer(3, GL_FLOAT, 0, dl->verts); // glDrawArrays(GL_LINE_STRIP, 0, dl->nr); @@ -3845,7 +3849,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) case DL_SURF: if (dl->index) { - GPU_enable_material(dl->col + 1, (glsl) ? &gattribs : NULL); + GPU_enable_material(dl->col + 1, (use_glsl) ? &gattribs : NULL); if (dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); @@ -3859,7 +3863,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) break; case DL_INDEX3: - GPU_enable_material(dl->col + 1, (glsl) ? &gattribs : NULL); + GPU_enable_material(dl->col + 1, (use_glsl) ? &gattribs : NULL); glVertexPointer(3, GL_FLOAT, 0, dl->verts); @@ -3879,7 +3883,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) break; case DL_INDEX4: - GPU_enable_material(dl->col + 1, (glsl) ? &gattribs : NULL); + GPU_enable_material(dl->col + 1, (use_glsl) ? &gattribs : NULL); glEnableClientState(GL_NORMAL_ARRAY); glVertexPointer(3, GL_FLOAT, 0, dl->verts); @@ -3937,7 +3941,8 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B } /* returns 1 when nothing was drawn */ -static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt) +static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + int dt, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -3985,12 +3990,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas else { if (draw_glsl_material(scene, ob, v3d, dt)) { GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); - drawDispListsolid(lb, ob, 1); + drawDispListsolid(lb, ob, ob_wire_col, TRUE); GPU_end_object_materials(); } else { GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); - drawDispListsolid(lb, ob, 0); + drawDispListsolid(lb, ob, ob_wire_col, FALSE); GPU_end_object_materials(); } if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) { @@ -4022,12 +4027,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (draw_glsl_material(scene, ob, v3d, dt)) { GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); - drawDispListsolid(lb, ob, 1); + drawDispListsolid(lb, ob, ob_wire_col, TRUE); GPU_end_object_materials(); } else { GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); - drawDispListsolid(lb, ob, 0); + drawDispListsolid(lb, ob, ob_wire_col, FALSE); GPU_end_object_materials(); } } @@ -4046,12 +4051,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (draw_glsl_material(scene, ob, v3d, dt)) { GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); - drawDispListsolid(lb, ob, 1); + drawDispListsolid(lb, ob, ob_wire_col, TRUE); GPU_end_object_materials(); } else { GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); - drawDispListsolid(lb, ob, 0); + drawDispListsolid(lb, ob, ob_wire_col, FALSE); GPU_end_object_materials(); } } @@ -5563,7 +5568,8 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } } -static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, int dt) +static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, + int dt, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -5572,10 +5578,13 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, BevList *bl; short hide_handles = (cu->drawflag & CU_HIDE_HANDLES); int index; + unsigned char wire_col[3]; /* DispList */ - UI_ThemeColor(TH_WIRE); - drawDispList(scene, v3d, rv3d, base, dt); + UI_GetThemeColor3ubv(TH_WIRE, wire_col); + glColor3ubv(wire_col); + + drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); if (v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -5887,7 +5896,8 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[ glEnd(); } /* return 1 if nothing was drawn */ -static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt) +static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + int dt, const unsigned char ob_wire_col[4]) { Object *ob = base->object; MetaBall *mb; @@ -5898,13 +5908,19 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, mb = ob->data; if (mb->editelems) { - UI_ThemeColor(TH_WIRE); - if ((G.f & G_PICKSEL) == 0) drawDispList(scene, v3d, rv3d, base, dt); + if ((G.f & G_PICKSEL) == 0) { + unsigned char wire_col[3]; + UI_GetThemeColor3ubv(TH_WIRE, wire_col); + glColor3ubv(wire_col); + + drawDispList(scene, v3d, rv3d, base, dt, wire_col); + } ml = mb->editelems->first; } else { - if ((base->flag & OB_FROMDUPLI) == 0) - drawDispList(scene, v3d, rv3d, base, dt); + if ((base->flag & OB_FROMDUPLI) == 0) { + drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); + } ml = mb->elems.first; } @@ -6276,7 +6292,8 @@ static void drawtexspace(Object *ob) } /* draws wire outline */ -static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base) +static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, + const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; @@ -6315,7 +6332,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base) } else if (ob->type == OB_ARMATURE) { if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) - draw_armature(scene, v3d, ar, base, OB_WIRE, FALSE, TRUE); + draw_armature(scene, v3d, ar, base, OB_WIRE, FALSE, ob_wire_col, TRUE); } glLineWidth(1.0); @@ -6407,19 +6424,13 @@ static void draw_hooks(Object *ob) } } -static void drawRBpivot(bRigidBodyJointConstraint *data) +static void drawRBpivot(bRigidBodyJointConstraint *data, const unsigned char ob_wire_col[4]) { const char *axis_str[3] = {"px", "py", "pz"}; int axis; float mat[4][4]; /* color */ - float curcol[4]; - unsigned char tcol[4]; - - glGetFloatv(GL_CURRENT_COLOR, curcol); - rgb_float_to_uchar(tcol, curcol); - tcol[3] = 255; eul_to_mat4(mat, &data->axX); glLineWidth(4.0f); @@ -6438,12 +6449,87 @@ static void drawRBpivot(bRigidBodyJointConstraint *data) glVertex3fv(v); glEnd(); - view3d_cached_text_draw_add(v, axis_str[axis], 0, V3D_CACHE_TEXT_ASCII, tcol); + view3d_cached_text_draw_add(v, axis_str[axis], 0, V3D_CACHE_TEXT_ASCII, ob_wire_col); } glLineWidth(1.0f); setlinestyle(0); } +static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4], + const int warning_recursive) +{ + Object *ob = base->object; + int colindex = 0; + + /* confusing logic here, there are 2 methods of setting the color + * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. + * + * note: no theme yet for 'colindex' */ + int theme_id = TH_WIRE; + int theme_shade = 0; + + if ((scene->obedit == NULL) && + (G.moving & G_TRANSFORM_OBJ) && + (base->flag & (SELECT + BA_WAS_SEL))) + { + theme_id = TH_TRANSFORM; + } + else { + /* Sets the 'colindex' */ + if (ob->id.lib) { + colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 4 : 3; + } + else if (warning_recursive == 1) { + if (base->flag & (SELECT + BA_WAS_SEL)) { + colindex = (scene->basact == base) ? 8 : 7; + } + else { + colindex = 6; + } + } + /* Sets the 'theme_id' or fallback to wire */ + else { + if (ob->flag & OB_FROMGROUP) { + if (base->flag & (SELECT + BA_WAS_SEL)) { + /* uses darker active color for non-active + selected*/ + theme_id = TH_GROUP_ACTIVE; + + if (scene->basact != base) { + theme_shade = -16; + } + } + else { + theme_id = TH_GROUP; + } + } + else { + if (base->flag & (SELECT + BA_WAS_SEL)) { + theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; + } + else { + if (ob->type == OB_LAMP) theme_id = TH_LAMP; + else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER; + else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA; + else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY; + /* fallback to TH_WIRE */ + } + } + } + } + + /* finally set the color */ + if (colindex == 0) { + if (theme_shade == 0) UI_GetThemeColor3ubv(theme_id, r_ob_wire_col); + else UI_GetThemeColorShade3ubv(theme_id, theme_shade, r_ob_wire_col); + } + else { + cpack_cpy_3ub(r_ob_wire_col, colortab[colindex]); + } + + /* no reason to use this but some functions take col[4] */ + r_ob_wire_col[3] = 255; +} + /* flag can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) { @@ -6454,7 +6540,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) RegionView3D *rv3d = ar->regiondata; float vec1[3], vec2[3]; unsigned int col = 0; - int /*sel, drawtype,*/ colindex = 0; + unsigned char ob_wire_col[4]; int i, selstart, selend, empty_object = 0; short dt, dtx, zbufoff = 0; const short is_obact = (ob == OBACT); @@ -6515,73 +6601,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* which wire color */ if ((flag & DRAW_CONSTCOLOR) == 0) { - /* confusing logic here, there are 2 methods of setting the color - * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. - * - * note: no theme yet for 'colindex' */ - int theme_id = TH_WIRE; - int theme_shade = 0; project_short(ar, ob->obmat[3], &base->sx); - if ((scene->obedit == NULL) && - (G.moving & G_TRANSFORM_OBJ) && - (base->flag & (SELECT + BA_WAS_SEL))) - { - theme_id = TH_TRANSFORM; - } - else { - /* Sets the 'colindex' */ - if (ob->id.lib) { - colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 4 : 3; - } - else if (warning_recursive == 1) { - if (base->flag & (SELECT + BA_WAS_SEL)) { - colindex = (scene->basact == base) ? 8 : 7; - } - else { - colindex = 6; - } - } - /* Sets the 'theme_id' or fallback to wire */ - else { - if (ob->flag & OB_FROMGROUP) { - if (base->flag & (SELECT + BA_WAS_SEL)) { - /* uses darker active color for non-active + selected*/ - theme_id = TH_GROUP_ACTIVE; - - if (scene->basact != base) { - theme_shade = -16; - } - } - else { - theme_id = TH_GROUP; - } - } - else { - if (base->flag & (SELECT + BA_WAS_SEL)) { - theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; - } - else { - if (ob->type == OB_LAMP) theme_id = TH_LAMP; - else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER; - else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA; - else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY; - /* fallback to TH_WIRE */ - } - } - } - } + draw_object_wire_color(scene, base, ob_wire_col, warning_recursive); - /* finally set the color */ - if (colindex == 0) { - if (theme_shade == 0) UI_ThemeColor(theme_id); - else UI_ThemeColorShade(theme_id, theme_shade); - } - else { - col = colortab[colindex]; - cpack(col); - } + glColor3ubv(ob_wire_col); } /* maximum drawtype */ @@ -6642,7 +6667,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (flag & DRAW_SCENESET) == 0) { if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(flag & DRAW_PICKING)) { - drawObjectSelect(scene, v3d, ar, base); + drawObjectSelect(scene, v3d, ar, base, ob_wire_col); } } } @@ -6661,11 +6686,11 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if (cu->flag & CU_FAST) { cpack(0xFFFFFF); set_inverted_drawing(1); - drawDispList(scene, v3d, rv3d, base, OB_WIRE); + drawDispList(scene, v3d, rv3d, base, OB_WIRE, ob_wire_col); set_inverted_drawing(0); } else { - drawDispList(scene, v3d, rv3d, base, dt); + drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); } if (cu->linewidth != 0.0f) { @@ -6740,7 +6765,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } } else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt); + empty_object = drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); } break; @@ -6750,7 +6775,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if (cu->editnurb) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); - drawnurb(scene, v3d, rv3d, base, nurbs->first, dt); + drawnurb(scene, v3d, rv3d, base, nurbs->first, dt, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && (v3d->drawtype >= OB_WIRE)) == 0) { @@ -6758,7 +6783,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } } else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt); + empty_object = drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); //XXX old animsys if (cu->path) // curve_draw_speed(scene, ob); @@ -6769,14 +6794,14 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) MetaBall *mb = ob->data; if (mb->editelems) - drawmball(scene, v3d, rv3d, base, dt); + drawmball(scene, v3d, rv3d, base, dt, ob_wire_col); else if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && (v3d->drawtype >= OB_WIRE)) == 0) { draw_bounding_volume(scene, ob, ob->boundtype); } } else - empty_object = drawmball(scene, v3d, rv3d, base, dt); + empty_object = drawmball(scene, v3d, rv3d, base, dt, ob_wire_col); break; } case OB_EMPTY: @@ -6791,7 +6816,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) break; case OB_LAMP: if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - drawlamp(scene, v3d, rv3d, base, dt, flag); + drawlamp(scene, v3d, rv3d, base, dt, flag, ob_wire_col); if (dtx || (base->flag & SELECT)) glMultMatrixf(ob->obmat); } break; @@ -6799,7 +6824,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0 || (rv3d->persp == RV3D_CAMOB && v3d->camera == ob)) /* special exception for active camera */ { - drawcamera(scene, v3d, rv3d, base, flag); + drawcamera(scene, v3d, rv3d, base, flag, ob_wire_col); break; } case OB_SPEAKER: @@ -6822,7 +6847,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) else { if (dt > OB_WIRE) GPU_enable_material(0, NULL); /* we use default material */ - empty_object = draw_armature(scene, v3d, ar, base, dt, flag, FALSE); + empty_object = draw_armature(scene, v3d, ar, base, dt, flag, ob_wire_col, FALSE); if (dt > OB_WIRE) GPU_disable_material(); } @@ -7026,7 +7051,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if (con->type == CONSTRAINT_TYPE_RIGIDBODYJOINT) { bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint *)con->data; if (data->flag & CONSTRAINT_DRAW_PIVOT) - drawRBpivot(data); + drawRBpivot(data, ob_wire_col); } } @@ -7054,13 +7079,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ /* but, we also don't draw names for sets or duplicators */ if (flag == 0) { - float zero[3] = {0, 0, 0}; - float curcol[4]; - unsigned char tcol[4]; - glGetFloatv(GL_CURRENT_COLOR, curcol); - rgb_float_to_uchar(tcol, curcol); - tcol[3] = 255; - view3d_cached_text_draw_add(zero, ob->id.name + 2, 10, 0, tcol); + const float zero[3] = {0, 0, 0}; + view3d_cached_text_draw_add(zero, ob->id.name + 2, 10, 0, ob_wire_col); } } /*if (dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c42264e4dac..7c12816741d 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1127,7 +1127,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) #ifdef VIEW3D_CAMERA_BORDER_HACK if (view3d_camera_border_hack_test == TRUE) { - glColor4fv(view3d_camera_border_hack_col); + glColor3ubv(view3d_camera_border_hack_col); glRectf(x1i + 1, y1i + 1, x2i - 1, y2i - 1); view3d_camera_border_hack_test = FALSE; } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 29edc0158d6..de259efdf59 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -128,7 +128,9 @@ void view3d_cached_text_draw_end(View3D * v3d, ARegion * ar, int depth_write, fl #define V3D_CACHE_TEXT_LOCALCLIP (1 << 4) /* drawarmature.c */ -int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag, const short is_outline); +int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, + int dt, int flag, const unsigned char ob_wire_col[4], + const short is_outline); /* drawmesh.c */ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, @@ -211,7 +213,7 @@ void draw_volume(struct ARegion *ar, struct GPUTexture *tex, float min[3], float * any direction it starts to fail */ #define VIEW3D_CAMERA_BORDER_HACK #ifdef VIEW3D_CAMERA_BORDER_HACK -extern float view3d_camera_border_hack_col[4]; +extern unsigned char view3d_camera_border_hack_col[3]; extern short view3d_camera_border_hack_test; #endif -- cgit v1.2.3 From 023fba473546ad1975f03a7490a3829286e82f03 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 6 Jun 2012 18:11:12 +0000 Subject: Transform Locks UI: * Some beautifying and cleanup to show X, Y, Z label. This fixes [#31717] Transform Locks panel -> no x,y,z coordinates are displayed --- .../scripts/startup/bl_ui/properties_data_bone.py | 33 +++++++++++++--------- release/scripts/startup/bl_ui/properties_object.py | 31 +++++++++++--------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py index 11524cf9c03..0f09893647a 100644 --- a/release/scripts/startup/bl_ui/properties_data_bone.py +++ b/release/scripts/startup/bl_ui/properties_data_bone.py @@ -119,21 +119,28 @@ class BONE_PT_transform_locks(BoneButtonsPanel, Panel): bone = context.bone pchan = ob.pose.bones[bone.name] - row = layout.row() - col = row.column() - col.prop(pchan, "lock_location") - col.active = not (bone.parent and bone.use_connect) + split = layout.split(percentage=0.1) + + col = split.column(align=True) + col.label(text="") + col.label(text="X:") + col.label(text="Y:") + col.label(text="Z:") + + col = split.row() + sub = col.row() + sub.active = not (bone.parent and bone.use_connect) + sub.column().prop(pchan, "lock_location", text="Location") + col.column().prop(pchan, "lock_rotation", text="Rotation") + col.column().prop(pchan, "lock_scale", text="Scale") - col = row.column() if pchan.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}: - col.prop(pchan, "lock_rotations_4d", text="Lock Rotation") - if pchan.lock_rotations_4d: - col.prop(pchan, "lock_rotation_w", text="W") - col.prop(pchan, "lock_rotation", text="") - else: - col.prop(pchan, "lock_rotation", text="Rotation") - - row.column().prop(pchan, "lock_scale") + row = layout.row() + row.prop(pchan, "lock_rotations_4d", text="Lock Rotation") + + sub = row.row() + sub.active = pchan.lock_rotations_4d + sub.prop(pchan, "lock_rotation_w", text="W") class BONE_PT_relations(BoneButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 4f3ca26725c..87c62e2791f 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -104,21 +104,26 @@ class OBJECT_PT_transform_locks(ObjectButtonsPanel, Panel): ob = context.object - row = layout.row() - - col = row.column() - col.prop(ob, "lock_location", text="Location") + split = layout.split(percentage=0.1) + + col = split.column(align=True) + col.label(text="") + col.label(text="X:") + col.label(text="Y:") + col.label(text="Z:") + + col = split.row() + col.column().prop(ob, "lock_location", text="Location") + col.column().prop(ob, "lock_rotation", text="Rotation") + col.column().prop(ob, "lock_scale", text="Scale") - col = row.column() if ob.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}: - col.prop(ob, "lock_rotations_4d", text="Rotation") - if ob.lock_rotations_4d: - col.prop(ob, "lock_rotation_w", text="W") - col.prop(ob, "lock_rotation", text="") - else: - col.prop(ob, "lock_rotation", text="Rotation") - - row.column().prop(ob, "lock_scale", text="Scale") + row = layout.row() + row.prop(ob, "lock_rotations_4d", text="Lock Rotation") + + sub = row.row() + sub.active = ob.lock_rotations_4d + sub.prop(ob, "lock_rotation_w", text="W") class OBJECT_PT_relations(ObjectButtonsPanel, Panel): -- cgit v1.2.3 From 3e3e5b2ea3a8dadfbd1dcfe295ddf28bc2236141 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 18:38:01 +0000 Subject: replace glGetFloatv(GL_CURRENT_COLOR, col_f); with the current wire color arg. --- source/blender/editors/space_view3d/drawarmature.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 0803654fd68..cb8b309dc72 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1995,9 +1995,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, float vec[3]; unsigned char col[4]; - float col_f[4]; - glGetFloatv(GL_CURRENT_COLOR, col_f); /* in case this is not set below */ - rgb_float_to_uchar(col, col_f); + col[0] = ob_wire_col[0]; + col[1] = ob_wire_col[1]; + col[2] = ob_wire_col[2]; col[3] = 255; if (v3d->zbuf) glDisable(GL_DEPTH_TEST); -- cgit v1.2.3 From f43a733f591377f2cdce0555443dba003c05fd30 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 6 Jun 2012 18:58:30 +0000 Subject: Changed semantic of recently added start_frame Now it's indicates at which scene frame number movie clip starts playing back. This this setting is still belongs to clip datavlock and used by all users of clip such as movie compositor nodes, constraints and so. After long discussion and thoughts about this it was decided that this would match image's current behavior (which initially seen a bit crappy), but that's actually allows: - Keep semantics of start frame in image and clip datablocks in sync - Allows to support features like support of loading image sequences with crappy numbers in suffix which doesn't fit long int. - Allows to eliminate extra boolean checkbox to control such kind of offset. Hopefully from pipeline POV it wouldn't hurt because idea of having this things implemented in original way was working only if sequence before processing started naming form 001. --- release/scripts/startup/bl_ui/space_clip.py | 4 +- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_movieclip.h | 3 + source/blender/blenkernel/intern/constraint.c | 13 ++-- source/blender/blenkernel/intern/movieclip.c | 39 ++++++------ source/blender/blenkernel/intern/tracking.c | 12 ++-- source/blender/blenloader/intern/readfile.c | 53 +++++++++------- source/blender/editors/include/ED_clip.h | 2 + source/blender/editors/space_clip/clip_draw.c | 22 +++---- source/blender/editors/space_clip/clip_editor.c | 19 +++--- source/blender/editors/space_clip/tracking_ops.c | 71 ++++++++++++++-------- .../editors/transform/transform_conversions.c | 7 ++- source/blender/makesdna/DNA_movieclip_types.h | 2 +- source/blender/makesrna/intern/rna_movieclip.c | 9 +-- 14 files changed, 146 insertions(+), 112 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 9f283b70f77..0174762fcc8 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -960,9 +960,7 @@ class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): col = layout.column() col.template_movieclip(sc, "clip", compact=True) - col.prop(clip, "use_custom_start_frame") - if clip.use_custom_start_frame: - col.prop(clip, "start_frame") + col.prop(clip, "start_frame") class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel): diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 6fccf819d05..db8fcd4a0d3 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 263 -#define BLENDER_SUBVERSION 9 +#define BLENDER_SUBVERSION 10 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 15b3cb91b90..221ae99a0ec 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -63,6 +63,9 @@ void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUs void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, int undistorted); +int BKE_movieclip_remap_scene_to_clip_frame(struct MovieClip *clip, int framenr); +int BKE_movieclip_remap_clip_to_scene_frame(struct MovieClip *clip, int framenr); + /* cacheing flags */ #define MOVIECLIP_CACHE_SKIP (1 << 0) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c6a0ecc057a..afd50de8159 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3897,6 +3897,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase MovieTrackingTrack *track; MovieTrackingObject *tracking_object; Object *camob = data->camera ? data->camera : scene->camera; + int framenr; if (data->flag & FOLLOWTRACK_ACTIVECLIP) clip = scene->clip; @@ -3919,6 +3920,8 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (!track) return; + framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); + if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { if (track->flag & TRACK_HAS_BUNDLE) { float obmat[4][4], mat[4][4]; @@ -3930,7 +3933,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase copy_m4_m4(mat, camob->obmat); - BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, imat); + BKE_tracking_get_interpolated_camera(tracking, tracking_object, framenr, imat); invert_m4(imat); mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL); @@ -3969,7 +3972,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase CameraParams params; float pos[2], rmat[4][4]; - marker = BKE_tracking_get_marker(track, scene->r.cfra); + marker = BKE_tracking_get_marker(track, framenr); add_v2_v2v2(pos, marker->pos, track->offset); @@ -4092,8 +4095,9 @@ static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float mat[4][4], obmat[4][4]; MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object = BKE_tracking_get_camera_object(tracking); + int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); - BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat); + BKE_tracking_get_interpolated_camera(tracking, object, framenr, mat); copy_m4_m4(obmat, cob->matrix); @@ -4156,10 +4160,11 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (object) { float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; + int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); BKE_object_where_is_calc_mat4(scene, camob, cammat); - BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat); + BKE_tracking_get_interpolated_camera(tracking, object, framenr, mat); invert_m4_m4(camimat, cammat); mult_m4_m4m4(parmat, cammat, data->invmat); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index a90fc28cd1e..de12926f3eb 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -153,18 +153,13 @@ static void get_sequence_fname(MovieClip *clip, int framenr, char *name) BLI_strncpy(name, clip->name, sizeof(clip->name)); BLI_stringdec(name, head, tail, &numlen); - if (clip->flag & MCLIP_CUSTOM_START_FRAME) { - offset = clip->start_frame; - } - else { - /* movieclips always points to first image from sequence, - * autoguess offset for now. could be something smarter in the future - */ - offset = sequence_guess_offset(clip->name, strlen(head), numlen); - } + /* movieclips always points to first image from sequence, + * autoguess offset for now. could be something smarter in the future + */ + offset = sequence_guess_offset(clip->name, strlen(head), numlen); if (numlen) - BLI_stringenc(name, head, tail, numlen, offset + framenr - 1); + BLI_stringenc(name, head, tail, numlen, offset + framenr - clip->start_frame); else BLI_strncpy(name, clip->name, sizeof(clip->name)); @@ -176,6 +171,7 @@ static void get_proxy_fname(MovieClip *clip, int proxy_render_size, int undistor { int size = rendersize_to_number(proxy_render_size); char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX]; + int proxynr = framenr - clip->start_frame + 1; BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX); @@ -187,9 +183,9 @@ static void get_proxy_fname(MovieClip *clip, int proxy_render_size, int undistor } if (undistorted) - BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, framenr); + BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr); else - BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, framenr); + BLI_snprintf(name, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr); BLI_path_abs(name, G.main->name); BLI_path_frame(name, 1, 0); @@ -254,11 +250,7 @@ static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, in int fra; dur = IMB_anim_get_duration(clip->anim, tc); - fra = framenr - 1; - - if (clip->flag & MCLIP_CUSTOM_START_FRAME) { - fra += clip->start_frame - 1; - } + fra = framenr - clip->start_frame; if (fra < 0) fra = 0; @@ -1038,7 +1030,8 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip if (act_track) { MovieTrackingTrack *track = act_track; - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, user->framenr); + int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if (marker->flag & MARKER_DISABLED) { scopes->track_disabled = TRUE; @@ -1230,3 +1223,13 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip) clip->id.us = 0; } + +int BKE_movieclip_remap_scene_to_clip_frame(MovieClip *clip, int framenr) +{ + return framenr - clip->start_frame + 1; +} + +int BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, int framenr) +{ + return framenr + clip->start_frame - 1; +} diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index b0745ebf1c8..4abb461bc81 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -972,7 +972,8 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u track = tracksbase->first; while (track) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, user->framenr); + int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) num_tracks++; @@ -993,7 +994,8 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u track = tracksbase->first; while (track) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, user->framenr); + int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) { TrackContext track_context; @@ -1311,7 +1313,7 @@ static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) ImBuf *ibuf; MovieClipUser user = context->user; - user.framenr = framenr; + user.framenr = BKE_movieclip_remap_clip_to_scene_frame(context->clip, framenr); ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag, MOVIECLIP_CACHE_SKIP); @@ -1399,7 +1401,7 @@ void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) int BKE_tracking_next(MovieTrackingContext *context) { ImBuf *ibuf_new; - int curfra = context->user.framenr; + int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr); int a, ok = FALSE, map_size; map_size = tracks_map_size(context->tracks_map); @@ -1529,7 +1531,7 @@ int BKE_tracking_next(MovieTrackingContext *context) marker_new.framenr = nextfra; marker_new.flag |= MARKER_DISABLED; - #pragma omp critical + //#pragma omp critical { BKE_tracking_insert_marker(track, &marker_new); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f1150d8f00a..8fccae91870 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7636,42 +7636,53 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ntreetype->foreach_nodetree(main, NULL, do_version_ntree_image_user_264); } - /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ - /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ - { - Scene *scene; - // composite redesign - for (scene=main->scene.first; scene; scene=scene->id.next) { - if (scene->nodetree) { - if (scene->nodetree->chunksize == 0) { - scene->nodetree->chunksize = 256; + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) { + { + Scene *scene; + // composite redesign + for (scene=main->scene.first; scene; scene=scene->id.next) { + if (scene->nodetree) { + if (scene->nodetree->chunksize == 0) { + scene->nodetree->chunksize = 256; + } } } } - } - { - bScreen *sc; + { + bScreen *sc; - for (sc = main->screen.first; sc; sc = sc->id.next) { - ScrArea *sa; + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; - for (sl = sa->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sclip = (SpaceClip *)sl; + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; - if (sclip->around == 0) { - sclip->around = V3D_CENTROID; + if (sclip->around == 0) { + sclip->around = V3D_CENTROID; + } } } } } } + + { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + clip->start_frame = 1; + } + } } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ + /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ + /* don't forget to set version number in blender.c! */ } diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index f7fb1709ce7..6b1028525a7 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -60,6 +60,8 @@ void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float * void ED_space_clip_aspect(struct SpaceClip *sc, float *aspx, float *aspy); void ED_space_clip_aspect_dimension_aware(struct SpaceClip *sc, float *aspx, float *aspy); +int ED_space_clip_clip_framenr(struct SpaceClip *sc); + void ED_space_clip_mask_size(struct SpaceClip *sc, int *width, int *height); void ED_space_clip_mask_aspect(struct SpaceClip *sc, float *aspx, float *aspy); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index d55d32deaa4..62ea0b00ff8 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -155,7 +155,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc else glColor4ub(255, 255, 0, 96); - glRecti((i - sfra) * framelen, 0, (i - sfra + 1)*framelen, 4); + glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4); } } } @@ -183,7 +183,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc } if (!ok) - glRecti((i - sfra) * framelen, 0, (i - sfra + 1) * framelen, 8); + glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8); } } @@ -338,17 +338,17 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin int count = sc->path_length; int i, a, b, curindex = -1; float path[102][2]; - int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr; + int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame; MovieTrackingMarker *marker; if (count == 0) return; - marker = BKE_tracking_get_marker(track, sc->user.framenr); - if (marker->framenr != sc->user.framenr || marker->flag & MARKER_DISABLED) - return; + start_frame = framenr = ED_space_clip_clip_framenr(sc); - framenr = marker->framenr; + marker = BKE_tracking_get_marker(track, framenr); + if (marker->framenr != framenr || marker->flag & MARKER_DISABLED) + return; a = count; i = framenr - 1; @@ -362,7 +362,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin add_v2_v2v2(path[--a], marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, path[a], path[a]); - if (marker->framenr == sc->user.framenr) + if (marker->framenr == start_frame) curindex = a; } else { @@ -381,7 +381,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin break; if (marker->framenr == i) { - if (marker->framenr == sc->user.framenr) + if (marker->framenr == start_frame) curindex = b; add_v2_v2v2(path[b++], marker->pos, track->offset); @@ -924,7 +924,7 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra if (marker->flag & MARKER_DISABLED) strcpy(state, "disabled"); - else if (marker->framenr != sc->user.framenr) + else if (marker->framenr != ED_space_clip_clip_framenr(sc)) strcpy(state, "estimated"); else if (marker->flag & MARKER_TRACKED) strcpy(state, "tracked"); @@ -972,7 +972,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, ListBase *tracksbase = BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track, *act_track; MovieTrackingMarker *marker; - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2]; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 3349a61cd86..ab100b46f70 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -362,6 +362,14 @@ void ED_clip_update_frame(const Main *mainp, int cfra) } } +/* return current frame number in clip space */ +int ED_space_clip_clip_framenr(SpaceClip *sc) +{ + MovieClip *clip = ED_space_clip(sc); + + return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr); +} + static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) { MovieClip *clip = ED_space_clip(sc); @@ -547,7 +555,6 @@ typedef struct SpaceClipDrawContext { /* fields to check if cache is still valid */ int framenr, start_frame; - short custom_start_frame; } SpaceClipDrawContext; int ED_space_clip_texture_buffer_supported(SpaceClip *sc) @@ -585,14 +592,7 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) * so not changed image buffer pointer means unchanged image content */ need_rebind |= context->texture_ibuf != ibuf; need_rebind |= context->framenr != sc->user.framenr; - - if (clip->flag & MCLIP_CUSTOM_START_FRAME) { - need_rebind |= context->custom_start_frame != TRUE; - need_rebind |= context->start_frame != clip->start_frame; - } - else { - need_rebind |= context->custom_start_frame != FALSE; - } + need_rebind |= context->start_frame != clip->start_frame; if (need_rebind) { int width = ibuf->x, height = ibuf->y; @@ -648,7 +648,6 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) context->image_height = ibuf->y; context->framenr = sc->user.framenr; context->start_frame = clip->start_frame; - context->custom_start_frame = (clip->flag & MCLIP_CUSTOM_START_FRAME) ? TRUE : FALSE; } else { /* displaying exactly the same image which was loaded t oa texture, diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index f6dbae596b8..7073fdb3542 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -88,10 +88,11 @@ static void add_marker(SpaceClip *sc, float x, float y) ListBase *tracksbase = BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; int width, height; + int framenr = ED_space_clip_clip_framenr(sc); ED_space_clip_size(sc, &width, &height); - track = BKE_tracking_add_track(tracking, tracksbase, x, y, sc->user.framenr, width, height); + track = BKE_tracking_add_track(tracking, tracksbase, x, y, framenr, width, height); BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, 0); @@ -202,7 +203,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) MovieClip *clip = ED_space_clip(sc); ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track = tracksbase->first, *next; - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); int has_selection = 0; while (track) { @@ -269,8 +270,9 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra MovieTrackingMarker *marker, wmEvent *event, int area, int action, int width, int height) { SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data"); + int framenr = ED_space_clip_clip_framenr(sc); - marker = BKE_tracking_ensure_marker(track, sc->user.framenr); + marker = BKE_tracking_ensure_marker(track, framenr); data->area = area; data->action = action; @@ -406,6 +408,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) float co[2]; void *customdata = NULL; ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); + int framenr = ED_space_clip_clip_framenr(sc); ED_space_clip_size(sc, &width, &height); @@ -417,7 +420,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) track = tracksbase->first; while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) { if (!customdata) @@ -671,7 +674,8 @@ static int mouse_on_rect(float co[2], float pos[2], float min[2], float max[2], static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *track) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + int framenr = ED_space_clip_clip_framenr(sc); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); float epsx, epsy; int width, height; @@ -727,10 +731,11 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas { MovieTrackingTrack *track = NULL, *cur; float mindist = 0.0f; + int framenr = ED_space_clip_clip_framenr(sc); cur = tracksbase->first; while (cur) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(cur, sc->user.framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(cur, framenr); if (((cur->flag & TRACK_HIDDEN) == 0) && MARKER_VISIBLE(sc, cur, marker)) { float dist, d1, d2 = FLT_MAX, d3 = FLT_MAX; @@ -879,6 +884,7 @@ static int border_select_exec(bContext *C, wmOperator *op) rcti rect; rctf rectf; int change = FALSE, mode, extend; + int framenr = ED_space_clip_clip_framenr(sc); /* get rectangle from operator */ rect.xmin = RNA_int_get(op->ptr, "xmin"); @@ -896,7 +902,7 @@ static int border_select_exec(bContext *C, wmOperator *op) track = tracksbase->first; while (track) { if ((track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if (MARKER_VISIBLE(sc, track, marker)) { if (BLI_in_rctf(&rectf, marker->pos[0], marker->pos[1])) { @@ -955,6 +961,7 @@ static int do_lasso_select_marker(bContext *C, int mcords[][2], short moves, sho ListBase *tracksbase = BKE_tracking_get_tracks(tracking); rcti rect; int change = FALSE; + int framenr = ED_space_clip_clip_framenr(sc); /* get rectangle from operator */ BLI_lasso_boundbox(&rect, mcords, moves); @@ -963,7 +970,7 @@ static int do_lasso_select_marker(bContext *C, int mcords[][2], short moves, sho track = tracksbase->first; while (track) { if ((track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if (MARKER_VISIBLE(sc, track, marker)) { float screen_co[2]; @@ -1057,6 +1064,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) ListBase *tracksbase = BKE_tracking_get_tracks(tracking); int x, y, radius, width, height, mode, change = FALSE; float zoomx, zoomy, offset[2], ellipse[2]; + int framenr = ED_space_clip_clip_framenr(sc); /* get operator properties */ x = RNA_int_get(op->ptr, "x"); @@ -1078,7 +1086,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) track = tracksbase->first; while (track) { if ((track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, sc->user.framenr); + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) { BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode != GESTURE_MODAL_SELECT); @@ -1135,7 +1143,7 @@ static int select_all_exec(bContext *C, wmOperator *op) MovieTrackingMarker *marker; ListBase *tracksbase = BKE_tracking_get_tracks(tracking); int action = RNA_enum_get(op->ptr, "action"); - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); int has_selection = FALSE; if (action == SEL_TOGGLE) { @@ -1225,21 +1233,22 @@ static int select_groped_exec(bContext *C, wmOperator *op) MovieTracking *tracking = &clip->tracking; ListBase *tracksbase = BKE_tracking_get_tracks(tracking); int group = RNA_enum_get(op->ptr, "group"); + int framenr = ED_space_clip_clip_framenr(sc); track = tracksbase->first; while (track) { int ok = FALSE; - marker = BKE_tracking_get_marker(track, sc->user.framenr); + marker = BKE_tracking_get_marker(track, framenr); if (group == 0) { /* Keyframed */ - ok = marker->framenr == sc->user.framenr && (marker->flag & MARKER_TRACKED) == 0; + ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED) == 0; } else if (group == 1) { /* Estimated */ - ok = marker->framenr != sc->user.framenr; + ok = marker->framenr != framenr; } else if (group == 2) { /* tracked */ - ok = marker->framenr == sc->user.framenr && (marker->flag & MARKER_TRACKED); + ok = marker->framenr == framenr && (marker->flag & MARKER_TRACKED); } else if (group == 3) { /* locked */ ok = track->flag & TRACK_LOCKED; @@ -1332,7 +1341,7 @@ static int track_count_markers(SpaceClip *sc, MovieClip *clip) int tot = 0; ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); track = tracksbase->first; while (track) { @@ -1376,7 +1385,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit { ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); int frames_limit = 0; clear_invisible_track_selection(sc, clip); @@ -1426,7 +1435,7 @@ static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backward track_init_markers(sc, clip, &frames_limit); - tmj->sfra = sc->user.framenr; + tmj->sfra = ED_space_clip_clip_framenr(sc); tmj->clip = clip; tmj->backwards = backwards; @@ -1443,6 +1452,8 @@ static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backward tmj->efra = MIN2(tmj->efra, tmj->sfra + frames_limit); } + tmj->efra = BKE_movieclip_remap_scene_to_clip_frame(clip, tmj->efra); + if (settings->speed != TRACKING_SPEED_FASTEST) { tmj->delay = 1.0f / scene->r.frs_sec * 1000.0f; @@ -1527,7 +1538,7 @@ static void track_markers_freejob(void *tmv) TrackMarkersJob *tmj = (TrackMarkersJob *)tmv; tmj->clip->tracking_context = NULL; - tmj->scene->r.cfra = tmj->lastfra; + tmj->scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(tmj->clip, tmj->lastfra); ED_update_for_newframe(tmj->main, tmj->scene, 0); BKE_tracking_sync(tmj->context); @@ -1544,7 +1555,7 @@ static int track_markers_exec(bContext *C, wmOperator *op) MovieClip *clip = ED_space_clip(sc); Scene *scene = CTX_data_scene(C); struct MovieTrackingContext *context; - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); int sfra = framenr, efra; int backwards = RNA_boolean_get(op->ptr, "backwards"); int sequence = RNA_boolean_get(op->ptr, "sequence"); @@ -1568,6 +1579,8 @@ static int track_markers_exec(bContext *C, wmOperator *op) efra = MIN2(efra, sfra + frames_limit); } + efra = BKE_movieclip_remap_scene_to_clip_frame(clip, efra); + if (!track_markers_check_direction(backwards, framenr, efra)) return OPERATOR_CANCELLED; @@ -1589,7 +1602,7 @@ static int track_markers_exec(bContext *C, wmOperator *op) BKE_tracking_context_free(context); /* update scene current frame to the lastes tracked frame */ - scene->r.cfra = framenr; + scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -1967,16 +1980,17 @@ static int clear_track_path_exec(bContext *C, wmOperator *op) ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); int action = RNA_enum_get(op->ptr, "action"); int clear_active = RNA_boolean_get(op->ptr, "clear_active"); + int framenr = ED_space_clip_clip_framenr(sc); if (clear_active) { track = BKE_tracking_active_track(&clip->tracking); - BKE_tracking_clear_path(track, sc->user.framenr, action); + BKE_tracking_clear_path(track, framenr, action); } else { track = tracksbase->first; while (track) { if (TRACK_VIEW_SELECTED(sc, track)) - BKE_tracking_clear_path(track, sc->user.framenr, action); + BKE_tracking_clear_path(track, framenr, action); track = track->next; } @@ -2023,10 +2037,11 @@ static int disable_markers_exec(bContext *C, wmOperator *op) ListBase *tracksbase = BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track = tracksbase->first; int action = RNA_enum_get(op->ptr, "action"); + int framenr = ED_space_clip_clip_framenr(sc); while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, sc->user.framenr); + MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, framenr); if (action == 0) marker->flag |= MARKER_DISABLED; @@ -2945,6 +2960,7 @@ static int detect_features_exec(bContext *C, wmOperator *op) int min_trackability = RNA_int_get(op->ptr, "min_trackability"); int min_distance = RNA_int_get(op->ptr, "min_distance"); int place_outside_layer = 0; + int framenr = ED_space_clip_clip_framenr(sc); bGPDlayer *layer = NULL; if (placement != 0) { @@ -2961,7 +2977,7 @@ static int detect_features_exec(bContext *C, wmOperator *op) track = track->next; } - BKE_tracking_detect_fast(tracking, tracksbase, ibuf, sc->user.framenr, margin, + BKE_tracking_detect_fast(tracking, tracksbase, ibuf, framenr, margin, min_trackability, min_distance, layer, place_outside_layer); IMB_freeImBuf(ibuf); @@ -3019,7 +3035,8 @@ static int frame_jump_exec(bContext *C, wmOperator *op) delta = pos == 1 ? 1 : -1; while (sc->user.framenr + delta >= SFRA && sc->user.framenr + delta <= EFRA) { - MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, sc->user.framenr + delta); + int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr + delta); + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); if (!marker || marker->flag & MARKER_DISABLED) break; @@ -3029,7 +3046,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) } else { /* to to failed frame */ if (clip->tracking.reconstruction.flag & TRACKING_RECONSTRUCTED) { - int a = sc->user.framenr; + int a = ED_space_clip_clip_framenr(sc); MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object = BKE_tracking_active_object(tracking); @@ -3043,7 +3060,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) cam = BKE_tracking_get_reconstructed_camera(tracking, object, a); if (!cam) { - sc->user.framenr = a; + sc->user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, a); break; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 19d97b64f54..0391afdc188 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5474,7 +5474,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, TransDataTracking *tdt, MovieTrackingTrack *track) { - MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, sc->user.framenr); + int framenr = ED_space_clip_clip_framenr(sc); + MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, framenr); tdt->flag = marker->flag; marker->flag &= ~(MARKER_DISABLED|MARKER_TRACKED); @@ -5517,7 +5518,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) MovieTrackingTrack *track; MovieTrackingMarker *marker; TransDataTracking *tdt; - int framenr = sc->user.framenr; + int framenr = ED_space_clip_clip_framenr(sc); /* count */ t->total = 0; @@ -5747,7 +5748,7 @@ static void cancelTransTracking(TransInfo *t) ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; MovieTrackingMarker *marker; - int a, framenr = sc->user.framenr; + int a, framenr = ED_space_clip_clip_framenr(sc); if (tdt->mode == transDataTracking_ModeTracks) { track = tracksbase->first; diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 81d532fd247..fd7046854ff 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -123,7 +123,7 @@ typedef struct MovieClipScopes { /* MovieClip->flag */ #define MCLIP_USE_PROXY (1<<0) #define MCLIP_USE_PROXY_CUSTOM_DIR (1<<1) -#define MCLIP_CUSTOM_START_FRAME (1<<2) +/*#define MCLIP_CUSTOM_START_FRAME (1<<2)*/ /* UNUSED */ #define MCLIP_TIMECODE_FLAGS (MCLIP_USE_PROXY|MCLIP_USE_PROXY_CUSTOM_DIR) diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 70cb0de643e..592e2c9f348 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -285,17 +285,10 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip"); - /* use custom offset */ - prop = RNA_def_property(srna, "use_custom_start_frame", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MCLIP_CUSTOM_START_FRAME); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Custom Start Frame", "Use custom first frame offset instead of automatic frame number"); - RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update"); - /* frame offset */ prop = RNA_def_property(srna, "start_frame", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "start_frame"); - RNA_def_property_ui_text(prop, "Start Frame", "Number of frame from sequence or movie displaying at scene frame #1"); + RNA_def_property_ui_text(prop, "Start Frame", "Global scene frame number at which this movie starts playing"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update"); } -- cgit v1.2.3 From 67326ad4d9b0c4eef281ee9835468173e62cb817 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 19:20:39 +0000 Subject: group outliner option to instance selected groups in the scene. --- .../editors/space_outliner/outliner_tools.c | 78 ++++++++++++---------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index b556fbf5c9d..e656b1242ab 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -385,6 +385,18 @@ static void group_linkobs2scene_cb(bContext *UNUSED(C), Scene *scene, TreeElemen } } +static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem) +{ + Group *group = (Group *)tselem->id; + + Object *ob = ED_object_add_type(C, OB_EMPTY, scene->cursor, NULL, FALSE, scene->layact); + rename_id(&ob->id, group->id.name + 2); + ob->dup_group = group; + ob->transflag |= OB_DUPLIGROUP; + id_lib_extern(&group->id); +} + void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soops, ListBase *lb, void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *)) @@ -636,13 +648,14 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot) /* **************************************** */ static EnumPropertyItem prop_group_op_types[] = { - {1, "UNLINK", 0, "Unlink", ""}, - {2, "LOCAL", 0, "Make Local", ""}, - {3, "LINK", 0, "Link Group Objects to Scene", ""}, - {4, "TOGVIS", 0, "Toggle Visible", ""}, - {5, "TOGSEL", 0, "Toggle Selectable", ""}, - {6, "TOGREN", 0, "Toggle Renderable", ""}, - {7, "RENAME", 0, "Rename", ""}, + {0, "UNLINK", 0, "Unlink Group", ""}, + {1, "LOCAL", 0, "Make Local Group", ""}, + {2, "LINK", 0, "Link Group Objects to Scene", ""}, + {3, "INSTANCE", 0, "Instance Group in Scene", ""}, + {4, "TOGVIS", 0, "Toggle Visible Group", ""}, + {5, "TOGSEL", 0, "Toggle Selectable", ""}, + {6, "TOGREN", 0, "Toggle Renderable", ""}, + {7, "RENAME", 0, "Rename", ""}, {0, NULL, 0, NULL, NULL} }; @@ -651,45 +664,36 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); int event; - const char *str = NULL; /* check for invalid states */ if (soops == NULL) return OPERATOR_CANCELLED; event = RNA_enum_get(op->ptr, "type"); - - if (event == 1) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_group_cb); - str = "Unlink group"; - } - else if (event == 2) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb); - str = "Localized Data"; - } - else if (event == 3) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_linkobs2scene_cb); - str = "Link Group Objects to Scene"; - } - else if (event == 4) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_visibility_cb); - str = "Toggle Visibility"; - } - else if (event == 5) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_selectability_cb); - str = "Toggle Selectability"; - } - else if (event == 6) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_renderability_cb); - str = "Toggle Renderability"; - } - else if (event == 7) { - outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb); - str = "Rename"; + + switch (event) { + case 0: outliner_do_libdata_operation(C, scene, soops, &soops->tree, unlink_group_cb); break; + case 1: outliner_do_libdata_operation(C, scene, soops, &soops->tree, id_local_cb); break; + case 2: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_linkobs2scene_cb); break; + case 3: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_instance_cb); break; + case 4: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_visibility_cb); break; + case 5: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_selectability_cb); break; + case 6: outliner_do_libdata_operation(C, scene, soops, &soops->tree, group_toggle_renderability_cb); break; + case 7: outliner_do_libdata_operation(C, scene, soops, &soops->tree, item_rename_cb); break; + default: + BLI_assert(0); + return OPERATOR_CANCELLED; } + + if (event == 3) { /* instance */ + Main *bmain = CTX_data_main(C); + + /* works without this except if you try render right after, see: 22027 */ + DAG_scene_sort(bmain, scene); + } - ED_undo_push(C, str); + ED_undo_push(C, prop_group_op_types[event].name); WM_event_add_notifier(C, NC_GROUP, NULL); return OPERATOR_FINISHED; -- cgit v1.2.3 From fdf0d01d08a91dbd0260b49d2b9cc91b6cab570f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 19:36:26 +0000 Subject: disable group/object selection in the outliner, it slows down drawing far too much. --- .../blender/editors/space_outliner/outliner_draw.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 547e8288d20..483016b7e00 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -69,6 +69,9 @@ #include "outliner_intern.h" +/* disable - this is far too slow - campbell */ +// #define USE_GROUP_SELECT + /* ****************************************************** */ /* Tree Size Functions */ @@ -207,6 +210,7 @@ static int group_restrict_flag(Group *gr, int flag) return 1; } +#ifdef USE_GROUP_SELECT static int group_select_flag(Group *gr) { GroupObject *gob; @@ -217,6 +221,7 @@ static int group_select_flag(Group *gr) return 0; } +#endif void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) { @@ -422,16 +427,26 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar gr = (Group *)tselem->id; uiBlockSetEmboss(block, UI_EMBOSSN); - + +#ifndef USE_GROUP_SELECT + restrict_bool = FALSE; +#endif + +#ifdef USE_GROUP_SELECT restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW); +#endif bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr); +#ifdef USE_GROUP_SELECT restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT); +#endif bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr); - + +#ifdef USE_GROUP_SELECT restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER); +#endif bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, "Restrict/Allow renderability"); uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr); @@ -1274,8 +1289,8 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene } } else if (te->idcode == ID_GR) { +#ifdef USE_GROUP_SELECT Group *gr = (Group *)tselem->id; - if (group_select_flag(gr)) { char col[4]; UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col); @@ -1284,6 +1299,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene active = 2; } +#endif } else if (te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; -- cgit v1.2.3 From 3e8ad394af94a88791ced5aae573f105fb3d501d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 20:05:58 +0000 Subject: code cleanup: remove unused mask args --- source/blender/blenkernel/BKE_mask.h | 11 +++++------ source/blender/blenkernel/intern/mask.c | 22 +++++++++++----------- source/blender/editors/mask/mask_add.c | 14 +++++++------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 19feb4d8f2e..2537e84a62c 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -122,13 +122,12 @@ void BKE_mask_update_display(struct Mask *mask, float ctime); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); -void BKE_mask_calc_handle_adjacent_interp(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, - const float u); -void BKE_mask_calc_tangent_polyline(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); -void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point); -void BKE_mask_calc_handle_point_auto(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, +void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); +void BKE_mask_calc_tangent_polyline(struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); +void BKE_mask_calc_handle_point(struct MaskSpline *spline, struct MaskSplinePoint *point); +void BKE_mask_calc_handle_point_auto(struct MaskSpline *spline, struct MaskSplinePoint *point, const short do_recalc_length); -void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point, +void BKE_mask_get_handle_point_adjacent(struct MaskSpline *spline, struct MaskSplinePoint *point, struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); void BKE_mask_calc_handles(struct Mask *mask); void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index aaefa558c9b..315b97c1866 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1228,7 +1228,7 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *poin #endif } -void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, MaskSplinePoint *point, +void BKE_mask_get_handle_point_adjacent(MaskSpline *spline, MaskSplinePoint *point, MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) { int i = (int)(point - spline->points); @@ -1241,13 +1241,13 @@ void BKE_mask_get_handle_point_adjacent(Mask *UNUSED(mask), MaskSpline *spline, /* calculates the tanget of a point by its previous and next * (ignoring handles - as if its a poly line) */ -void BKE_mask_calc_tangent_polyline(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, float t[2]) +void BKE_mask_calc_tangent_polyline(MaskSpline *spline, MaskSplinePoint *point, float t[2]) { float tvec_a[2], tvec_b[2]; MaskSplinePoint *point_prev, *point_next; - BKE_mask_get_handle_point_adjacent(mask, spline, point, + BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next); if (point_prev) { @@ -1270,11 +1270,11 @@ void BKE_mask_calc_tangent_polyline(Mask *mask, MaskSpline *spline, MaskSplinePo normalize_v2(t); } -void BKE_mask_calc_handle_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *point) +void BKE_mask_calc_handle_point(MaskSpline *spline, MaskSplinePoint *point) { MaskSplinePoint *point_prev, *point_next; - BKE_mask_get_handle_point_adjacent(mask, spline, point, + BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next); mask_calc_point_handle(point, point_prev, point_next); @@ -1291,7 +1291,7 @@ static void enforce_dist_v2_v2fl(float v1[2], const float v2[2], const float dis } } -void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, const float u) +void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u) { /* TODO! - make this interpolate between siblings - not always midpoint! */ int length_tot = 0; @@ -1303,7 +1303,7 @@ void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSp BLI_assert(u >= 0.0f && u <= 1.0f); - BKE_mask_get_handle_point_adjacent(mask, spline, point, + BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next); if (point_prev && point_next) { @@ -1344,7 +1344,7 @@ void BKE_mask_calc_handle_adjacent_interp(Mask *mask, MaskSpline *spline, MaskSp * * Useful for giving sane defaults. */ -void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplinePoint *point, +void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point, const short do_recalc_length) { MaskSplinePoint *point_prev, *point_next; @@ -1353,7 +1353,7 @@ void BKE_mask_calc_handle_point_auto(Mask *mask, MaskSpline *spline, MaskSplineP (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) + len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) / 2.0f; - BKE_mask_get_handle_point_adjacent(mask, spline, point, + BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next); point->bezt.h1 = HD_AUTO; @@ -1381,11 +1381,11 @@ void BKE_mask_calc_handles(Mask *mask) int i; for (i = 0; i < spline->tot_point; i++) { - BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + BKE_mask_calc_handle_point(spline, &spline->points[i]); /* could be done in a different function... */ if (spline->points_deform) { - BKE_mask_calc_handle_point(mask, spline, &spline->points[i]); + BKE_mask_calc_handle_point(spline, &spline->points[i]); } } } diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index f8c36e866d7..7ffff2b06e5 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -235,7 +235,7 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[2], vec); if (reference_adjacent) { - BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); + BKE_mask_calc_handle_adjacent_interp(spline, new_point, u); } } else { @@ -287,8 +287,8 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask add_v2_v2(bezt->vec[0], vec); sub_v2_v2(bezt->vec[2], vec); #else - BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE); - BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u); + BKE_mask_calc_handle_point_auto(spline, new_point, TRUE); + BKE_mask_calc_handle_adjacent_interp(spline, new_point, u); #endif } @@ -425,7 +425,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const if ((spline->flag & MASK_SPLINE_CYCLIC) || (point_index > 0 && point_index != spline->tot_point - 1)) { - BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point); + BKE_mask_calc_tangent_polyline(spline, point, tangent_point); sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]); if (dot_v2v2(tangent_point, tangent_co) < 0.0f) { @@ -487,7 +487,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const if (do_recalc_src) { /* TODO, update keyframes in time */ - BKE_mask_calc_handle_point_auto(mask, spline, ref_point, FALSE); + BKE_mask_calc_handle_point_auto(spline, ref_point, FALSE); } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -572,8 +572,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op) spline->flag |= MASK_SPLINE_CYCLIC; /* TODO, update keyframes in time */ - BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE); - BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE); + BKE_mask_calc_handle_point_auto(spline, point, FALSE); + BKE_mask_calc_handle_point_auto(spline, point_other, FALSE); /* TODO: only update this spline */ BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); -- cgit v1.2.3 From 052e34cc3d52bee1678bd0b2a015b7de97ae7ad7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 20:26:26 +0000 Subject: fix for bug where auto-handles were not calculated correctly for animated curves. --- source/blender/blenkernel/BKE_mask.h | 3 ++ source/blender/blenkernel/intern/mask.c | 56 ++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 2537e84a62c..a93e811557a 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -129,7 +129,10 @@ void BKE_mask_calc_handle_point_auto(struct MaskSpline *spline, struct MaskSplin const short do_recalc_length); void BKE_mask_get_handle_point_adjacent(struct MaskSpline *spline, struct MaskSplinePoint *point, struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next); +void BKE_mask_layer_calc_handles(struct MaskLayer *masklay); +void BKE_mask_layer_calc_handles_deform(struct MaskLayer *masklay); void BKE_mask_calc_handles(struct Mask *mask); +void BKE_mask_calc_handles_deform(struct Mask *mask); void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); /* animation */ diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 315b97c1866..f7679d473b9 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1231,12 +1231,11 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *poin void BKE_mask_get_handle_point_adjacent(MaskSpline *spline, MaskSplinePoint *point, MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next) { - int i = (int)(point - spline->points); - BLI_assert(i >= i && i < spline->tot_point); - (void)i; /* quiet release builds */ + /* TODO, could avoid calling this at such low level */ + MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - *r_point_prev = mask_spline_point_prev(spline, spline->points, point); - *r_point_next = mask_spline_point_next(spline, spline->points, point); + *r_point_prev = mask_spline_point_prev(spline, points_array, point); + *r_point_next = mask_spline_point_next(spline, points_array, point); } /* calculates the tanget of a point by its previous and next @@ -1370,25 +1369,41 @@ void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point, } } +void BKE_mask_layer_calc_handles(MaskLayer *masklay) +{ + MaskSpline *spline; + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + BKE_mask_calc_handle_point(spline, &spline->points[i]); + } + } +} + +void BKE_mask_layer_calc_handles_deform(MaskLayer *masklay) +{ + MaskSpline *spline; + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + for (i = 0; i < spline->tot_point; i++) { + BKE_mask_calc_handle_point(spline, &spline->points_deform[i]); + } + } +} + void BKE_mask_calc_handles(Mask *mask) { MaskLayer *masklay; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; - - for (spline = masklay->splines.first; spline; spline = spline->next) { - int i; - - for (i = 0; i < spline->tot_point; i++) { - BKE_mask_calc_handle_point(spline, &spline->points[i]); + BKE_mask_layer_calc_handles(masklay); + } +} - /* could be done in a different function... */ - if (spline->points_deform) { - BKE_mask_calc_handle_point(spline, &spline->points[i]); - } - } - } +void BKE_mask_calc_handles_deform(Mask *mask) +{ + MaskLayer *masklay; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + BKE_mask_layer_calc_handles_deform(masklay); } } @@ -1525,6 +1540,9 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) } } } + + /* TODO, move into loop above and only run if there are auto-handles */ + BKE_mask_calc_handles_deform(mask); } /* the purpose of this function is to ensure spline->points_deform is never out of date. -- cgit v1.2.3 From 04159137409e1a218845601d251506a33537b1a6 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 6 Jun 2012 21:55:55 +0000 Subject: Cmake: * Removed first line, probably accidentally committed in r47439. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd038415772..191fb61e1b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,3 @@ -set(Boost_DEBUG TRUE) # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or -- cgit v1.2.3 From 379c4ae4d8b92ae444c0372dc54872c72b10c199 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 6 Jun 2012 22:36:07 +0000 Subject: Cycles / OSL: * Missing header kernel_passes.h, needed for "direction_to_panorama" in kernel_triangle.h --- intern/cycles/kernel/osl/osl_services.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 12f3a377ef4..2d285b45d4a 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -31,6 +31,7 @@ #include "kernel_compat_cpu.h" #include "kernel_globals.h" #include "kernel_object.h" +#include "kernel_passes.h" #include "kernel_triangle.h" CCL_NAMESPACE_BEGIN -- cgit v1.2.3 From d5032657edd365ded8b98500536ecdbe1b54df5a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Jun 2012 22:38:39 +0000 Subject: style cleanup --- intern/container/CTR_UHeap.h | 6 ++--- intern/cycles/util/util_system.cpp | 4 ++-- intern/ghost/GHOST_Types.h | 3 +-- intern/mikktspace/mikktspace.c | 21 ++++++----------- intern/mikktspace/mikktspace.h | 3 +-- source/blender/blenkernel/BKE_cloth.h | 27 ++++++++-------------- source/blender/blenkernel/BKE_collision.h | 3 +-- source/blender/blenkernel/BKE_node.h | 3 +-- source/blender/blenkernel/BKE_sketch.h | 6 ++--- source/blender/blenkernel/intern/implicit.c | 3 +-- source/blender/blenkernel/intern/particle_system.c | 10 ++++---- source/blender/blenkernel/intern/seqcache.c | 3 +-- source/blender/bmesh/intern/bmesh_marking.h | 5 ++-- .../editors/armature/editarmature_retarget.c | 9 +++----- source/blender/editors/include/ED_transform.h | 3 +-- source/blender/editors/space_file/filelist.c | 6 ++--- source/blender/editors/space_file/filelist.h | 3 +-- source/blender/editors/space_node/node_intern.h | 3 +-- .../editors/transform/transform_conversions.c | 2 +- source/blender/editors/transform/transform_ops.c | 3 +-- .../blender/gpu/shaders/gpu_shader_material.glsl | 4 ++-- .../blender/imbuf/intern/openexr/openexr_api.cpp | 3 +-- source/blender/makesdna/DNA_actuator_types.h | 3 +-- source/blender/makesdna/DNA_cloth_types.h | 6 ++--- source/blender/makesdna/DNA_listBase.h | 9 +++----- source/blender/makesdna/DNA_particle_types.h | 4 ++-- .../blender/render/extern/include/RE_shader_ext.h | 6 ++--- .../blender/render/intern/include/render_types.h | 24 +++++++------------ source/blender/render/intern/include/rendercore.h | 6 ++--- source/blender/render/intern/include/sunsky.h | 3 +-- source/blender/render/intern/include/voxeldata.h | 3 +-- source/blender/render/intern/include/zbuf.h | 3 +-- .../render/intern/raytrace/rayobject_instance.cpp | 3 +-- .../blender/render/intern/source/convertblender.c | 6 ++--- source/blender/render/intern/source/pointdensity.c | 3 +-- source/blender/windowmanager/WM_types.h | 2 +- source/blender/windowmanager/intern/wm_window.c | 11 ++++----- source/gameengine/Converter/BL_ArmatureObject.cpp | 2 +- .../Converter/BL_BlenderDataConversion.cpp | 7 +++--- .../Converter/BL_DeformableGameObject.cpp | 2 +- .../Converter/BL_ShapeActionActuator.cpp | 4 ++-- source/gameengine/Expressions/PyObjectPlus.h | 2 +- source/gameengine/Expressions/Value.h | 2 +- .../gameengine/GameLogic/Joystick/SCA_Joystick.h | 14 +++++------ source/gameengine/GameLogic/SCA_JoystickSensor.cpp | 12 ++++++---- source/gameengine/GameLogic/SCA_JoystickSensor.h | 2 +- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 3 +-- .../gameengine/Ketsji/KX_BulletPhysicsController.h | 2 +- source/gameengine/Ketsji/KX_Dome.cpp | 19 +++++++++------ source/gameengine/Ketsji/KX_GameObject.h | 2 +- source/gameengine/Ketsji/KX_IpoActuator.cpp | 2 +- source/gameengine/Ketsji/KX_KetsjiEngine.h | 3 +-- source/gameengine/Ketsji/KX_LightIpoSGController.h | 2 +- .../gameengine/Ketsji/KX_MaterialIpoController.h | 2 +- .../gameengine/Ketsji/KX_ObColorIpoSGController.h | 2 +- source/gameengine/Ketsji/KX_SoundActuator.h | 3 +-- source/gameengine/Ketsji/KX_WorldIpoController.h | 2 +- source/gameengine/Rasterizer/RAS_LightObject.h | 2 +- source/gameengine/SceneGraph/SG_ParentRelation.h | 3 +-- 59 files changed, 130 insertions(+), 189 deletions(-) diff --git a/intern/container/CTR_UHeap.h b/intern/container/CTR_UHeap.h index ad3d7d2bb02..8711d4375cb 100644 --- a/intern/container/CTR_UHeap.h +++ b/intern/container/CTR_UHeap.h @@ -56,7 +56,7 @@ class CTR_UHeapable { public : int & HeapPos( - ){ + ) { return m_ind; }; float & @@ -93,7 +93,7 @@ protected : }; ~CTR_UHeapable( - ){ + ) { }; }; @@ -214,7 +214,7 @@ private: HeapType *base, int i, int j - ){ + ) { std::swap(m_vector[i],m_vector[j]); CTR_UHeapable *heap_i = base + m_vector[i]; diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp index e8c81e57654..ad7f3347cee 100644 --- a/intern/cycles/util/util_system.cpp +++ b/intern/cycles/util/util_system.cpp @@ -152,7 +152,7 @@ bool system_cpu_support_optimized() /*__cpuid(result, 0x80000000); num_ex = result[0];*/ - if(num >= 1){ + if(num >= 1) { __cpuid(result, 0x00000001); caps.mmx = (result[3] & ((int)1 << 23)) != 0; caps.sse = (result[3] & ((int)1 << 25)) != 0; @@ -167,7 +167,7 @@ bool system_cpu_support_optimized() caps.fma3 = (result[2] & ((int)1 << 12)) != 0; } - /*if(num_ex >= 0x80000001){ + /*if(num_ex >= 0x80000001) { __cpuid(result, 0x80000001); caps.x64 = (result[3] & ((int)1 << 29)) != 0; caps.sse4a = (result[2] & ((int)1 << 6)) != 0; diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 7614cb80e00..8454f338645 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -56,8 +56,7 @@ typedef unsigned long long GHOST_TUns64; typedef void *GHOST_TUserDataPtr; -typedef enum -{ +typedef enum { GHOST_kFailure = 0, GHOST_kSuccess } GHOST_TSuccess; diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index cba4c406759..0a3141d6782 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -40,8 +40,7 @@ #define INTERNAL_RND_SORT_SEED 39871946 // internal structure -typedef struct -{ +typedef struct { float x, y, z; } SVec3; @@ -119,14 +118,12 @@ static tbool VNotZero(const SVec3 v) -typedef struct -{ +typedef struct { int iNrFaces; int * pTriMembers; } SSubGroup; -typedef struct -{ +typedef struct { int iNrFaces; int * pFaceIndices; int iVertexRepresentitive; @@ -141,8 +138,7 @@ typedef struct -typedef struct -{ +typedef struct { int FaceNeighbors[3]; SGroup * AssignedGroup[3]; @@ -156,8 +152,7 @@ typedef struct unsigned char vert_num[4]; } STriInfo; -typedef struct -{ +typedef struct { SVec3 vOs; float fMagS; SVec3 vOt; @@ -426,8 +421,7 @@ tbool genTangSpace(const SMikkTSpaceContext * pContext, const float fAngularThre /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -typedef struct -{ +typedef struct { float vert[3]; int index; } STmpVert; @@ -911,8 +905,7 @@ static SVec3 GetTexCoord(const SMikkTSpaceContext * pContext, const int index) ///////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////// -typedef union -{ +typedef union { struct { int i0, i1, f; diff --git a/intern/mikktspace/mikktspace.h b/intern/mikktspace/mikktspace.h index dc2308f6116..52c44a713c6 100644 --- a/intern/mikktspace/mikktspace.h +++ b/intern/mikktspace/mikktspace.h @@ -62,8 +62,7 @@ extern "C" { typedef int tbool; typedef struct SMikkTSpaceContext SMikkTSpaceContext; -typedef struct -{ +typedef struct { // Returns the number of faces (triangles/quads) on the mesh to be processed. int (*m_getNumFaces)(const SMikkTSpaceContext * pContext); diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 3475ef532da..bcda970e60c 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -69,8 +69,7 @@ struct CollisionTree; * own connectivity of the mesh based on the actual edges in the mesh. * */ -typedef struct Cloth -{ +typedef struct Cloth { struct ClothVertex *verts; /* The vertices that represent this cloth. */ struct LinkNode *springs; /* The springs connecting the mesh. */ unsigned int numverts; /* The number of verts == m * n. */ @@ -91,8 +90,7 @@ typedef struct Cloth /** * The definition of a cloth vertex. */ -typedef struct ClothVertex -{ +typedef struct ClothVertex { int flags; /* General flags per vertex. */ float v[3]; /* The velocity of the point. */ float xconst[3]; /* constrained position */ @@ -117,8 +115,7 @@ ClothVertex; /** * The definition of a spring. */ -typedef struct ClothSpring -{ +typedef struct ClothSpring { int ij; /* Pij from the paper, one end of the spring. */ int kl; /* Pkl from the paper, one end of the spring. */ float restlen; /* The original length of the spring. */ @@ -149,8 +146,7 @@ ClothSpring; /* SIMULATION FLAGS: goal flags,.. */ /* These are the bits used in SimSettings.flags. */ -typedef enum -{ +typedef enum { CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),// object is only collision object, no cloth simulation is done CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled @@ -160,15 +156,13 @@ typedef enum } CLOTH_SIMSETTINGS_FLAGS; /* COLLISION FLAGS */ -typedef enum -{ +typedef enum { CLOTH_COLLSETTINGS_FLAG_ENABLED = ( 1 << 1 ), /* enables cloth - object collisions */ CLOTH_COLLSETTINGS_FLAG_SELF = ( 1 << 2 ), /* enables selfcollisions */ } CLOTH_COLLISIONSETTINGS_FLAGS; /* Spring types as defined in the paper.*/ -typedef enum -{ +typedef enum { CLOTH_SPRING_TYPE_STRUCTURAL = (1 << 1), CLOTH_SPRING_TYPE_SHEAR = (1 << 2), CLOTH_SPRING_TYPE_BENDING = (1 << 3), @@ -176,8 +170,7 @@ typedef enum } CLOTH_SPRING_TYPES; /* SPRING FLAGS */ -typedef enum -{ +typedef enum { CLOTH_SPRING_FLAG_DEACTIVATE = ( 1 << 1 ), CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied } CLOTH_SPRINGS_FLAGS; @@ -230,16 +223,14 @@ int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsig /* This enum provides the IDs for our solvers. */ // only one available in the moment -typedef enum -{ +typedef enum { CM_IMPLICIT = 0, } CM_SOLVER_ID; /* This structure defines how to call the solver. */ -typedef struct -{ +typedef struct { const char *name; CM_SOLVER_ID id; int ( *init ) (struct Object *ob, struct ClothModifierData *clmd ); diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 191056571c0..ec257a2f394 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -59,8 +59,7 @@ struct LinkNode; //////////////////////////////////////// /* COLLISION FLAGS */ -typedef enum -{ +typedef enum { COLLISION_IN_FUTURE = (1 << 1), #ifdef WITH_ELTOPO COLLISION_USE_COLLFACE = (1 << 2), diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b9d0076c7c8..5fbd58e26a5 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -266,8 +266,7 @@ struct bNodeTreeExec; typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree); typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name); -typedef struct bNodeTreeType -{ +typedef struct bNodeTreeType { int type; /* type identifier */ char idname[64]; /* id name for RNA identification */ diff --git a/source/blender/blenkernel/BKE_sketch.h b/source/blender/blenkernel/BKE_sketch.h index 50ee1184b3e..ed7ce05506d 100644 --- a/source/blender/blenkernel/BKE_sketch.h +++ b/source/blender/blenkernel/BKE_sketch.h @@ -26,14 +26,12 @@ * \ingroup bke */ -typedef enum SK_PType -{ +typedef enum SK_PType { PT_CONTINUOUS, PT_EXACT, } SK_PType; -typedef enum SK_PMode -{ +typedef enum SK_PMode { PT_SNAP, PT_PROJECT, } SK_PMode; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index d4861a27057..4aef47159df 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -695,8 +695,7 @@ DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, flo /////////////////////////////////////////////////////////////////// // simulator start /////////////////////////////////////////////////////////////////// -typedef struct Implicit_Data -{ +typedef struct Implicit_Data { lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z; fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI, *M; } Implicit_Data; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f19dfe74a36..6c7336958b5 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2363,13 +2363,12 @@ static EdgeHash *sph_springhash_build(ParticleSystem *psys) } #define SPH_NEIGHBORS 512 -typedef struct SPHNeighbor -{ +typedef struct SPHNeighbor { ParticleSystem *psys; int index; } SPHNeighbor; -typedef struct SPHRangeData -{ + +typedef struct SPHRangeData { SPHNeighbor neighbors[SPH_NEIGHBORS]; int tot_neighbors; @@ -2641,8 +2640,7 @@ static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float d /************************************************/ /* Basic physics */ /************************************************/ -typedef struct EfData -{ +typedef struct EfData { ParticleTexture ptex; ParticleSimulationData *sim; ParticleData *pa; diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index f1f3dd47d8b..ea4699f8495 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -38,8 +38,7 @@ #include "IMB_moviecache.h" -typedef struct seqCacheKey -{ +typedef struct seqCacheKey { struct Sequence * seq; SeqRenderData context; float cfra; diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 12ebaedac60..406971652dc 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -27,8 +27,7 @@ * \ingroup bmesh */ -typedef struct BMEditSelection -{ +typedef struct BMEditSelection { struct BMEditSelection *next, *prev; BMElem *ele; char htype; @@ -82,7 +81,7 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]); #define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head) #define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head) -int _bm_select_history_check(BMesh *bm, const BMHeader *ele); +int _bm_select_history_check(BMesh *bm, const BMHeader *ele); int _bm_select_history_remove(BMesh *bm, BMHeader *ele); void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele); void _bm_select_history_store(BMesh *bm, BMHeader *ele); diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index d90bd96a6f1..91c342ec070 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -81,20 +81,17 @@ typedef struct RetargetParam { bContext *context; } RetargetParam; -typedef enum -{ +typedef enum { RETARGET_LENGTH, RETARGET_AGGRESSIVE } RetargetMode; -typedef enum -{ +typedef enum { METHOD_BRUTE_FORCE = 0, METHOD_MEMOIZE = 1 } RetargetMethod; -typedef enum -{ +typedef enum { ARC_FREE = 0, ARC_TAKEN = 1, ARC_USED = 2 diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index c4d7197bfa1..42036d1ea17 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -168,8 +168,7 @@ typedef struct DepthPeel { struct ListBase; -typedef enum SnapMode -{ +typedef enum SnapMode { SNAP_ALL = 0, SNAP_NOT_SELECTED = 1, SNAP_NOT_OBEDIT = 2 diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index d84214413da..a535e888156 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -102,8 +102,7 @@ typedef struct ThumbnailJob { ReportList reports; } ThumbnailJob; -typedef struct FileList -{ +typedef struct FileList { struct direntry *filelist; int *fidx; int numfiles; @@ -124,8 +123,7 @@ typedef struct FileList } FileList; -typedef struct FolderList -{ +typedef struct FolderList { struct FolderList *next, *prev; char *foldername; } FolderList; diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index fac6a387b9f..7a37c5fb3c5 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -53,8 +53,7 @@ typedef enum FileSelType { FILE_SEL_TOGGLE = 2 } FileSelType; -typedef enum FileCheckType -{ +typedef enum FileCheckType { CHECK_DIRS = 1, CHECK_FILES = 2, CHECK_ALL = 3 diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 35b1583b24e..9e873799f1c 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -50,8 +50,7 @@ struct bNodeLink; struct Main; /* temp data to pass on to modal */ -typedef struct bNodeLinkDrag -{ +typedef struct bNodeLinkDrag { struct bNodeLinkDrag *next, *prev; /* List of links dragged by the operator. diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0391afdc188..61dff466387 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5847,7 +5847,7 @@ void flushTransTracking(TransInfo *t) /* * masking * */ -typedef struct TransDataMasking{ +typedef struct TransDataMasking { int is_handle; float handle[2], orig_handle[2]; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 9d2a104d8e9..e4c85309081 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -51,8 +51,7 @@ #include "transform.h" -typedef struct TransformModeItem -{ +typedef struct TransformModeItem { char *idname; int mode; void (*opfunc)(wmOperatorType*); diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index b9bd7e961f8..fb248f1b016 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1261,8 +1261,8 @@ void mtex_bump_bicubic( vec3 texco, sampler2D ima, float hScale, mat4 H; - for(int i = 0; i < 4; i++){ - for(int j = 0; j < 4; j++){ + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 4; j++) { ivec2 iTexTmp = iTexLocMod + ivec2(i,j); // wrap texture coordinates manually for texelFetch to work on uvs oitside the 0,1 range. diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 93a5f8eca7c..baea18d4898 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -904,8 +904,7 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height) /* ********************************************************* */ -typedef struct RGBA -{ +typedef struct RGBA { float r; float g; float b; diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index f4e06455c63..4a5ad69cb91 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -62,8 +62,7 @@ typedef struct bActionActuator { float layer_weight; /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */ } bActionActuator; -typedef struct Sound3D -{ +typedef struct Sound3D { float min_gain; float max_gain; float reference_distance; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index b214186fee6..4928a88b33e 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -44,8 +44,7 @@ * variables with different names to minimize confusion. */ -typedef struct ClothSimSettings -{ +typedef struct ClothSimSettings { struct LinkNode *cache; /* UNUSED atm */ float mingoal; /* see SB */ float Cdis; /* Mechanical damping of springs. */ @@ -89,8 +88,7 @@ typedef struct ClothSimSettings } ClothSimSettings; -typedef struct ClothCollSettings -{ +typedef struct ClothCollSettings { struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ float epsilon; /* min distance for collisions. */ float self_friction; /* Fiction/damping with self contact. */ diff --git a/source/blender/makesdna/DNA_listBase.h b/source/blender/makesdna/DNA_listBase.h index 35549aee3d2..333e414278d 100644 --- a/source/blender/makesdna/DNA_listBase.h +++ b/source/blender/makesdna/DNA_listBase.h @@ -41,22 +41,19 @@ extern "C" { #endif /* generic - all structs which are used in linked-lists used this */ -typedef struct Link -{ +typedef struct Link { struct Link *next, *prev; } Link; /* use this when it is not worth defining a custom one... */ -typedef struct LinkData -{ +typedef struct LinkData { struct LinkData *next, *prev; void *data; } LinkData; /* never change the size of this! genfile.c detects pointerlen with it */ -typedef struct ListBase -{ +typedef struct ListBase { void *first, *last; } ListBase; diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index f5d525d47b5..0853df87a35 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -234,8 +234,8 @@ typedef struct ParticleSettings { struct PartDeflect *pd2; } ParticleSettings; -typedef struct ParticleSystem -{ /* note1: make sure all (runtime) are NULL's in 'copy_particlesystem' XXX, this function is no more! - need to invstigate */ +typedef struct ParticleSystem { + /* note1: make sure all (runtime) are NULL's in 'copy_particlesystem' XXX, this function is no more! - need to invstigate */ /* note2: make sure any uses of this struct in DNA are accounted for in 'BKE_object_copy_particlesystems' */ struct ParticleSystem *next, *prev; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index cf9e6f7966f..26a1b9908b3 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -45,8 +45,7 @@ typedef struct TexResult { } TexResult; /* localized shade result data */ -typedef struct ShadeResult -{ +typedef struct ShadeResult { float combined[4]; float col[4]; float alpha, mist, z; @@ -95,8 +94,7 @@ typedef struct ShadeInputCol { } ShadeInputCol; /* localized renderloop data */ -typedef struct ShadeInput -{ +typedef struct ShadeInput { /* copy from face, also to extract tria from quad */ /* note it mirrors a struct above for quick copy */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index f84b00451a6..e5af51cf2d7 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -65,16 +65,14 @@ struct Main; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 -typedef struct SampleTables -{ +typedef struct SampleTables { float centLut[16]; float *fmask1[9], *fmask2[9]; char cmask[256], *centmask; } SampleTables; -typedef struct QMCSampler -{ +typedef struct QMCSampler { struct QMCSampler *next, *prev; int type; int tot; @@ -88,8 +86,7 @@ typedef struct QMCSampler #define SAMP_TYPE_HAMMERSLEY 2 /* this is handed over to threaded hiding/passes/shading engine */ -typedef struct RenderPart -{ +typedef struct RenderPart { struct RenderPart *next, *prev; RenderResult *result; /* result of part rendering */ @@ -347,8 +344,7 @@ typedef struct ObjectInstanceRen { /* ------------------------------------------------------------------------- */ -typedef struct VertRen -{ +typedef struct VertRen { float co[3]; float n[3]; float *orco; @@ -384,8 +380,7 @@ typedef struct VlakRen { int index; } VlakRen; -typedef struct HaloRen -{ +typedef struct HaloRen { short miny, maxy; float alfa, xs, ys, rad, radsq, sin, cos, co[3], no[3]; float hard, b, g, r; @@ -456,8 +451,7 @@ typedef struct StrandRen { /* ------------------------------------------------------------------------- */ -typedef struct VolumeOb -{ +typedef struct VolumeOb { struct VolumeOb *next, *prev; struct Material *ma; struct ObjectRen *obr; @@ -469,8 +463,7 @@ typedef struct MatInside { struct ObjectInstanceRen *obi; } MatInside; -typedef struct VolPrecachePart -{ +typedef struct VolPrecachePart { struct VolPrecachePart *next, *prev; struct RayObject *tree; struct ShadeInput *shi; @@ -486,8 +479,7 @@ typedef struct VolPrecachePart struct Render *re; } VolPrecachePart; -typedef struct VolumePrecache -{ +typedef struct VolumePrecache { int res[3]; float *bbmin, *bbmax; float *data_r; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 284b386ca33..0fbbf52e613 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -46,16 +46,14 @@ struct RayObject; /* ------------------------------------------------------------------------- */ -typedef struct PixStr -{ +typedef struct PixStr { struct PixStr *next; int obi, facenr, z, maskz; unsigned short mask; short shadfac; } PixStr; -typedef struct PixStrMain -{ +typedef struct PixStrMain { struct PixStrMain *next, *prev; struct PixStr *ps; int counter; diff --git a/source/blender/render/intern/include/sunsky.h b/source/blender/render/intern/include/sunsky.h index 0afd9246150..4bb7d99ba16 100644 --- a/source/blender/render/intern/include/sunsky.h +++ b/source/blender/render/intern/include/sunsky.h @@ -31,8 +31,7 @@ #define SPECTRUM_START 350.0 #define SPECTRUM_END 800.0 -typedef struct SunSky -{ +typedef struct SunSky { short effect_type, skyblendtype, sky_colorspace; float turbidity; float theta, phi; diff --git a/source/blender/render/intern/include/voxeldata.h b/source/blender/render/intern/include/voxeldata.h index 63620331c85..dd2262e0357 100644 --- a/source/blender/render/intern/include/voxeldata.h +++ b/source/blender/render/intern/include/voxeldata.h @@ -35,8 +35,7 @@ struct Render; struct TexResult; -typedef struct VoxelDataHeader -{ +typedef struct VoxelDataHeader { int resolX, resolY, resolZ; int frames; } VoxelDataHeader; diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index 77cee59a83a..cdf171443d7 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -80,8 +80,7 @@ typedef struct APixstrand { struct APixstrand *next; } APixstrand; -typedef struct APixstrMain -{ +typedef struct APixstrMain { struct APixstrMain *next, *prev; void *ps; } APixstrMain; diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp index ce88bac1587..92a412103ba 100644 --- a/source/blender/render/intern/raytrace/rayobject_instance.cpp +++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp @@ -62,8 +62,7 @@ static RayObjectAPI instance_api = RE_rayobject_instance_hint_bb }; -typedef struct InstanceRayObject -{ +typedef struct InstanceRayObject { RayObject rayobj; RayObject *target; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index a2b911911d0..a48a6b75049 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -520,8 +520,7 @@ static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemAr ************ tangent space generation interface **************** ****************************************************************/ -typedef struct -{ +typedef struct { ObjectRen *obr; } SRenderMeshToTangent; @@ -1011,8 +1010,7 @@ static Material *give_render_material(Render *re, Object *ob, short nr) /* ------------------------------------------------------------------------- */ /* Particles */ /* ------------------------------------------------------------------------- */ -typedef struct ParticleStrandData -{ +typedef struct ParticleStrandData { struct MCol *mcol; float *orco, *uvco, *surfnor; float time, adapt_angle, adapt_pix, size; diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 96a1a13b75f..3c1a18316ca 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -325,8 +325,7 @@ void free_pointdensities(Render *re) } } -typedef struct PointDensityRangeData -{ +typedef struct PointDensityRangeData { float *density; float squared_radius; float *point_data; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 25abc171057..a15d020c230 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -385,7 +385,7 @@ typedef struct wmTabletData { float Ytilt; /* as above */ } wmTabletData; -typedef enum { // motion progress, for modal handlers +typedef enum { /* motion progress, for modal handlers */ P_NOT_STARTED, P_STARTING, // <-- P_IN_PROGRESS, // <-- only these are sent for NDOF motion diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 7361e74755e..265a3c11377 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -577,12 +577,11 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* ************ events *************** */ -typedef enum -{ - SHIFT = 's', - CONTROL = 'c', - ALT = 'a', - OS = 'C' +typedef enum { + SHIFT = 's', + CONTROL = 'c', + ALT = 'a', + OS = 'C' } modifierKeyType; /* check if specified modifier key type is pressed */ diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index f38782a9405..7174a563efa 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -529,7 +529,7 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, return true; } - else{ + else { act->SetBlendTime(0.0); return false; } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 3d73ca66c92..927a0535870 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -488,11 +488,10 @@ static void GetRGB(short type, } } -typedef struct MTF_localLayer -{ +typedef struct MTF_localLayer { MTFace *face; const char *name; -}MTF_localLayer; +} MTF_localLayer; // ------------------------------------ bool ConvertMaterial( @@ -1193,7 +1192,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); } - else{ + else { visible = true; twoside = false; collider = true; diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index dd4c51b5403..4967401f279 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -76,7 +76,7 @@ bool BL_DeformableGameObject::SetActiveAction(BL_ShapeActionActuator *act, short return true; } - else{ + else { act->SetBlendTime(0.0f); return false; } diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 13e79b13304..c339e10f673 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -316,7 +316,7 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) m_localtime += (length/m_stridelength) * deltapos.length(); m_lastpos = newpos; } - else{ + else { SetLocalTime(curtime); } } @@ -466,7 +466,7 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) BLI_freelistN(&tchanbase); } } - else{ + else { m_blendframe = 0.0f; } } diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 278febee4ac..c50e42446a5 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -527,7 +527,7 @@ typedef struct KX_PYATTRIBUTE_DEF { /*------------------------------ * PyObjectPlus ------------------------------*/ -typedef PyTypeObject * PyParentObject; // Define the PyParent Object +typedef PyTypeObject *PyParentObject; /* Define the PyParent Object */ #else // WITH_PYTHON diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 00320ff9ed2..261f5244f21 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -158,7 +158,7 @@ class CAction public: CAction() { }; - virtual ~CAction(){ + virtual ~CAction() { }; virtual void Execute() const =0; diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h index a6809716e32..685cc3fcc48 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h @@ -99,7 +99,7 @@ class SCA_Joystick void OnButtonDown(SDL_Event *sdl_event); void OnNothing(SDL_Event *sdl_event); #if 0 /* not used yet */ - void OnBallMotion(SDL_Event *sdl_event){} + void OnBallMotion(SDL_Event *sdl_event) {} #endif #endif /* WITH_SDL */ @@ -156,27 +156,27 @@ public: void cSetPrecision(int val); - int GetAxisPosition(int index){ + int GetAxisPosition(int index) { return m_axis_array[index]; } - int GetHat(int index){ + int GetHat(int index) { return m_hat_array[index]; } - int GetThreshold(void){ + int GetThreshold(void) { return m_prec; } - bool IsTrigAxis(void){ + bool IsTrigAxis(void) { return m_istrig_axis; } - bool IsTrigButton(void){ + bool IsTrigButton(void) { return m_istrig_button; } - bool IsTrigHat(void){ + bool IsTrigHat(void) { return m_istrig_hat; } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 07fad3bfe37..c82e015919d 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -137,7 +137,8 @@ bool SCA_JoystickSensor::Evaluate() if (js->aAxisPairIsPositive(m_axis-1)) { /* use zero based axis index internally */ m_istrig = 1; result = true; - }else{ + } + else { if (m_istrig) { m_istrig = 0; result = true; @@ -148,7 +149,8 @@ bool SCA_JoystickSensor::Evaluate() if (js->aAxisPairDirectionIsPositive(m_axis-1, m_axisf)) { /* use zero based axis index internally */ m_istrig = 1; result = true; - }else{ + } + else { if (m_istrig) { m_istrig = 0; result = true; @@ -168,7 +170,8 @@ bool SCA_JoystickSensor::Evaluate() if (js->aAxisIsPositive(m_axis-1)) { /* use zero based axis index internally */ m_istrig = 1; result = true; - }else{ + } + else { if (m_istrig) { m_istrig = 0; result = true; @@ -209,7 +212,8 @@ bool SCA_JoystickSensor::Evaluate() if ((m_bAllEvents && js->GetHat(m_hat-1)) || js->aHatIsPositive(m_hat-1, m_hatf)) { m_istrig = 1; result = true; - }else{ + } + else { if (m_istrig) { m_istrig = 0; result = true; diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index eecbf2c4183..5dc35faf244 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -117,7 +117,7 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); - short int GetJoyIndex(void){ + short int GetJoyIndex(void) { return m_joyindex; } diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 1e16cbd51f2..26cfc560b6d 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -118,8 +118,7 @@ static void mem_error_cb(const char *errorStr) } #ifdef WIN32 -typedef enum -{ +typedef enum { SCREEN_SAVER_MODE_NONE = 0, SCREEN_SAVER_MODE_PREVIEW, SCREEN_SAVER_MODE_SAVER, diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 4ced21aa2d8..3b3a1f5cbfb 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -86,7 +86,7 @@ public: SetOption( int option, int value - ){ + ) { // intentionally empty }; diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index eaabbdd8233..6d57b6950f1 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -445,7 +445,8 @@ void KX_Dome::GLDrawWarpQuads(void) } } glEnd(); - } else{ + } + else { printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n", warp.mode); } } @@ -502,7 +503,8 @@ bool KX_Dome::ParseWarpMesh(STR_String text) if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)) { printf("Dome Error: Warp Mesh File with insufficient data!\n"); return false; - }else{ + } + else { warp.nodes = vector > (warp.n_height, vector(warp.n_width)); for (i=2; i-2 < (warp.n_width*warp.n_height); i++) { @@ -520,7 +522,7 @@ bool KX_Dome::ParseWarpMesh(STR_String text) warp.nodes[nodeY][nodeX].v = atof(columns[3]); warp.nodes[nodeY][nodeX].i = atof(columns[4]); } - else{ + else { warp.nodes.clear(); printf("Dome Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n"); return false; @@ -1671,7 +1673,8 @@ void KX_Dome::DrawEnvMap(void) if (can_width/3 <= can_height/2) { ortho_width = 1.0; ortho_height = (float)can_height/can_width; - }else{ + } + else { ortho_height = 2.0f / 3; ortho_width = (float)can_width/can_height * ortho_height; } @@ -1801,7 +1804,8 @@ void KX_Dome::DrawDomeFisheye(void) if (can_width < can_height) { ortho_width = 1.0; ortho_height = (float)can_height/can_width; - }else{ + } + else { ortho_width = (float)can_width/can_height; ortho_height = 1.0; } @@ -1897,7 +1901,8 @@ void KX_Dome::DrawPanorama(void) if ((can_width / 2) <= (can_height)) { ortho_width = 1.0; ortho_height = (float)can_height/can_width; - }else{ + } + else { ortho_width = (float)can_width/can_height * 0.5; ortho_height = 0.5; } @@ -1995,7 +2000,7 @@ void KX_Dome::DrawDomeWarped(void) glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); glCallList(dlistId + m_numfaces); } - else{ + else { glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); GLDrawWarpQuads(); } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index a173ef1ed8f..2b0d13ff2f7 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -712,7 +712,7 @@ public: void AddMesh( RAS_MeshObject* mesh - ){ + ) { m_meshes.push_back(mesh); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 9777eaf333e..7e7e7f8cef2 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -297,7 +297,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) { SetLocalTime(curtime); } - else{ + else { if (!m_bNegativeEvent) { /* Perform wraparound */ SetLocalTime(curtime); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 0a50ab0a43a..f9c6d59b668 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -150,8 +150,7 @@ private: int m_curreye; /** Categories for profiling display. */ - typedef enum - { + typedef enum { tc_first = 0, tc_physics = 0, tc_logic, diff --git a/source/gameengine/Ketsji/KX_LightIpoSGController.h b/source/gameengine/Ketsji/KX_LightIpoSGController.h index 78466e822e7..15591bfa981 100644 --- a/source/gameengine/Ketsji/KX_LightIpoSGController.h +++ b/source/gameengine/Ketsji/KX_LightIpoSGController.h @@ -90,7 +90,7 @@ public: SetOption( int option, int value - ){ + ) { // intentionally empty }; diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.h b/source/gameengine/Ketsji/KX_MaterialIpoController.h index 85b2a971fbe..11d92925a02 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.h +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.h @@ -49,7 +49,7 @@ public: SetOption( int option, int value - ){ + ) { // intentionally empty }; diff --git a/source/gameengine/Ketsji/KX_ObColorIpoSGController.h b/source/gameengine/Ketsji/KX_ObColorIpoSGController.h index d2d69d6db12..d2f4c69bf47 100644 --- a/source/gameengine/Ketsji/KX_ObColorIpoSGController.h +++ b/source/gameengine/Ketsji/KX_ObColorIpoSGController.h @@ -64,7 +64,7 @@ public: SetOption( int option, int value - ){ + ) { // intentionally empty }; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 71ec3ae2f59..dbdb17d0da5 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -43,8 +43,7 @@ #include "BKE_sound.h" -typedef struct KX_3DSoundSettings -{ +typedef struct KX_3DSoundSettings { float min_gain; float max_gain; float reference_distance; diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h index 1f60280e355..9578130b51e 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.h +++ b/source/gameengine/Ketsji/KX_WorldIpoController.h @@ -88,7 +88,7 @@ public: SetOption( int option, int value - ){ + ) { // intentionally empty }; diff --git a/source/gameengine/Rasterizer/RAS_LightObject.h b/source/gameengine/Rasterizer/RAS_LightObject.h index c378a9ea0c2..ddf360683cd 100644 --- a/source/gameengine/Rasterizer/RAS_LightObject.h +++ b/source/gameengine/Rasterizer/RAS_LightObject.h @@ -36,7 +36,7 @@ struct RAS_LightObject { - enum LightType{ + enum LightType { LIGHT_SPOT, LIGHT_SUN, LIGHT_NORMAL diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h index 689ada84edd..4140563828f 100644 --- a/source/gameengine/SceneGraph/SG_ParentRelation.h +++ b/source/gameengine/SceneGraph/SG_ParentRelation.h @@ -76,8 +76,7 @@ public : virtual ~SG_ParentRelation( - ){ - }; + ) {}; /** * You must provide a way of duplicating an -- cgit v1.2.3 From 46945d805f21ea0c338317050e35296d0b1afdd4 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 6 Jun 2012 23:01:42 +0000 Subject: Revert my own commit r47544, this does not seem to be the correct fix. :/ --- intern/cycles/kernel/osl/osl_services.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 2d285b45d4a..12f3a377ef4 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -31,7 +31,6 @@ #include "kernel_compat_cpu.h" #include "kernel_globals.h" #include "kernel_object.h" -#include "kernel_passes.h" #include "kernel_triangle.h" CCL_NAMESPACE_BEGIN -- cgit v1.2.3 From 5ebc88266e71249e664e994e081627c926faf89e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 6 Jun 2012 23:27:38 +0000 Subject: Cycles: small code fix for disabled code. --- intern/cycles/kernel/kernel_light.h | 4 ++++ intern/cycles/kernel/kernel_path.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index a056cd71bb1..2bc5a882ce5 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -391,6 +391,10 @@ __device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, fl __device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls, float *pdf) { regular_light_sample(kg, index, randu, randv, P, ls, pdf); + + /* compute incoming direction and distance */ + if(ls->t != FLT_MAX) + ls->D = normalize_len(ls->P - P, &ls->t); } __device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index e0e17ee57dc..e41a5a62c14 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -365,7 +365,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R #ifdef __MULTI_LIGHT__ /* index -1 means randomly sample from distribution */ - int i = (kernel_data.integrator.num_distribution)? -1: 0; + int i = (kernel_data.integrator.num_all_lights)? 0: -1; for(; i < kernel_data.integrator.num_all_lights; i++) { #else -- cgit v1.2.3 From 78cf502c8025dc79523038bd6ff10e06781e5a0c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 6 Jun 2012 23:27:43 +0000 Subject: Cycles: border render now works in the viewport, when looking through the camera, same as in render. It draws objects in solid draw mode outside of the border. --- intern/cycles/blender/blender_camera.cpp | 239 ++++++++++++++++------ intern/cycles/blender/blender_session.cpp | 10 +- intern/cycles/blender/blender_sync.h | 2 +- intern/cycles/render/buffers.cpp | 8 +- intern/cycles/render/camera.cpp | 9 + intern/cycles/render/camera.h | 3 + intern/cycles/render/session.cpp | 1 + source/blender/editors/space_view3d/view3d_draw.c | 55 ++++- 8 files changed, 245 insertions(+), 82 deletions(-) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index bdd02bb5086..9bc82344fcc 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -56,6 +56,11 @@ struct BlenderCamera { float sensor_width; float sensor_height; + float border_left; + float border_right; + float border_bottom; + float border_top; + Transform matrix; }; @@ -70,6 +75,8 @@ static void blender_camera_init(BlenderCamera *bcam) bcam->sensor_height = 18.0f; bcam->sensor_fit = BlenderCamera::AUTO; bcam->shuttertime = 1.0f; + bcam->border_right = 1.0f; + bcam->border_top = 1.0f; } static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) @@ -188,85 +195,94 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type) return transform_clear_scale(result); } -static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height) +static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, + float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size) { - /* copy camera to compare later */ - Camera prevcam = *cam; - /* dimensions */ float xratio = width*bcam->pixelaspect.x; float yratio = height*bcam->pixelaspect.y; /* compute x/y aspect and ratio */ - float aspectratio, xaspect, yaspect; + float xaspect, yaspect; /* sensor fitting */ bool horizontal_fit; - float sensor_size; - - cam->sensorwidth = bcam->sensor_width; - cam->sensorheight = bcam->sensor_height; if(bcam->sensor_fit == BlenderCamera::AUTO) { horizontal_fit = (xratio > yratio); - sensor_size = bcam->sensor_width; + *sensor_size = bcam->sensor_width; } else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) { horizontal_fit = true; - sensor_size = bcam->sensor_width; + *sensor_size = bcam->sensor_width; } else { horizontal_fit = false; - sensor_size = bcam->sensor_height; + *sensor_size = bcam->sensor_height; } if(horizontal_fit) { - aspectratio= xratio/yratio; - xaspect= aspectratio; + *aspectratio= xratio/yratio; + xaspect= *aspectratio; yaspect= 1.0f; } else { - aspectratio= yratio/xratio; + *aspectratio= yratio/xratio; xaspect= 1.0f; - yaspect= aspectratio; + yaspect= *aspectratio; } /* modify aspect for orthographic scale */ if(bcam->type == CAMERA_ORTHOGRAPHIC) { - xaspect = xaspect*bcam->ortho_scale/(aspectratio*2.0f); - yaspect = yaspect*bcam->ortho_scale/(aspectratio*2.0f); - aspectratio = bcam->ortho_scale/2.0f; + xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f); + yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f); + *aspectratio = bcam->ortho_scale/2.0f; } if(bcam->type == CAMERA_PANORAMA) { /* set viewplane */ - cam->left = 0.0f; - cam->right = 1.0f; - cam->bottom = 0.0f; - cam->top = 1.0f; + *left = 0.0f; + *right = 1.0f; + *bottom = 0.0f; + *top = 1.0f; } else { /* set viewplane */ - cam->left = -xaspect; - cam->right = xaspect; - cam->bottom = -yaspect; - cam->top = yaspect; + *left = -xaspect; + *right = xaspect; + *bottom = -yaspect; + *top = yaspect; /* zoom for 3d camera view */ - cam->left *= bcam->zoom; - cam->right *= bcam->zoom; - cam->bottom *= bcam->zoom; - cam->top *= bcam->zoom; + *left *= bcam->zoom; + *right *= bcam->zoom; + *bottom *= bcam->zoom; + *top *= bcam->zoom; /* modify viewplane with camera shift and 3d camera view offset */ - float dx = 2.0f*(aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); - float dy = 2.0f*(aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); + float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); + float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - cam->left += dx; - cam->right += dx; - cam->bottom += dy; - cam->top += dy; + *left += dx; + *right += dx; + *bottom += dy; + *top += dy; } +} + +static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height) +{ + /* copy camera to compare later */ + Camera prevcam = *cam; + float aspectratio, sensor_size; + + /* viewplane */ + blender_camera_viewplane(bcam, width, height, + &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size); + + /* sensor */ + cam->sensorwidth = bcam->sensor_width; + cam->sensorheight = bcam->sensor_height; /* clipping distances */ cam->nearclip = bcam->nearclip; @@ -294,6 +310,12 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->use_motion = false; cam->shuttertime = bcam->shuttertime; + /* border */ + cam->border_left = bcam->border_left; + cam->border_right = bcam->border_right; + cam->border_bottom = bcam->border_bottom; + cam->border_top = bcam->border_top; + /* set update flag */ if(cam->modified(prevcam)) cam->tag_update(); @@ -313,6 +335,14 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height) bcam.pixelaspect.y = r.pixel_aspect_y(); bcam.shuttertime = r.motion_blur_shutter(); + /* border */ + if(r.use_border()) { + bcam.border_left = r.border_min_x(); + bcam.border_right = r.border_max_x(); + bcam.border_bottom = r.border_min_y(); + bcam.border_top = r.border_max_y(); + } + /* camera object */ BL::Object b_ob = b_scene.camera(); @@ -348,67 +378,142 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) /* Sync 3D View Camera */ -void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) +static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { - BlenderCamera bcam; - blender_camera_init(&bcam); - /* 3d view parameters */ - bcam.nearclip = b_v3d.clip_start(); - bcam.farclip = b_v3d.clip_end(); - bcam.lens = b_v3d.lens(); - bcam.shuttertime = b_scene.render().motion_blur_shutter(); + bcam->nearclip = b_v3d.clip_start(); + bcam->farclip = b_v3d.clip_end(); + bcam->lens = b_v3d.lens(); + bcam->shuttertime = b_scene.render().motion_blur_shutter(); if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) { /* camera view */ BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); if(b_ob) { - blender_camera_from_object(&bcam, b_ob); + blender_camera_from_object(bcam, b_ob); /* magic zoom formula */ - bcam.zoom = (float)b_rv3d.view_camera_zoom(); - bcam.zoom = (1.41421f + bcam.zoom/50.0f); - bcam.zoom *= bcam.zoom; - bcam.zoom = 2.0f/bcam.zoom; + bcam->zoom = (float)b_rv3d.view_camera_zoom(); + bcam->zoom = (1.41421f + bcam->zoom/50.0f); + bcam->zoom *= bcam->zoom; + bcam->zoom = 2.0f/bcam->zoom; /* offset */ - bcam.offset = get_float2(b_rv3d.view_camera_offset()); + bcam->offset = get_float2(b_rv3d.view_camera_offset()); } } else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) { /* orthographic view */ - bcam.farclip *= 0.5; - bcam.nearclip = -bcam.farclip; + bcam->farclip *= 0.5; + bcam->nearclip = -bcam->farclip; - bcam.type = CAMERA_ORTHOGRAPHIC; - bcam.ortho_scale = b_rv3d.view_distance(); + bcam->type = CAMERA_ORTHOGRAPHIC; + bcam->ortho_scale = b_rv3d.view_distance(); } - bcam.zoom *= 2.0f; + bcam->zoom *= 2.0f; /* 3d view transform */ - bcam.matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); + bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); +} + +static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height) +{ + BL::RenderSettings r = b_scene.render(); + + if(!r.use_border()) + return; + + /* camera view? */ + if(!(b_rv3d && b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA)) + return; + + BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); + + if(!b_ob) + return; + + bcam->border_left = r.border_min_x(); + bcam->border_right = r.border_max_x(); + bcam->border_bottom = r.border_min_y(); + bcam->border_top = r.border_max_y(); + + float cam_left, cam_right, cam_bottom, cam_top; + float view_left, view_right, view_bottom, view_top; + float view_aspect, cam_aspect, sensor_size; + + /* get viewport viewplane */ + BlenderCamera view_bcam; + blender_camera_init(&view_bcam); + blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height); + + blender_camera_viewplane(&view_bcam, width, height, + &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size); + + view_left /= view_aspect; + view_right /= view_aspect; + view_bottom /= view_aspect; + view_top /= view_aspect; + + /* get camera viewplane */ + BlenderCamera cam_bcam; + blender_camera_init(&cam_bcam); + blender_camera_from_object(&cam_bcam, b_ob); + + width = (int)(r.resolution_x()*r.resolution_percentage()/100); + height = (int)(r.resolution_y()*r.resolution_percentage()/100); + + blender_camera_viewplane(&cam_bcam, width, height, + &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size); + + cam_left /= cam_aspect; + cam_right /= cam_aspect; + cam_bottom /= cam_aspect; + cam_top /= cam_aspect; + + /* determine viewport subset matching camera border */ + float tmp_left = ((cam_left - view_left) / (view_right - view_left)); + float tmp_right = ((cam_right - view_left) / (view_right - view_left)); + float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom)); + float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom)); + + bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left); + bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left); + bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom); + bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom); + + /* clamp */ + bcam->border_left = max(bcam->border_left, 0.0f); + bcam->border_right = min(bcam->border_right, 1.0f); + bcam->border_bottom = max(bcam->border_bottom, 0.0f); + bcam->border_top = min(bcam->border_top, 1.0f); +} + +void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) +{ + BlenderCamera bcam; + blender_camera_init(&bcam); + blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height); + blender_camera_border(&bcam, b_scene, b_v3d, b_rv3d, width, height); - /* sync */ blender_camera_sync(scene->camera, &bcam, width, height); } -BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::RegionView3D b_rv3d, int width, int height) +BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height) { BufferParams params; params.full_width = width; params.full_height = height; - /* border render */ - BL::RenderSettings r = b_scene.render(); - - if(!b_rv3d && r.use_border()) { - params.full_x = r.border_min_x()*width; - params.full_y = r.border_min_y()*height; - params.width = (int)(r.border_max_x()*width) - params.full_x; - params.height = (int)(r.border_max_y()*height) - params.full_y; + if(b_scene.render().use_border()) { + /* border render */ + params.full_x = cam->border_left*width; + params.full_y = cam->border_bottom*height; + params.width = (int)(cam->border_right*width) - params.full_x; + params.height = (int)(cam->border_top*height) - params.full_y; } else { params.width = width; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 997909f1b92..9726f7b94cf 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -106,7 +106,7 @@ void BlenderSession::create_session() session->set_pause(BlenderSync::get_session_pause(b_scene, background)); /* set buffer parameters */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); session->reset(buffer_params, session_params.samples); } @@ -181,7 +181,7 @@ void BlenderSession::render() { /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); int w = buffer_params.width, h = buffer_params.height; /* create render result */ @@ -326,7 +326,7 @@ void BlenderSession::synchronize() /* reset if needed */ if(scene->need_reset()) { - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); session->reset(buffer_params, session_params.samples); } } @@ -364,7 +364,7 @@ bool BlenderSession::draw(int w, int h) /* reset if requested */ if(reset) { SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, w, h); session->reset(buffer_params, session_params.samples); } @@ -374,7 +374,7 @@ bool BlenderSession::draw(int w, int h) update_status_progress(); /* draw */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); return !session->draw(buffer_params); } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 10afd468850..bc6258d35ac 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -63,7 +63,7 @@ public: static SceneParams get_scene_params(BL::Scene b_scene, bool background); static SessionParams get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background); static bool get_session_pause(BL::Scene b_scene, bool background); - static BufferParams get_buffer_params(BL::Scene b_scene, BL::RegionView3D b_rv3d, int width, int height); + static BufferParams get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height); private: /* sync */ diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index a80851b945a..a7fd47c94cf 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -311,8 +311,14 @@ void DisplayBuffer::draw_set(int width, int height) void DisplayBuffer::draw(Device *device) { - if(draw_width != 0 && draw_height != 0) + if(draw_width != 0 && draw_height != 0) { + glPushMatrix(); + glTranslatef(params.full_x, params.full_y, 0.0f); + device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent); + + glPopMatrix(); + } } bool DisplayBuffer::draw_ready() diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 3ecffab7cbc..ed239074cd4 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -58,6 +58,11 @@ Camera::Camera() bottom = -1.0f; top = 1.0f; + border_left = 0.0f; + border_right = 1.0f; + border_bottom = 0.0f; + border_top = 1.0f; + screentoworld = transform_identity(); rastertoworld = transform_identity(); ndctoworld = transform_identity(); @@ -248,6 +253,10 @@ bool Camera::modified(const Camera& cam) (right == cam.right) && (bottom == cam.bottom) && (top == cam.top) && + (border_left == cam.border_left) && + (border_right == cam.border_right) && + (border_bottom == cam.border_bottom) && + (border_top == cam.border_top) && (matrix == cam.matrix) && (motion == cam.motion) && (use_motion == cam.use_motion) && diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 7a09b5981e4..647423d88ba 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -67,6 +67,9 @@ public: int width, height; float left, right, bottom, top; + /* border */ + float border_left, border_right, border_bottom, border_top; + /* transformation */ Transform matrix; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 34a0c0ff877..173d73ea2c7 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -27,6 +27,7 @@ #include "util_foreach.h" #include "util_function.h" +#include "util_opengl.h" #include "util_task.h" #include "util_time.h" diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 7c12816741d..a36c14151e6 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1146,7 +1146,6 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) /* border */ if (scene->r.mode & R_BORDER) { - cpack(0); x3 = x1 + scene->r.border.xmin * (x2 - x1); y3 = y1 + scene->r.border.ymin * (y2 - y1); @@ -2735,12 +2734,15 @@ static void draw_viewport_fps(Scene *scene, ARegion *ar) BLF_draw_default_ascii(22, ar->winy - 17, 0.0f, printable, sizeof(printable)); } -static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar) +static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit); + +static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw_border) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); RenderEngineType *type; + GLint scissor[4]; /* create render engine */ if (!rv3d->render_engine) { @@ -2757,17 +2759,48 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar) view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL); /* background draw */ + ED_region_pixelspace(ar); + + if (draw_border) { + /* for border draw, we only need to clear a subset of the 3d view */ + rctf viewborder; + rcti cliprct; + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE); + + cliprct.xmin = viewborder.xmin + scene->r.border.xmin * (viewborder.xmax - viewborder.xmin); + cliprct.ymin = viewborder.ymin + scene->r.border.ymin * (viewborder.ymax - viewborder.ymin); + cliprct.xmax = viewborder.xmin + scene->r.border.xmax * (viewborder.xmax - viewborder.xmin); + cliprct.ymax = viewborder.ymin + scene->r.border.ymax * (viewborder.ymax - viewborder.ymin); + + cliprct.xmin += ar->winrct.xmin; + cliprct.xmax += ar->winrct.xmin; + cliprct.ymin += ar->winrct.ymin; + cliprct.ymax += ar->winrct.ymin; + + cliprct.xmin = MAX2(cliprct.xmin, ar->winrct.xmin); + cliprct.ymin = MAX2(cliprct.ymin, ar->winrct.ymin); + cliprct.xmax = MIN2(cliprct.xmax, ar->winrct.xmax); + cliprct.ymax = MIN2(cliprct.ymax, ar->winrct.ymax); + + glGetIntegerv(GL_SCISSOR_BOX, scissor); + glScissor(cliprct.xmin, cliprct.ymin, cliprct.xmax - cliprct.xmin, cliprct.ymax - cliprct.ymin); + } + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - ED_region_pixelspace(ar); - - /* render result draw */ if (v3d->flag & V3D_DISPBGPICS) view3d_draw_bgpic(scene, ar, v3d, FALSE, TRUE); else fdrawcheckerboard(0, 0, ar->winx, ar->winy); + if (draw_border) { + /* restore scissor as it was before */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); + } + + /* render result draw */ type = rv3d->render_engine->type; type->view_draw(rv3d->render_engine, C); @@ -3028,15 +3061,21 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha void view3d_main_area_draw(const bContext *C, ARegion *ar) { + Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); const char *grid_unit = NULL; + int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER)); - /* draw viewport using external renderer? */ - if (!(v3d->drawtype == OB_RENDER && view3d_main_area_draw_engine(C, ar))) { - /* draw viewport using opengl */ + /* draw viewport using opengl */ + if (v3d->drawtype != OB_RENDER || draw_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); ED_region_pixelspace(ar); } + + /* draw viewport using external renderer */ + if (v3d->drawtype == OB_RENDER) + view3d_main_area_draw_engine(C, ar, draw_border); view3d_main_area_draw_info(C, ar, grid_unit); -- cgit v1.2.3 From 8beea054f7490ee9892b963c96b5ce80886483be Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Thu, 7 Jun 2012 01:44:22 +0000 Subject: Fixing some potential heap corruption issues in the Blenderplayer when it is built with CMake. This fix forces Blender and the Blenderplayer to use the same SDNA, since inconsistencies between Blender's and the Blenderplayer's SDNA is what lead to the corruption issues. --- source/blenderplayer/CMakeLists.txt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 9fb0c103f1d..2c2b3f6df8a 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -31,12 +31,6 @@ if(WITH_CODEC_QUICKTIME) add_definitions(-DWITH_QUICKTIME) endif() -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dna.c - COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesdna ${CMAKE_CURRENT_BINARY_DIR}/dna.c ${CMAKE_SOURCE_DIR}/source/blender/makesdna/ - DEPENDS ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesdna -) - if(WIN32 AND NOT UNIX) string(SUBSTRING ${BLENDER_VERSION} 0 1 bver1) string(SUBSTRING ${BLENDER_VERSION} 2 1 bver2) @@ -60,10 +54,10 @@ if(WIN32 AND NOT UNIX) ) endif() - add_executable(blenderplayer ${EXETYPE} ${CMAKE_CURRENT_BINARY_DIR}/dna.c ../icons/winblender.rc) + add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c ../icons/winblender.rc) elseif(APPLE) - add_executable(blenderplayer ${EXETYPE} ${CMAKE_CURRENT_BINARY_DIR}/dna.c) + add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) @@ -74,7 +68,7 @@ elseif(APPLE) MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION} ${BLENDER_DATE}") else() - add_executable(blenderplayer ${CMAKE_CURRENT_BINARY_DIR}/dna.c) + add_executable(blenderplayer bad_level_call_stubs/stubs.c) endif() add_dependencies(blenderplayer makesdna) -- cgit v1.2.3 From ebb2dc84fcbb344ae3625e0e9d89b724d5378ca0 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Thu, 7 Jun 2012 01:46:28 +0000 Subject: Some slight refactoring of the BGE's LibLoad code to make things a bit cleaner (no functional changes). --- .../Converter/KX_BlenderSceneConverter.cpp | 60 ++++++++++------------ 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 0613b137fe8..78e5d7b32c2 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -930,13 +930,34 @@ bool KX_BlenderSceneConverter::LinkBlendFilePath(const char *path, char *group, return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str, options); } -bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) +static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode) { - Main *main_newlib; /* stored as a dynamic 'main' until we free it */ Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; - int idcode= BKE_idcode_from_name(group); short flag= 0; /* don't need any special options */ + + /* here appending/linking starts */ + main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); + + int totnames_dummy; + names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); + + int i=0; + LinkNode *n= names; + while(n) { + BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); + n= (LinkNode *)n->next; + i++; + } + BLI_linklist_free(names, free); /* free linklist *and* each node's data */ + + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); +} + +bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) +{ + Main *main_newlib; /* stored as a dynamic 'main' until we free it */ + int idcode= BKE_idcode_from_name(group); ReportList reports; static char err_local[255]; @@ -964,40 +985,11 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain"); BKE_reports_init(&reports, RPT_STORE); - /* here appending/linking starts */ - main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); - - int totnames_dummy; - names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); - - int i=0; - LinkNode *n= names; - while(n) { - BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); - n= (LinkNode *)n->next; - i++; - } - BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - - BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); + load_datablocks(main_newlib, bpy_openlib, path, idcode); /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); - - int totnames_dummy; - names = BLO_blendhandle_get_datablock_names( bpy_openlib, ID_AC, &totnames_dummy); - - int i=0; - LinkNode *n= names; - while(n) { - BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, ID_AC); - n= (LinkNode *)n->next; - i++; - } - BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - - BLO_library_append_end(NULL, main_tmp, &bpy_openlib, ID_AC, flag); + load_datablocks(main_newlib, bpy_openlib, path, ID_AC); } BLO_blendhandle_close(bpy_openlib); -- cgit v1.2.3 From e69ec8be5554a774612b8eeb15a2f00a327cc795 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 7 Jun 2012 05:29:10 +0000 Subject: Bugfix [#31735] Performance issue related to object parenting to armature In the file included with the bugreport, framerates were dropping from 60fps to 11fps for an armature with several lattices parented, and a 5fps drop everytime an object was parented to the armature. Upon (re-)inspection of the code, it became apparent that this was being caused by a block of code that would recalculate the parent (perhaps recursively) as it thought the parent state was for the wrong timestamp. However, the timestamps this was using was never really updated (except for a single place, which set it to a single fixed value to force recalculations to take place), which meant that this branch was run all the time. AFACT, this is a remnant from some of the old timeoffset stuff + pre-Depsgraph timestamping hacks that are no longer used/set. --- source/blender/blenkernel/intern/object.c | 25 ++---------------------- source/blender/blenkernel/intern/scene.c | 2 -- source/blender/editors/space_view3d/drawobject.c | 3 --- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 04631729d7a..16b699f16f9 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1927,11 +1927,6 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) { float slowmat[4][4] = MAT4_UNITY; - float stime = ctime; - - /* new version: correct parent+vertexparent and track+parent */ - /* this one only calculates direct attached parent and track */ - /* is faster, but should keep track of timeoffs */ if (ob == NULL) return; @@ -1941,21 +1936,8 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) if (ob->parent) { Object *par = ob->parent; - /* hurms, code below conflicts with depgraph... (ton) */ - /* and even worse, it gives bad effects for NLA stride too (try ctime != par->ctime, with MBlur) */ - if (stime != par->ctime) { - // only for ipo systems? - Object tmp = *par; - - if (par->proxy_from) ; // was a copied matrix, no where_is! bad... - else BKE_object_where_is_calc_time(scene, par, ctime); - - solve_parenting(scene, ob, par, ob->obmat, slowmat, 0); - - *par = tmp; - } - else - solve_parenting(scene, ob, par, ob->obmat, slowmat, 0); + /* calculate parent matrix */ + solve_parenting(scene, ob, par, ob->obmat, slowmat, 0); /* "slow parent" is definitely not threadsafe, and may also give bad results jumping around * An old-fashioned hack which probably doesn't really cut it anymore @@ -1974,10 +1956,7 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) bConstraintOb *cob; cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - - /* constraints need ctime, not stime. Some call BKE_object_where_is_calc_time and bsystem_time */ solve_constraints(&ob->constraints, cob, ctime); - constraints_clear_evalob(cob); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d9f1a6372ee..1113555e3bf 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -610,8 +610,6 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) /* not too nice... for recovering objects with lost data */ //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE; ob->flag = base->flag; - - ob->ctime = -1234567.0; /* force ipo to be calculated later */ } /* no full animation update, this to enable render code to work (render code calls own animation updates) */ } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 63dc6c21863..73d941f62ce 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -6578,9 +6578,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* no return after this point, otherwise leaks */ view3d_cached_text_draw_begin(); - /* patch? children objects with a timeoffs change the parents. How to solve! */ - /* if ( ((int)ob->ctime) != F_(scene->r.cfra)) BKE_object_where_is_calc(scene, ob); */ - /* draw motion paths (in view space) */ if (ob->mpath && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { bAnimVizSettings *avs = &ob->avs; -- cgit v1.2.3 From ffd75901f32e2270406e43855c7b2dee065f948e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 7 Jun 2012 05:39:28 +0000 Subject: Code cleanup - Shuffled solve_parenting() function around to remove need for forward def/local prototype --- source/blender/blenkernel/intern/object.c | 169 +++++++++++++++--------------- 1 file changed, 82 insertions(+), 87 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 16b699f16f9..a01024acfd3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -115,8 +115,6 @@ #include "GPU_material.h" /* Local function protos */ -static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul); - float originmat[3][3]; /* after BKE_object_where_is_calc(), can be used in other functions (bad!) */ void BKE_object_workob_clear(Object *workob) @@ -1904,6 +1902,84 @@ static void ob_parvert3(Object *ob, Object *par, float mat[][4]) } } +static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul) +{ + float totmat[4][4]; + float tmat[4][4]; + float locmat[4][4]; + float vec[3]; + int ok; + + BKE_object_to_mat4(ob, locmat); + + if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat); + + switch (ob->partype & PARTYPE) { + case PAROBJECT: + ok = 0; + if (par->type == OB_CURVE) { + if (((Curve *)par->data)->flag & CU_PATH) { + ob_parcurve(scene, ob, par, tmat); + ok = 1; + } + } + + if (ok) mul_serie_m4(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + else copy_m4_m4(totmat, par->obmat); + + break; + case PARBONE: + ob_parbone(ob, par, tmat); + mul_serie_m4(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + + case PARVERT1: + unit_m4(totmat); + if (simul) { + copy_v3_v3(totmat[3], par->obmat[3]); + } + else { + give_parvert(par, ob->par1, vec); + mul_v3_m4v3(totmat[3], par->obmat, vec); + } + break; + case PARVERT3: + ob_parvert3(ob, par, tmat); + + mul_serie_m4(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + + case PARSKEL: + copy_m4_m4(totmat, par->obmat); + break; + } + + // total + mul_serie_m4(tmat, totmat, ob->parentinv, + NULL, NULL, NULL, NULL, NULL, NULL); + mul_serie_m4(obmat, tmat, locmat, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (simul) { + + } + else { + // external usable originmat + copy_m3_m4(originmat, tmat); + + // origin, voor help line + if ((ob->partype & PARTYPE) == PARSKEL) { + copy_v3_v3(ob->orig, par->obmat[3]); + } + else { + copy_v3_v3(ob->orig, totmat[3]); + } + } +} + static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[4][4]) { float *fp1, *fp2; @@ -1926,8 +2002,6 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) { - float slowmat[4][4] = MAT4_UNITY; - if (ob == NULL) return; /* execute drivers only, as animation has already been done */ @@ -1935,6 +2009,7 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) if (ob->parent) { Object *par = ob->parent; + float slowmat[4][4] = MAT4_UNITY; /* calculate parent matrix */ solve_parenting(scene, ob, par, ob->obmat, slowmat, 0); @@ -1950,7 +2025,7 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) else { BKE_object_to_mat4(ob, ob->obmat); } - + /* solve constraints */ if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; @@ -1975,9 +2050,9 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4]) if (ob->parent) { Object *par = ob->parent; - + solve_parenting(scene, ob, par, obmat, slowmat, 1); - + if (ob->partype & PARSLOW) where_is_object_parslow(ob, obmat, slowmat); } @@ -1986,91 +2061,11 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4]) } } -static void solve_parenting(Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul) -{ - float totmat[4][4]; - float tmat[4][4]; - float locmat[4][4]; - float vec[3]; - int ok; - - BKE_object_to_mat4(ob, locmat); - - if (ob->partype & PARSLOW) copy_m4_m4(slowmat, obmat); - - switch (ob->partype & PARTYPE) { - case PAROBJECT: - ok = 0; - if (par->type == OB_CURVE) { - if (((Curve *)par->data)->flag & CU_PATH) { - ob_parcurve(scene, ob, par, tmat); - ok = 1; - } - } - - if (ok) mul_serie_m4(totmat, par->obmat, tmat, - NULL, NULL, NULL, NULL, NULL, NULL); - else copy_m4_m4(totmat, par->obmat); - - break; - case PARBONE: - ob_parbone(ob, par, tmat); - mul_serie_m4(totmat, par->obmat, tmat, - NULL, NULL, NULL, NULL, NULL, NULL); - break; - - case PARVERT1: - unit_m4(totmat); - if (simul) { - copy_v3_v3(totmat[3], par->obmat[3]); - } - else { - give_parvert(par, ob->par1, vec); - mul_v3_m4v3(totmat[3], par->obmat, vec); - } - break; - case PARVERT3: - ob_parvert3(ob, par, tmat); - - mul_serie_m4(totmat, par->obmat, tmat, - NULL, NULL, NULL, NULL, NULL, NULL); - break; - - case PARSKEL: - copy_m4_m4(totmat, par->obmat); - break; - } - - // total - mul_serie_m4(tmat, totmat, ob->parentinv, - NULL, NULL, NULL, NULL, NULL, NULL); - mul_serie_m4(obmat, tmat, locmat, - NULL, NULL, NULL, NULL, NULL, NULL); - - if (simul) { - - } - else { - // external usable originmat - copy_m3_m4(originmat, tmat); - - // origin, voor help line - if ((ob->partype & PARTYPE) == PARSKEL) { - copy_v3_v3(ob->orig, par->obmat[3]); - } - else { - copy_v3_v3(ob->orig, totmat[3]); - } - } - -} - void BKE_object_where_is_calc(struct Scene *scene, Object *ob) { BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); } - 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 -- cgit v1.2.3 From e261d5ca3b57b5e2f1e58ce84fd1dc9290978101 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 07:28:55 +0000 Subject: improvement to handle recalculation, only do this on auto-handles when they are in a spline. --- source/blender/blenkernel/intern/mask.c | 29 +++++++++++++++++------------ source/blender/makesdna/DNA_mask_types.h | 7 +++---- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index f7679d473b9..0a6063a6b21 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1399,14 +1399,6 @@ void BKE_mask_calc_handles(Mask *mask) } } -void BKE_mask_calc_handles_deform(Mask *mask) -{ - MaskLayer *masklay; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - BKE_mask_layer_calc_handles_deform(masklay); - } -} - void BKE_mask_update_deform(Mask *mask) { MaskLayer *masklay; @@ -1516,9 +1508,10 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - int i; for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + int has_auto = FALSE; BKE_mask_spline_ensure_deform(spline); @@ -1537,12 +1530,24 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) add_v2_v2(point_deform->bezt.vec[1], delta); add_v2_v2(point_deform->bezt.vec[2], delta); } + + if (point->bezt.h1 == HD_AUTO) { + has_auto = TRUE; + } + } + + /* if the spline has auto handles, these need to be recalculated after deformation */ + if (has_auto) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point_deform = &spline->points_deform[i]; + if (point_deform->bezt.h1 == HD_AUTO) { + BKE_mask_calc_handle_point(spline, point_deform); + } + } } + /* end extra calc handles loop */ } } - - /* TODO, move into loop above and only run if there are auto-handles */ - BKE_mask_calc_handles_deform(mask); } /* the purpose of this function is to ensure spline->points_deform is never out of date. diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index c036369c692..23f33729f69 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -43,9 +43,9 @@ typedef struct Mask { ID id; struct AnimData *adt; - ListBase masklayers; /* mask layers */ - int masklay_act; /* index of active mask layer (-1 == None) */ - int masklay_tot; /* total number of mask layers */ + ListBase masklayers; /* mask layers */ + int masklay_act; /* index of active mask layer (-1 == None) */ + int masklay_tot; /* total number of mask layers */ } Mask; typedef struct MaskParent { @@ -166,5 +166,4 @@ enum { MASK_BLENDFLAG_INVERT = (1 << 0) }; - #endif // __DNA_MASK_TYPES_H__ -- cgit v1.2.3 From c714388473115752f32d0f2a7b722d4ef3bf7d57 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 Jun 2012 07:39:37 +0000 Subject: Fix #31734: Edge slide operator Flip/Even options not working Issue was caused by wrong check whether transform is in edge slide mode. --- source/blender/editors/transform/transform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0abc4f00c54..b437d186549 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5201,7 +5201,7 @@ void initEdgeSlide(TransInfo *t) int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) { - if (t->flag & TFM_EDGE_SLIDE) { + if (t->mode == TFM_EDGE_SLIDE) { SlideData *sld = t->customData; if (sld) { @@ -5243,7 +5243,7 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) void drawNonPropEdge(const struct bContext *C, TransInfo *t) { - if (t->flag & TFM_EDGE_SLIDE) { + if (t->mode == TFM_EDGE_SLIDE) { SlideData *sld = (SlideData *)t->customData; /* Non-Prop mode */ if (sld && sld->is_proportional == FALSE) { -- cgit v1.2.3 From a921ca86f7a008d818f0f6da930c9d25b971ab64 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 08:02:48 +0000 Subject: fix for error in previous commit. - dupli-group armatures with pose bone objects set would draw with uninitialized color - also fix old bug - armature were over-riding the constcolor option - so drawing dupli-groups for eg - would ignore the DRAW_CONSTCOLOR flag. --- source/blender/editors/space_view3d/drawarmature.c | 28 +++++++++----- source/blender/editors/space_view3d/drawobject.c | 43 +++++++++++++--------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index cb8b309dc72..cf8b84b5a56 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1658,7 +1658,7 @@ static void bone_matrix_translate_y(float mat[][4], float y) /* assumes object is Armature with pose */ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, const unsigned char ob_wire_col[4], - const short is_ghost, const short is_outline) + const short do_const_color, const short is_outline) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; @@ -1828,10 +1828,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } /* prepare colors */ - if (is_ghost) { + if (do_const_color) { /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */ } - else if (arm->flag & ARM_POSEMODE) + else if (arm->flag & ARM_POSEMODE) set_pchan_colorset(ob, pchan); else { glColor3ubv(ob_wire_col); @@ -1993,12 +1993,22 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ if ((G.f & G_PICKSEL) == 0) { float vec[3]; - + unsigned char col[4]; - col[0] = ob_wire_col[0]; - col[1] = ob_wire_col[1]; - col[2] = ob_wire_col[2]; - col[3] = 255; + + if (do_const_color) { + /* so we can draw bone names in current const color */ + float tcol[4]; + glGetFloatv(GL_CURRENT_COLOR, tcol); + rgb_float_to_uchar(col, tcol); + col[3] = 255; + } + else { + col[0] = ob_wire_col[0]; + col[1] = ob_wire_col[1]; + col[2] = ob_wire_col[2]; + col[3] = 255; + } if (v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -2602,7 +2612,7 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } } - draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, FALSE, is_outline); + draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (flag & DRAW_CONSTCOLOR), is_outline); arm->flag &= ~ARM_POSEMODE; if (ob->mode & OB_MODE_POSE) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 73d941f62ce..51985a2860f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1231,19 +1231,23 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, /* lamp center */ copy_v3_v3(vec, ob->obmat[3]); - - /* for AA effects */ - curcol[0] = ob_wire_col[0]; - curcol[1] = ob_wire_col[1]; - curcol[2] = ob_wire_col[2]; - curcol[3] = 154; - glColor4ubv(curcol); + + if ((flag & DRAW_CONSTCOLOR) == 0) { + /* for AA effects */ + curcol[0] = ob_wire_col[0]; + curcol[1] = ob_wire_col[1]; + curcol[2] = ob_wire_col[2]; + curcol[3] = 154; + glColor4ubv(curcol); + } if (lampsize > 0.0f) { - if (ob->id.us > 1) { - if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155); - else glColor4ub(0x77, 0xCC, 0xCC, 155); + if ((flag & DRAW_CONSTCOLOR) == 0) { + if (ob->id.us > 1) { + if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155); + else glColor4ub(0x77, 0xCC, 0xCC, 155); + } } /* Inner Circle */ @@ -1253,8 +1257,10 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, drawcircball(GL_POLYGON, vec, lampsize, imat); /* restore */ - if (ob->id.us > 1) - glColor4ubv(curcol); + if ((flag & DRAW_CONSTCOLOR) == 0) { + if (ob->id.us > 1) + glColor4ubv(curcol); + } /* Outer circle */ circrad = 3.0f * lampsize; @@ -1486,9 +1492,10 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, glDisable(GL_BLEND); - /* restore for drawing extra stuff */ - glColor3ubv(ob_wire_col); - + if ((flag & DRAW_CONSTCOLOR) == 0) { + /* restore for drawing extra stuff */ + glColor3ubv(ob_wire_col); + } } static void draw_limit_line(float sta, float end, unsigned int col) @@ -6540,7 +6547,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) RegionView3D *rv3d = ar->regiondata; float vec1[3], vec2[3]; unsigned int col = 0; - unsigned char ob_wire_col[4]; + unsigned char _ob_wire_col[4]; /* dont initialize this */ + unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ int i, selstart, selend, empty_object = 0; short dt, dtx, zbufoff = 0; const short is_obact = (ob == OBACT); @@ -6601,7 +6609,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) project_short(ar, ob->obmat[3], &base->sx); - draw_object_wire_color(scene, base, ob_wire_col, warning_recursive); + draw_object_wire_color(scene, base, _ob_wire_col, warning_recursive); + ob_wire_col = _ob_wire_col; glColor3ubv(ob_wire_col); } -- cgit v1.2.3 From ef850d75f52726e9d479cd9873ec8b6343cdf3f2 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 7 Jun 2012 08:04:58 +0000 Subject: Fix unaligned array crash in Eigen3 because of compilation option. The EIGEN_DONT_ALIGN_STATICALLY compilation option was added for Win32 only in revision 41283 because of some compilation problem. But this option is causing alignment problem for Eigen3 local variables when SSE optimization is enabled. I do not have any compilation problem when the option is not defined, so I just remove it as it should. --- intern/itasc/CMakeLists.txt | 3 --- intern/itasc/SConscript | 3 --- source/blender/ikplugin/CMakeLists.txt | 3 --- source/blender/ikplugin/SConscript | 3 --- 4 files changed, 12 deletions(-) diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index 3d24a0cb8c6..f4bc0326ea1 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -318,8 +318,5 @@ set(SRC ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h ) -if(WIN32) - add_definitions(-DEIGEN_DONT_ALIGN_STATICALLY) -endif() blender_add_lib(bf_intern_itasc "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/itasc/SConscript b/intern/itasc/SConscript index 69dddf40228..c1ad931c665 100644 --- a/intern/itasc/SConscript +++ b/intern/itasc/SConscript @@ -9,8 +9,5 @@ incs = '. ../../extern/Eigen3' defs = [] -if env['PLATFORM'] == 'win32': - defs.append('EIGEN_DONT_ALIGN_STATICALLY') - env.BlenderLib ('bf_intern_itasc', sources, Split(incs), defs, libtype=['intern','player'], priority=[20,100] ) diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt index 87b0c6c671a..f37b254d719 100644 --- a/source/blender/ikplugin/CMakeLists.txt +++ b/source/blender/ikplugin/CMakeLists.txt @@ -57,8 +57,5 @@ if(WITH_IK_ITASC) ) endif() -if(WIN32) - add_definitions(-DEIGEN_DONT_ALIGN_STATICALLY) -endif() blender_add_lib(bf_ikplugin "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/ikplugin/SConscript b/source/blender/ikplugin/SConscript index 4cff3399fdc..38c53894df8 100644 --- a/source/blender/ikplugin/SConscript +++ b/source/blender/ikplugin/SConscript @@ -8,7 +8,4 @@ incs += ' ../blenkernel ../include ../ikplugin #/intern/itasc #/extern/Eigen3' defs.append('WITH_IK_ITASC') -if env['PLATFORM'] == 'win32': - defs.append('EIGEN_DONT_ALIGN_STATICALLY') - env.BlenderLib ( 'bf_ikplugin', sources, Split(incs), defs, libtype=['core','player'], priority=[180, 190] ) -- cgit v1.2.3 From 2b889eea8d1e43e46c9a1dfb2ab3a253eab60e55 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 7 Jun 2012 08:16:41 +0000 Subject: Fix [#31430] part 2: crash in iTaSC when end effector is a fixed bone. This situation was causing access to invalid index in the joint angle array although the end effector doesn't need any joint angle to compute its pause. Fixed this by changing the internal API of joint array: return pointer instead of reference so that NULL pointer can be returned instead of crashing when the index is invalid. --- intern/itasc/Armature.cpp | 28 ++++++++++++------------- intern/itasc/Distance.cpp | 2 +- intern/itasc/kdl/jntarray.cpp | 17 +++++++++------ intern/itasc/kdl/jntarray.hpp | 18 ++++++++++------ intern/itasc/kdl/joint.cpp | 26 +++++++++++++++-------- intern/itasc/kdl/joint.hpp | 2 +- intern/itasc/kdl/kinfam_io.cpp | 2 +- intern/itasc/kdl/segment.cpp | 4 ++-- intern/itasc/kdl/segment.hpp | 4 ++-- intern/itasc/kdl/utilities/utility.h | 4 ++++ source/blender/ikplugin/intern/itasc_plugin.cpp | 6 +++--- 11 files changed, 68 insertions(+), 45 deletions(-) diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp index dd5c1921a98..1dacb8bc184 100644 --- a/intern/itasc/Armature.cpp +++ b/intern/itasc/Armature.cpp @@ -158,7 +158,7 @@ void Armature::pushQ(CacheTS timestamp) { if (m_qCCh >= 0) { // try to keep the cache if the joints are the same - m_cache->addCacheVectorIfDifferent(this, m_qCCh, timestamp, &m_qKdl(0), m_qKdl.rows(), KDL::epsilon); + m_cache->addCacheVectorIfDifferent(this, m_qCCh, timestamp, m_qKdl(0), m_qKdl.rows(), KDL::epsilon); m_qCTs = timestamp; } } @@ -170,8 +170,8 @@ bool Armature::popQ(CacheTS timestamp) double* item; item = (double*)m_cache->getPreviousCacheItem(this, m_qCCh, ×tamp); if (item && m_qCTs != timestamp) { - double& q = m_qKdl(0); - memcpy(&q, item, m_qKdl.rows()*sizeof(q)); + double* q = m_qKdl(0); + memcpy(q, item, m_qKdl.rows()*sizeof(double)); m_qCTs = timestamp; // changing the joint => recompute the jacobian updateJacobian(); @@ -255,7 +255,7 @@ bool Armature::getSegment(const std::string& name, const unsigned int q_size, co p_tip = &sit->second.segment.getFrameToTip(); for (unsigned int dof=0; dofgetNDof(); dof++) { (&q_rest)[dof] = m_joints[sit->second.q_nr+dof].rest; - (&q)[dof] = m_qKdl(sit->second.q_nr+dof); + (&q)[dof] = m_qKdl[sit->second.q_nr+dof]; } return true; } @@ -267,7 +267,7 @@ double Armature::getMaxJointChange() double maxJoint = 0.0; for (unsigned int i=0; isegment->second.q_nr; iv_nr; i++, nr++) { - *(double*)&pConstraint->value[i].y = m_qKdl(nr); - *(double*)&pConstraint->value[i].ydot = m_qdotKdl(nr); + *(double*)&pConstraint->value[i].y = m_qKdl[nr]; + *(double*)&pConstraint->value[i].ydot = m_qdotKdl[nr]; } if (pConstraint->function && (pConstraint->substep || (!timestamp.reiterate && !timestamp.substep))) { (*pConstraint->function)(timestamp, pConstraint->values, pConstraint->v_nr, pConstraint->param); diff --git a/intern/itasc/Distance.cpp b/intern/itasc/Distance.cpp index 7cf04367a4e..c9efca101e3 100644 --- a/intern/itasc/Distance.cpp +++ b/intern/itasc/Distance.cpp @@ -189,7 +189,7 @@ void Distance::updateKinematics(const Timestamp& timestamp) void Distance::updateJacobian() { for(unsigned int i=0;i<6;i++) - m_chiKdl(i)=m_chi(i); + m_chiKdl[i]=m_chi[i]; m_fksolver->JntToCart(m_chiKdl,m_internalPose); m_jacsolver->JntToJac(m_chiKdl,m_jac); diff --git a/intern/itasc/kdl/jntarray.cpp b/intern/itasc/kdl/jntarray.cpp index 77c75e6af6c..db2c913a532 100644 --- a/intern/itasc/kdl/jntarray.cpp +++ b/intern/itasc/kdl/jntarray.cpp @@ -71,20 +71,25 @@ namespace KDL SetToZero(*this); } - double JntArray::operator()(unsigned int i,unsigned int j)const + double JntArray::operator[](unsigned int i)const { - assert(i=size) + return NULL; + return &data[i]; + } + unsigned int JntArray::rows()const { return size; diff --git a/intern/itasc/kdl/jntarray.hpp b/intern/itasc/kdl/jntarray.hpp index 8db4cd6f2b3..ece6b0bdb6b 100644 --- a/intern/itasc/kdl/jntarray.hpp +++ b/intern/itasc/kdl/jntarray.hpp @@ -107,24 +107,30 @@ class MyTask : public RTT::TaskContext JntArray& operator = ( const JntArray& arg); /** - * get_item operator for the joint array, if a second value is - * given it should be zero, since a JntArray resembles a column. + * get_item operator for the joint array * * * @return the joint value at position i, starting from 0 * @pre 0 != size (ie non-default constructor or resize() called) */ - double operator()(unsigned int i,unsigned int j=0)const; + double operator[](unsigned int i) const; /** - * set_item operator, again if a second value is given it - *should be zero. + * set_item operator * * @return reference to the joint value at position i,starting *from zero. * @pre 0 != size (ie non-default constructor or resize() called) */ - double& operator()(unsigned int i,unsigned int j=0); + double& operator[](unsigned int i); /** + * access operator for the joint array. Use pointer here to allow + * access to sequential joint angles (required for ndof joints) + * + * + * @return the joint value at position i, NULL if i is outside the valid range + */ + double* operator()(unsigned int i); + /** * Returns the number of rows (size) of the array * */ diff --git a/intern/itasc/kdl/joint.cpp b/intern/itasc/kdl/joint.cpp index 5458efc4fcf..161794ddd72 100644 --- a/intern/itasc/kdl/joint.cpp +++ b/intern/itasc/kdl/joint.cpp @@ -55,37 +55,45 @@ namespace KDL { { } - Frame Joint::pose(const double& q)const + Frame Joint::pose(const double* q)const { switch(type){ case RotX: - return Frame(Rotation::RotX(scale*q+offset)); + assert(q); + return Frame(Rotation::RotX(scale*q[0]+offset)); break; case RotY: - return Frame(Rotation::RotY(scale*q+offset)); + assert(q); + return Frame(Rotation::RotY(scale*q[0]+offset)); break; case RotZ: - return Frame(Rotation::RotZ(scale*q+offset)); + assert(q); + return Frame(Rotation::RotZ(scale*q[0]+offset)); break; case TransX: - return Frame(Vector(scale*q+offset,0.0,0.0)); + assert(q); + return Frame(Vector(scale*q[0]+offset,0.0,0.0)); break; case TransY: - return Frame(Vector(0.0,scale*q+offset,0.0)); + assert(q); + return Frame(Vector(0.0,scale*q[0]+offset,0.0)); break; case TransZ: - return Frame(Vector(0.0,0.0,scale*q+offset)); + assert(q); + return Frame(Vector(0.0,0.0,scale*q[0]+offset)); break; case Sphere: // the joint angles represent a rotation vector expressed in the base frame of the joint // (= the frame you get when there is no offset nor rotation) - return Frame(Rot(Vector((&q)[0], (&q)[1], (&q)[2]))); + assert(q); + return Frame(Rot(Vector(q[0], q[1], q[2]))); break; case Swing: // the joint angles represent a 2D rotation vector in the XZ planee of the base frame of the joint // (= the frame you get when there is no offset nor rotation) - return Frame(Rot(Vector((&q)[0], 0.0, (&q)[1]))); + assert(q); + return Frame(Rot(Vector(q[0], 0.0, q[1]))); break; default: return Frame::Identity(); diff --git a/intern/itasc/kdl/joint.hpp b/intern/itasc/kdl/joint.hpp index a1291509f0f..9d25b427499 100644 --- a/intern/itasc/kdl/joint.hpp +++ b/intern/itasc/kdl/joint.hpp @@ -70,7 +70,7 @@ namespace KDL { * * @return the resulting 6D-pose */ - Frame pose(const double& q)const; + Frame pose(const double* q)const; /** * Request the resulting 6D-velocity with a joint velocity qdot * diff --git a/intern/itasc/kdl/kinfam_io.cpp b/intern/itasc/kdl/kinfam_io.cpp index 15557ab5f05..ff4cab862ce 100644 --- a/intern/itasc/kdl/kinfam_io.cpp +++ b/intern/itasc/kdl/kinfam_io.cpp @@ -76,7 +76,7 @@ std::istream& operator >>(std::istream& is, Tree& tree) { std::ostream& operator <<(std::ostream& os, const JntArray& array) { os << "["; for (unsigned int i = 0; i < array.rows(); i++) - os << std::setw(KDL_FRAME_WIDTH) << array(i); + os << std::setw(KDL_FRAME_WIDTH) << array[i]; os << "]"; return os; } diff --git a/intern/itasc/kdl/segment.cpp b/intern/itasc/kdl/segment.cpp index cba797899e1..f963559c4c8 100644 --- a/intern/itasc/kdl/segment.cpp +++ b/intern/itasc/kdl/segment.cpp @@ -48,12 +48,12 @@ namespace KDL { { } - Frame Segment::pose(const double& q)const + Frame Segment::pose(const double* q)const { return joint.pose(q)*f_tip; } - Twist Segment::twist(const double& q, const double& qdot, int dof)const + Twist Segment::twist(const double* q, const double& qdot, int dof)const { return joint.twist(qdot, dof).RefPoint(pose(q).p); } diff --git a/intern/itasc/kdl/segment.hpp b/intern/itasc/kdl/segment.hpp index 87d972ead70..130bfb13f8b 100644 --- a/intern/itasc/kdl/segment.hpp +++ b/intern/itasc/kdl/segment.hpp @@ -73,7 +73,7 @@ namespace KDL { * * @return pose from the root to the tip of the segment */ - Frame pose(const double& q)const; + Frame pose(const double* q)const; /** * Request the 6D-velocity of the tip of the segment, given * the joint position q and the joint velocity qdot. @@ -85,7 +85,7 @@ namespace KDL { *in the base-frame of the segment(root) and with the tip of *the segment as reference point. */ - Twist twist(const double& q,const double& qdot, int dof=0)const; + Twist twist(const double* q,const double& qdot, int dof=0)const; /** * Request the 6D-velocity at a given point p, relative to base frame of the segment diff --git a/intern/itasc/kdl/utilities/utility.h b/intern/itasc/kdl/utilities/utility.h index fbf9982665a..892b375d442 100644 --- a/intern/itasc/kdl/utilities/utility.h +++ b/intern/itasc/kdl/utilities/utility.h @@ -27,6 +27,10 @@ #include #include +#ifdef NDEBUG +#undef assert +#define assert(e) ((void)0) +#endif ///////////////////////////////////////////////////////////// // configurable options for the frames library. diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index ebbb201de8e..048dd955726 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -1000,7 +1000,7 @@ static void convert_pose(IK_Scene *ikscene) // assume uniform scaling and take Y scale as general scale for the armature scale = len_v3(ikscene->blArmature->obmat[1]); - rot = (ikscene->jointArray.rows() > 0) ? &ikscene->jointArray(0) : NULL; + rot = ikscene->jointArray(0); for (joint=a=0, ikchan = ikscene->channels; anumchan && jointnumjoint; ++a, ++ikchan) { pchan= ikchan->pchan; bone= pchan->bone; @@ -1041,7 +1041,7 @@ static void BKE_pose_rest(IK_Scene *ikscene) // rest pose is 0 SetToZero(ikscene->jointArray); // except for transY joints - rot = (ikscene->jointArray.rows() > 0) ? &ikscene->jointArray(0) : NULL; + rot = ikscene->jointArray(0); for (joint=a=0, ikchan = ikscene->channels; anumchan && jointnumjoint; ++a, ++ikchan) { pchan= ikchan->pchan; bone= pchan->bone; @@ -1140,7 +1140,7 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan) // in Blender, the rest pose is always 0 for joints BKE_pose_rest(ikscene); } - rot = (ikscene->jointArray.rows() > 0) ? &ikscene->jointArray(0) : NULL; + rot = ikscene->jointArray(0); for (a=0, ikchan = ikscene->channels; atotchannel; ++a, ++ikchan) { pchan= ikchan->pchan; bone= pchan->bone; -- cgit v1.2.3 From 2c362c13fd9d66eec5aa37de043ef230ecfd8e5e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 08:20:10 +0000 Subject: dont draw bone names/axis inside duplicators --- source/blender/editors/space_view3d/drawarmature.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index cf8b84b5a56..7d0faabaff2 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1985,11 +1985,17 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glDisable(GL_CULL_FACE); /* draw DoFs */ - if (arm->flag & ARM_POSEMODE) - draw_pose_dofs(ob); + if (arm->flag & ARM_POSEMODE) { + if (((base->flag & OB_FROMDUPLI) == 0)) { + draw_pose_dofs(ob); + } + } /* finally names and axes */ - if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) && (is_outline == 0)) { + if ((arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) && + (is_outline == 0) && + ((base->flag & OB_FROMDUPLI) == 0)) + { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ if ((G.f & G_PICKSEL) == 0) { float vec[3]; -- cgit v1.2.3 From bc961c90a2fffa1323036c30cb7db69e1c40537d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 09:04:45 +0000 Subject: fix for armature specular material color overriding the wire color when instanced in a dupli --- source/blender/editors/space_view3d/drawarmature.c | 24 ++++++++++++++-------- source/blender/editors/space_view3d/drawmesh.c | 6 +++--- source/blender/editors/space_view3d/drawobject.c | 6 +++--- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 7d0faabaff2..7edf18136d2 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1753,8 +1753,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (bone == arm->act_bone) flag |= BONE_DRAW_ACTIVE; - /* set color-set to use */ - set_pchan_colorset(ob, pchan); + if (do_const_color) { + /* keep color */ + } + else { + /* set color-set to use */ + set_pchan_colorset(ob, pchan); + } if (use_custom) { /* if drawwire, don't try to draw in solid */ @@ -1950,7 +1955,12 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* extra draw service for pose mode */ /* set color-set to use */ - set_pchan_colorset(ob, pchan); + if (do_const_color) { + /* keep color */ + } + else { + set_pchan_colorset(ob, pchan); + } if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) { /* custom bone shapes should not be drawn here! */ @@ -2001,7 +2011,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, float vec[3]; unsigned char col[4]; - if (do_const_color) { /* so we can draw bone names in current const color */ float tcol[4]; @@ -2562,11 +2571,8 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (dt > OB_WIRE && !ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { /* we use color for solid lighting */ - glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); - glEnable(GL_COLOR_MATERIAL); - glColor3ub(255, 255, 255); // clear spec - glDisable(GL_COLOR_MATERIAL); - + const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); // only for lighting... } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index de1d9f22667..19696b2b0e0 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -1015,14 +1015,14 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *d if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) { if (do_light) { + const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f}; + /* enforce default material settings */ GPU_enable_material(0, NULL); /* but set default spec */ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); - glEnable(GL_COLOR_MATERIAL); /* according manpages needed */ - glColor3ub(120, 120, 120); - glDisable(GL_COLOR_MATERIAL); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); /* diffuse */ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 51985a2860f..63780ebbd20 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3434,6 +3434,8 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material); } else { + const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f}; + /* draw outline */ if ( (v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && @@ -3451,9 +3453,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* set default spec */ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); - glEnable(GL_COLOR_MATERIAL); /* according manpages needed */ - glColor3ub(120, 120, 120); - glDisable(GL_COLOR_MATERIAL); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); /* diffuse */ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glEnable(GL_LIGHTING); -- cgit v1.2.3 From ed7dbbdfe946fa7bf22d319997ea3634bc48cab3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 09:05:51 +0000 Subject: fix for buffer overrun on windows by kjym3 on IRC. --- source/blender/python/intern/bpy_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 0c88c7d9c81..73188b3f830 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -421,7 +421,7 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, fclose(fp); - pystring = MEM_mallocN(strlen(fn) + 36, "pystring"); + pystring = MEM_mallocN(strlen(fn) + 37, "pystring"); pystring[0] = '\0'; sprintf(pystring, "f=open(r'%s');exec(f.read());f.close()", fn); py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict); -- cgit v1.2.3 From a99b9a5c3d6eb567092dcfb005a540564b5b8ebd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 Jun 2012 09:11:16 +0000 Subject: Fix #31725: UV map order is ignored when opening in 2.6+ versions Issue was caused by do_versions being used pdata as reference for active/render/ stencil/clone layer indices instead of fdata. Added some utility functions used only by do_versions to be sure this indices are set from fdata for pre-bmesh files. --- source/blender/blenkernel/BKE_customdata.h | 1 + source/blender/blenkernel/BKE_mesh.h | 1 + source/blender/blenkernel/intern/customdata.c | 42 +++++++++++++++++++++++++++ source/blender/blenkernel/intern/mesh.c | 22 ++++++++++++++ source/blender/blenloader/intern/readfile.c | 2 +- 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index bbe68db8bfe..3dc68edf12b 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -321,6 +321,7 @@ void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int totloop, int totpoly); void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total); void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype); /* External file storage */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 1878e43f577..887340622ad 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -151,6 +151,7 @@ void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); void BKE_mesh_delete_material_index(struct Mesh *me, short index); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh); +void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh); void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id, struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, int totedge_i, int totface_i, int totloop_i, int totpoly_i, diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 5dc50dca45a..f551b2d18a4 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2219,6 +2219,48 @@ void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, } } +/* update active indices for active/render/clone/stencil custom data layers + * based on indices from fdata layers + * used by do_versions in readfile.c when creating pdata and ldata for pre-bmesh + * meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files + */ +void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata) +{ + int act; + + if (CustomData_has_layer(fdata, CD_MTFACE)) { + act = CustomData_get_active_layer(fdata, CD_MTFACE); + CustomData_set_layer_active(pdata, CD_MTEXPOLY, act); + CustomData_set_layer_active(ldata, CD_MLOOPUV, act); + + act = CustomData_get_render_layer(fdata, CD_MTFACE); + CustomData_set_layer_render(pdata, CD_MTEXPOLY, act); + CustomData_set_layer_render(ldata, CD_MLOOPUV, act); + + act = CustomData_get_clone_layer(fdata, CD_MTFACE); + CustomData_set_layer_clone(pdata, CD_MTEXPOLY, act); + CustomData_set_layer_clone(ldata, CD_MLOOPUV, act); + + act = CustomData_get_stencil_layer(fdata, CD_MTFACE); + CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, act); + CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act); + } + + if (CustomData_has_layer(fdata, CD_MCOL)) { + act = CustomData_get_active_layer(fdata, CD_MCOL); + CustomData_set_layer_active(ldata, CD_MLOOPCOL, act); + + act = CustomData_get_render_layer(fdata, CD_MCOL); + CustomData_set_layer_render(ldata, CD_MLOOPCOL, act); + + act = CustomData_get_clone_layer(fdata, CD_MCOL); + CustomData_set_layer_clone(ldata, CD_MLOOPCOL, act); + + act = CustomData_get_stencil_layer(fdata, CD_MCOL); + CustomData_set_layer_stencil(ldata, CD_MLOOPCOL, act); + } +} + void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype) { int chunksize; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index ed93f27fe5c..d0b9e73e295 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2038,6 +2038,28 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) mesh_update_customdata_pointers(mesh, TRUE); } +/* the same as BKE_mesh_convert_mfaces_to_mpolys but oriented to be used in do_versions from readfile.c + * the difference is how active/render/clone/stencil indices are handled here + * + * normally thay're being set from pdata which totally makes sense for meshes which are already + * converted to bmesh structures, but when loading older files indices shall be updated in other + * way around, so newly added pdata and ldata would have this indices set based on fdata layer + * + * this is normally only needed when reading older files, in all other cases BKE_mesh_convert_mfaces_to_mpolys + * shall be always used + */ +void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh) +{ + BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata, + mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly, + mesh->medge, mesh->mface, + &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly); + + CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->pdata, &mesh->ldata); + + mesh_update_customdata_pointers(mesh, TRUE); +} + void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, int totedge_i, int totface_i, int totloop_i, int totpoly_i, MEdge *medge, MFace *mface, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8fccae91870..cdf344beb4d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3684,7 +3684,7 @@ static void lib_link_mesh(FileData *fd, Main *main) Main *gmain = G.main; G.main = main; - BKE_mesh_convert_mfaces_to_mpolys(me); + BKE_mesh_do_versions_convert_mfaces_to_mpolys(me); G.main = gmain; } -- cgit v1.2.3 From 35a274711ef26d0014e70d66f8fab337d4d54312 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 7 Jun 2012 10:55:53 +0000 Subject: Bugfix [#31723] Renderer (internal) ignores keyframes on 'Compositing' checkbox for animations Pipeline options such as Use Compositing and Use Sequencer cannot be animated due to the way that they are implemented now, so adding these to the list of render properties that we cannot animate. --- source/blender/makesrna/intern/rna_scene.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 9eb313204f7..85c7b5679c1 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3660,6 +3660,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_compositing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_DOCOMP); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Compositing", "Process the render result through the compositing pipeline, " "if compositing nodes are enabled"); @@ -3667,6 +3668,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_sequencer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_DOSEQ); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Sequencer", "Process the render (and composited) result through the video sequence " "editor pipeline, if sequencer strips exist"); -- cgit v1.2.3 From 3140cd993d4c63ef597bf5a2314fab7e8e847667 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 14:21:25 +0000 Subject: fix for crash with selecting camera bundles. --- source/blender/editors/space_view3d/drawobject.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 63780ebbd20..2c59e2861e5 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1744,7 +1744,9 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); - glColor3ubv(ob_wire_col); + if ((flag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } if (flag & DRAW_PICKING) glLoadName(base->selcol); -- cgit v1.2.3 From 742171f60943e78f148fe6be15e4eaaf0c5f85ec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 15:20:51 +0000 Subject: fix for crash with recent color commits to draw-object, this case wasnt handled correctly before. --- source/blender/editors/space_view3d/drawobject.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 2c59e2861e5..edb40adfc67 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1774,9 +1774,16 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base #ifdef VIEW3D_CAMERA_BORDER_HACK if (is_view && !(G.f & G_PICKSEL)) { - view3d_camera_border_hack_col[0] = ob_wire_col[0]; - view3d_camera_border_hack_col[1] = ob_wire_col[1]; - view3d_camera_border_hack_col[2] = ob_wire_col[2]; + if ((flag & DRAW_CONSTCOLOR) == 0) { + view3d_camera_border_hack_col[0] = ob_wire_col[0]; + view3d_camera_border_hack_col[1] = ob_wire_col[1]; + view3d_camera_border_hack_col[2] = ob_wire_col[2]; + } + else { + float col[4]; + glGetFloatv(GL_CURRENT_COLOR, col); + rgb_float_to_uchar(view3d_camera_border_hack_col, col); + } view3d_camera_border_hack_test = TRUE; return; } -- cgit v1.2.3 From 3916414709d1baace6bd9d1e802be2730048da66 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 15:33:32 +0000 Subject: adding mask points now adds in the correct place relative to shape keys (updating other keys for the new points still needs work though) --- source/blender/editors/mask/mask_add.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 7ffff2b06e5..f81496c377a 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -54,7 +54,8 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather, MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, - float *u_r, float tangent[2]) + float *u_r, float tangent[2], + const short use_deform) { MaskLayer *masklay, *point_masklay; MaskSpline *point_spline; @@ -80,9 +81,12 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c for (spline = masklay->splines.first; spline; spline = spline->next) { int i; + MaskSplinePoint *cur_point; - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *cur_point = &spline->points[i]; + for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points; + i < spline->tot_point; + i++, cur_point++) + { float *diff_points; int tot_diff_point; @@ -123,7 +127,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c point_masklay = masklay; point_spline = spline; - point = cur_point; + point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point; dist = cur_dist; u = (float)i / tot_point; @@ -370,7 +374,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2]) float tangent[2]; float u; - if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent)) { + if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent, TRUE)) { MaskSplinePoint *new_point; int point_index = point - spline->points; @@ -651,7 +655,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) if (point) return OPERATOR_FINISHED; - if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) { + if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL, TRUE)) { Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u); -- cgit v1.2.3 From 105b1031dd34d19755b7ec5f5a7dcc6bfa74b2fb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 15:49:02 +0000 Subject: code cleanup: rename sequencer types to SEQ_TYPE_*** and use enums rather then defines. --- source/blender/blenkernel/intern/ipo.c | 12 +- source/blender/blenkernel/intern/seqeffects.c | 32 ++-- source/blender/blenkernel/intern/sequencer.c | 196 +++++++++++---------- source/blender/blenlib/intern/bpath.c | 4 +- source/blender/blenloader/intern/readfile.c | 10 +- source/blender/blenloader/intern/versioning_250.c | 2 +- .../blender/blenloader/intern/versioning_legacy.c | 2 +- source/blender/blenloader/intern/writefile.c | 14 +- source/blender/editors/sound/sound_ops.c | 6 +- .../blender/editors/space_outliner/outliner_draw.c | 10 +- .../blender/editors/space_outliner/outliner_tree.c | 4 +- .../editors/space_sequencer/sequencer_add.c | 18 +- .../editors/space_sequencer/sequencer_draw.c | 92 +++++----- .../editors/space_sequencer/sequencer_edit.c | 96 +++++----- .../editors/space_sequencer/sequencer_select.c | 30 ++-- .../editors/transform/transform_conversions.c | 22 +-- source/blender/makesdna/DNA_sequence_types.h | 171 +++++++++--------- source/blender/makesrna/intern/rna_sequencer.c | 104 +++++------ source/blender/makesrna/intern/rna_sequencer_api.c | 40 ++--- source/blender/render/intern/source/pipeline.c | 4 +- 20 files changed, 437 insertions(+), 432 deletions(-) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 9737888e0b2..bbc1874c2ae 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1924,14 +1924,14 @@ void do_versions_ipos_to_animato(Main *main) * (semi-hack (tm) ) */ switch (seq->type) { - case SEQ_IMAGE: - case SEQ_META: - case SEQ_SCENE: - case SEQ_MOVIE: - case SEQ_COLOR: + case SEQ_TYPE_IMAGE: + case SEQ_TYPE_META: + case SEQ_TYPE_SCENE: + case SEQ_TYPE_MOVIE: + case SEQ_TYPE_COLOR: adrcode = SEQ_FAC_OPACITY; break; - case SEQ_SPEED: + case SEQ_TYPE_SPEED: adrcode = SEQ_FAC_SPEED; break; } diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 4b6c362cd85..5e41c009fd3 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2987,12 +2987,12 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.copy = NULL; switch (sequence_type) { - case SEQ_CROSS: + case SEQ_TYPE_CROSS: rval.execute = do_cross_effect; rval.early_out = early_out_fade; rval.get_default_fac = get_default_fac_fade; break; - case SEQ_GAMCROSS: + case SEQ_TYPE_GAMCROSS: rval.init = init_gammacross; rval.load = load_gammacross; rval.free = free_gammacross; @@ -3000,30 +3000,30 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.get_default_fac = get_default_fac_fade; rval.execute = do_gammacross_effect; break; - case SEQ_ADD: + case SEQ_TYPE_ADD: rval.execute = do_add_effect; rval.early_out = early_out_mul_input2; break; - case SEQ_SUB: + case SEQ_TYPE_SUB: rval.execute = do_sub_effect; rval.early_out = early_out_mul_input2; break; - case SEQ_MUL: + case SEQ_TYPE_MUL: rval.execute = do_mul_effect; rval.early_out = early_out_mul_input2; break; - case SEQ_ALPHAOVER: + case SEQ_TYPE_ALPHAOVER: rval.init = init_alpha_over_or_under; rval.execute = do_alphaover_effect; break; - case SEQ_OVERDROP: + case SEQ_TYPE_OVERDROP: rval.execute = do_overdrop_effect; break; - case SEQ_ALPHAUNDER: + case SEQ_TYPE_ALPHAUNDER: rval.init = init_alpha_over_or_under; rval.execute = do_alphaunder_effect; break; - case SEQ_WIPE: + case SEQ_TYPE_WIPE: rval.init = init_wipe_effect; rval.num_inputs = num_inputs_wipe; rval.free = free_wipe_effect; @@ -3032,21 +3032,21 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.get_default_fac = get_default_fac_fade; rval.execute = do_wipe_effect; break; - case SEQ_GLOW: + case SEQ_TYPE_GLOW: rval.init = init_glow_effect; rval.num_inputs = num_inputs_glow; rval.free = free_glow_effect; rval.copy = copy_glow_effect; rval.execute = do_glow_effect; break; - case SEQ_TRANSFORM: + case SEQ_TYPE_TRANSFORM: rval.init = init_transform_effect; rval.num_inputs = num_inputs_transform; rval.free = free_transform_effect; rval.copy = copy_transform_effect; rval.execute = do_transform_effect; break; - case SEQ_SPEED: + case SEQ_TYPE_SPEED: rval.init = init_speed_effect; rval.num_inputs = num_inputs_speed; rval.load = load_speed_effect; @@ -3056,7 +3056,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.early_out = early_out_speed; rval.store_icu_yrange = store_icu_yrange_speed; break; - case SEQ_COLOR: + case SEQ_TYPE_COLOR: rval.init = init_solid_color; rval.num_inputs = num_inputs_color; rval.early_out = early_out_color; @@ -3064,12 +3064,12 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) rval.copy = copy_solid_color; rval.execute = do_solid_color; break; - case SEQ_MULTICAM: + case SEQ_TYPE_MULTICAM: rval.num_inputs = num_inputs_multicam; rval.early_out = early_out_multicam; rval.execute = do_multicam; break; - case SEQ_ADJUSTMENT: + case SEQ_TYPE_ADJUSTMENT: rval.num_inputs = num_inputs_adjustment; rval.early_out = early_out_adjustment; rval.execute = do_adjustment; @@ -3084,7 +3084,7 @@ struct SeqEffectHandle get_sequence_effect(Sequence *seq) { struct SeqEffectHandle rval = {NULL}; - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { rval = get_sequence_effect_impl(seq->type); if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) { rval.load(seq); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5318c5514ca..699e0b1cd97 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -178,7 +178,7 @@ void seq_free_sequence(Scene *scene, Sequence *seq) if (seq->anim) IMB_free_anim(seq->anim); - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { struct SeqEffectHandle sh = get_sequence_effect(seq); sh.free(seq); @@ -195,7 +195,7 @@ void seq_free_sequence(Scene *scene, Sequence *seq) if (ed->act_seq == seq) ed->act_seq = NULL; - if (seq->scene_sound && ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) + if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) sound_remove_scene_sound(scene, seq->scene_sound); seq_free_animdata(scene, seq); @@ -543,10 +543,10 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase /* for sound we go over full meta tree to update bounds of the sound strips, * since sound is played outside of evaluating the imbufs, */ for (seq = metaseq->seqbase.first; seq; seq = seq->next) { - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { seq_update_sound_bounds_recursive_rec(scene, seq, MAX2(start, metaseq_start(seq)), MIN2(end, metaseq_end(seq))); } - else if (ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) { + else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { if (seq->scene_sound) { int startofs = seq->startofs; int endofs = seq->endofs; @@ -582,10 +582,10 @@ void calc_sequence_disp(Scene *scene, Sequence *seq) seq->handsize = (float)((seq->enddisp - seq->startdisp) / 25); } - if (ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) { + if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { seq_update_sound_bounds(scene, seq); } - else if (seq->type == SEQ_META) + else if (seq->type == SEQ_TYPE_META) seq_update_sound_bounds_recursive(scene, seq); } @@ -603,7 +603,7 @@ void calc_sequence(Scene *scene, Sequence *seq) /* effects and meta: automatic start and end */ - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { /* pointers */ if (seq->seq2 == NULL) seq->seq2 = seq->seq1; if (seq->seq3 == NULL) seq->seq3 = seq->seq1; @@ -641,7 +641,7 @@ void calc_sequence(Scene *scene, Sequence *seq) } } else { - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { seqm = seq->seqbase.first; if (seqm) { min = MAXFRAME * 2; @@ -669,7 +669,10 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) int prev_startdisp = 0, prev_enddisp = 0; /* note: don't rename the strip, will break animation curves */ - if (ELEM6(seq->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_SCENE, SEQ_META, SEQ_MOVIECLIP) == 0) { + if (ELEM6(seq->type, + SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, + SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP) == 0) + { return; } @@ -681,7 +684,7 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) } switch (seq->type) { - case SEQ_IMAGE: + case SEQ_TYPE_IMAGE: { /* Hack? */ size_t olen = MEM_allocN_len(seq->strip->stripdata) / sizeof(struct StripElem); @@ -694,7 +697,7 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) } break; } - case SEQ_MOVIE: + case SEQ_TYPE_MOVIE: BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(str, G.main->name); @@ -719,7 +722,7 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) seq->len = 0; } break; - case SEQ_MOVIECLIP: + case SEQ_TYPE_MOVIECLIP: seq->len = BKE_movieclip_get_duration(seq->clip); seq->len -= seq->anim_startofs; @@ -728,7 +731,7 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) seq->len = 0; } break; - case SEQ_SOUND: + case SEQ_TYPE_SOUND_RAM: #ifdef WITH_AUDASPACE if (!seq->sound) return; @@ -742,7 +745,7 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) return; #endif break; - case SEQ_SCENE: + case SEQ_TYPE_SCENE: { seq->len = (seq->scene) ? seq->scene->r.efra - seq->scene->r.sfra + 1 : 0; seq->len -= seq->anim_startofs; @@ -781,7 +784,7 @@ void BKE_sequencer_sort(Scene *scene) while ( (seq = ed->seqbasep->first) ) { BLI_remlink(ed->seqbasep, seq); - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { seqt = effbase.first; while (seqt) { if (seqt->machine >= seq->machine) { @@ -895,27 +898,27 @@ void seqbase_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq) static const char *give_seqname_by_type(int type) { switch (type) { - case SEQ_META: return "Meta"; - case SEQ_IMAGE: return "Image"; - case SEQ_SCENE: return "Scene"; - case SEQ_MOVIE: return "Movie"; - case SEQ_MOVIECLIP: return "Clip"; - case SEQ_SOUND: return "Audio"; - case SEQ_CROSS: return "Cross"; - case SEQ_GAMCROSS: return "Gamma Cross"; - case SEQ_ADD: return "Add"; - case SEQ_SUB: return "Sub"; - case SEQ_MUL: return "Mul"; - case SEQ_ALPHAOVER: return "Alpha Over"; - case SEQ_ALPHAUNDER: return "Alpha Under"; - case SEQ_OVERDROP: return "Over Drop"; - case SEQ_WIPE: return "Wipe"; - case SEQ_GLOW: return "Glow"; - case SEQ_TRANSFORM: return "Transform"; - case SEQ_COLOR: return "Color"; - case SEQ_MULTICAM: return "Multicam"; - case SEQ_ADJUSTMENT: return "Adjustment"; - case SEQ_SPEED: return "Speed"; + case SEQ_TYPE_META: return "Meta"; + case SEQ_TYPE_IMAGE: return "Image"; + case SEQ_TYPE_SCENE: return "Scene"; + case SEQ_TYPE_MOVIE: return "Movie"; + case SEQ_TYPE_MOVIECLIP: return "Clip"; + case SEQ_TYPE_SOUND_RAM: return "Audio"; + case SEQ_TYPE_CROSS: return "Cross"; + case SEQ_TYPE_GAMCROSS: return "Gamma Cross"; + case SEQ_TYPE_ADD: return "Add"; + case SEQ_TYPE_SUB: return "Sub"; + case SEQ_TYPE_MUL: return "Mul"; + case SEQ_TYPE_ALPHAOVER: return "Alpha Over"; + case SEQ_TYPE_ALPHAUNDER: return "Alpha Under"; + case SEQ_TYPE_OVERDROP: return "Over Drop"; + case SEQ_TYPE_WIPE: return "Wipe"; + case SEQ_TYPE_GLOW: return "Glow"; + case SEQ_TYPE_TRANSFORM: return "Transform"; + case SEQ_TYPE_COLOR: return "Color"; + case SEQ_TYPE_MULTICAM: return "Multicam"; + case SEQ_TYPE_ADJUSTMENT: return "Adjustment"; + case SEQ_TYPE_SPEED: return "Speed"; default: return NULL; } @@ -926,7 +929,7 @@ const char *give_seqname(Sequence *seq) const char *name = give_seqname_by_type(seq->type); if (!name) { - if (seq->type < SEQ_EFFECT) { + if (seq->type < SEQ_TYPE_EFFECT) { return seq->strip->dir; } else { @@ -1008,7 +1011,7 @@ static float give_stripelem_index(Sequence *seq, float cfra) int sta = seq->start; int end = seq->start + seq->len - 1; - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { end = seq->enddisp; } @@ -1041,7 +1044,7 @@ StripElem *give_stripelem(Sequence *seq, int cfra) { StripElem *se = seq->strip->stripdata; - if (seq->type == SEQ_IMAGE) { /* only + if (seq->type == SEQ_TYPE_IMAGE) { /* only * IMAGE strips use the whole array, * MOVIE strips use only * the first element, all other strips @@ -1085,7 +1088,7 @@ int evaluate_seq_frame(Scene *scene, int cfra) static int video_seq_is_rendered(Sequence *seq) { - return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_SOUND); + return (seq && !(seq->flag & SEQ_MUTE) && seq->type != SEQ_TYPE_SOUND_RAM); } static int get_shown_sequences(ListBase *seqbasep, int cfra, int chanshown, Sequence **seq_arr_out) @@ -1231,7 +1234,7 @@ static int seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *n if (seq->flag & (SEQ_USE_PROXY_CUSTOM_DIR | SEQ_USE_PROXY_CUSTOM_FILE)) { BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir)); } - else if (seq->type == SEQ_IMAGE) { + else if (seq->type == SEQ_TYPE_IMAGE) { BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir); } else { @@ -1248,7 +1251,7 @@ static int seq_proxy_get_fname(Sequence *seq, int cfra, int render_size, char *n /* generate a separate proxy directory for each preview size */ - if (seq->type == SEQ_IMAGE) { + if (seq->type == SEQ_TYPE_IMAGE) { BLI_snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", dir, render_size, give_stripelem(seq, cfra)->name); @@ -1393,7 +1396,7 @@ struct SeqIndexBuildContext *seq_proxy_rebuild_context(Main *bmain, Scene *scene context->orig_seq = seq; context->seq = nseq; - if (nseq->type == SEQ_MOVIE) { + if (nseq->type == SEQ_TYPE_MOVIE) { seq_open_anim_file(nseq); if (nseq->anim) { @@ -1412,7 +1415,7 @@ void seq_proxy_rebuild(SeqIndexBuildContext *context, short *stop, short *do_upd Scene *scene = context->scene; int cfra; - if (seq->type == SEQ_MOVIE) { + if (seq->type == SEQ_TYPE_MOVIE) { if (context->index_context) { IMB_anim_index_rebuild(context->index_context, stop, do_update, progress); } @@ -1642,7 +1645,7 @@ static void color_balance(Sequence *seq, ImBuf *ibuf, float mul) } /* - * input preprocessing for SEQ_IMAGE, SEQ_MOVIE, SEQ_MOVIECLIP and SEQ_SCENE + * input preprocessing for SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP and SEQ_TYPE_SCENE * * Do all the things you can't really do afterwards using sequence effects * (read: before rescaling to render resolution has been done) @@ -1696,7 +1699,7 @@ static ImBuf *input_preprocess( ibuf = IMB_makeSingleUser(ibuf); if ((seq->flag & SEQ_FILTERY) && - !ELEM(seq->type, SEQ_MOVIE, SEQ_MOVIECLIP)) + !ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP)) { IMB_filtery(ibuf); } @@ -2126,7 +2129,8 @@ static ImBuf *seq_render_scene_strip( if (sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (scene == context.scene || have_seq == 0) && camera) { char err_out[256] = "unknown"; - /* for old scened this can be uninitialized, should probably be added to do_versions at some point if the functionality stays */ + /* for old scened this can be uninitialized, + * should probably be added to do_versions at some point if the functionality stays */ if (context.scene->r.seq_prev_type == 0) context.scene->r.seq_prev_type = 3 /* ==OB_SOLID */; @@ -2204,8 +2208,8 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) int is_proxy_image = FALSE; float nr = give_stripelem_index(seq, cfra); /* all effects are handled similarly with the exception of speed effect */ - int type = (seq->type & SEQ_EFFECT && seq->type != SEQ_SPEED) ? SEQ_EFFECT : seq->type; - int is_preprocessed = !ELEM3(type, SEQ_IMAGE, SEQ_MOVIE, SEQ_SCENE); + int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type; + int is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE); ibuf = seq_stripelem_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); @@ -2218,13 +2222,13 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) ibuf = copy_from_ibuf_still(context, seq, nr); /* MOVIECLIPs have their own proxy management */ - if (ibuf == NULL && seq->type != SEQ_MOVIECLIP) { + if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { ibuf = seq_proxy_fetch(context, seq, cfra); is_proxy_image = (ibuf != NULL); } if (ibuf == NULL) switch (type) { - case SEQ_META: + case SEQ_TYPE_META: { ImBuf *meta_ibuf = NULL; @@ -2246,7 +2250,7 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) break; } - case SEQ_SPEED: + case SEQ_TYPE_SPEED: { ImBuf *child_ibuf = NULL; @@ -2272,13 +2276,13 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) } break; } - case SEQ_EFFECT: + case SEQ_TYPE_EFFECT: { ibuf = seq_render_effect_strip_impl( context, seq, seq->start + nr); break; } - case SEQ_IMAGE: + case SEQ_TYPE_IMAGE: { StripElem *s_elem = give_stripelem(seq, cfra); @@ -2303,7 +2307,7 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) } break; } - case SEQ_MOVIE: + case SEQ_TYPE_MOVIE: { seq_open_anim_file(seq); @@ -2330,7 +2334,7 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) copy_to_ibuf_still(context, seq, nr, ibuf); break; } - case SEQ_SCENE: + case SEQ_TYPE_SCENE: { // scene can be NULL after deletions ibuf = seq_render_scene_strip(context, seq, nr); @@ -2340,7 +2344,7 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) copy_to_ibuf_still(context, seq, nr, ibuf); break; } - case SEQ_MOVIECLIP: + case SEQ_TYPE_MOVIECLIP: { ibuf = seq_render_movieclip_strip(context, seq, nr); @@ -2383,7 +2387,7 @@ static int seq_must_swap_input_in_blend_mode(Sequence *seq) /* bad hack, to fix crazy input ordering of * those two effects */ - if (ELEM3(seq->blend_mode, SEQ_ALPHAOVER, SEQ_ALPHAUNDER, SEQ_OVERDROP)) { + if (ELEM3(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) { swap_input = TRUE; } @@ -2567,7 +2571,7 @@ ImBuf *give_ibuf_seq_direct(SeqRenderData context, float cfra, Sequence *seq) /* check used when we need to change seq->blend_mode but not to effect or audio strips */ static int seq_can_blend(Sequence *seq) { - if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { + if (ELEM4(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE)) { return 1; } else { @@ -2949,16 +2953,16 @@ void free_imbuf_seq(Scene *scene, ListBase *seqbase, int check_mem_usage, for (seq = seqbase->first; seq; seq = seq->next) { if (seq->strip) { - if (seq->type == SEQ_MOVIE && !keep_file_handles) + if (seq->type == SEQ_TYPE_MOVIE && !keep_file_handles) free_anim_seq(seq); - if (seq->type == SEQ_SPEED) { + if (seq->type == SEQ_TYPE_SPEED) { sequence_effect_speed_rebuild_map(scene, seq, 1); } } - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { free_imbuf_seq(scene, &seq->seqbase, FALSE, keep_file_handles); } - if (seq->type == SEQ_SCENE) { + if (seq->type == SEQ_TYPE_SCENE) { /* FIXME: recurs downwards, * but do recurs protection somehow! */ } @@ -2995,9 +2999,9 @@ static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *chan if (free_imbuf) { if (ibuf_change) { - if (seq->type == SEQ_MOVIE) + if (seq->type == SEQ_TYPE_MOVIE) free_anim_seq(seq); - if (seq->type == SEQ_SPEED) { + if (seq->type == SEQ_TYPE_SPEED) { sequence_effect_speed_rebuild_map(scene, seq, 1); } } @@ -3086,8 +3090,8 @@ void seq_tx_set_final_right(Sequence *seq, int val) int seq_single_check(Sequence *seq) { return ((seq->len == 1) && - (seq->type == SEQ_IMAGE || - ((seq->type & SEQ_EFFECT) && + (seq->type == SEQ_TYPE_IMAGE || + ((seq->type & SEQ_TYPE_EFFECT) && get_sequence_effect_num_inputs(seq->type) == 0))); } @@ -3110,7 +3114,7 @@ int seqbase_isolated_sel_check(ListBase *seqbase) /* test relationships */ for (seq = seqbase->first; seq; seq = seq->next) { - if ((seq->type & SEQ_EFFECT) == 0) + if ((seq->type & SEQ_TYPE_EFFECT) == 0) continue; if (seq->flag & SELECT) { @@ -3173,7 +3177,7 @@ void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) } /* sounds cannot be extended past their endpoints */ - if (seq->type == SEQ_SOUND) { + if (seq->type == SEQ_TYPE_SOUND_RAM) { seq->startstill = 0; seq->endstill = 0; } @@ -3199,7 +3203,7 @@ void seq_single_fix(Sequence *seq) int seq_tx_test(Sequence *seq) { - return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0); + return (seq->type < SEQ_TYPE_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0); } static int seq_overlap(Sequence *seq1, Sequence *seq2) @@ -3228,7 +3232,7 @@ void seq_translate(Scene *evil_scene, Sequence *seq, int delta) seq_offset_animdata(evil_scene, seq, delta); seq->start += delta; - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { Sequence *seq_child; for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { seq_translate(evil_scene, seq_child, delta); @@ -3240,7 +3244,7 @@ void seq_translate(Scene *evil_scene, Sequence *seq, int delta) void seq_sound_init(Scene *scene, Sequence *seq) { - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { Sequence *seq_child; for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) { seq_sound_init(scene, seq_child); @@ -3268,7 +3272,7 @@ Sequence *seq_foreground_frame_get(Scene *scene, int frame) if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame) continue; /* only use elements you can see - not */ - if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) { + if (ELEM5(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) { if (seq->machine > best_machine) { best_seq = seq; best_machine = seq->machine; @@ -3394,10 +3398,10 @@ void seq_update_sound_bounds_all(Scene *scene) Sequence *seq; for (seq = ed->seqbase.first; seq; seq = seq->next) { - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { seq_update_sound_bounds_recursive(scene, seq); } - else if (ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) { + else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { seq_update_sound_bounds(scene, seq); } } @@ -3420,7 +3424,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i for (seq = seqbasep->first; seq; seq = seq->next) { seqmute = (mute || (seq->flag & SEQ_MUTE)); - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { /* if this is the current meta sequence, unmute because * all sequences above this were set to mute */ if (seq == metaseq) @@ -3428,7 +3432,7 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute); } - else if (ELEM(seq->type, SEQ_SOUND, SEQ_SCENE)) { + else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { if (seq->scene_sound) { sound_mute_scene_sound(seq->scene_sound, seqmute); } @@ -3454,10 +3458,10 @@ static void seq_update_sound_recursive(Scene *scene, ListBase *seqbasep, bSound Sequence *seq; for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { seq_update_sound_recursive(scene, &seq->seqbase, sound); } - else if (seq->type == SEQ_SOUND) { + else if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->scene_sound && sound == seq->sound) { sound_update_scene_sound(seq->scene_sound, sound); } @@ -3521,18 +3525,18 @@ int seq_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) /* type checking, could be more advanced but disalow sound vs non-sound copy */ if (seq_a->type != seq_b->type) { - if (seq_a->type == SEQ_SOUND || seq_b->type == SEQ_SOUND) { + if (seq_a->type == SEQ_TYPE_SOUND_RAM || seq_b->type == SEQ_TYPE_SOUND_RAM) { *error_str = "Strips were not compatible"; return 0; } /* disallow effects to swap with non-effects strips */ - if ((seq_a->type & SEQ_EFFECT) != (seq_b->type & SEQ_EFFECT)) { + if ((seq_a->type & SEQ_TYPE_EFFECT) != (seq_b->type & SEQ_TYPE_EFFECT)) { *error_str = "Strips were not compatible"; return 0; } - if ((seq_a->type & SEQ_EFFECT) && (seq_b->type & SEQ_EFFECT)) { + if ((seq_a->type & SEQ_TYPE_EFFECT) && (seq_b->type & SEQ_TYPE_EFFECT)) { if (get_sequence_effect_num_inputs(seq_a->type) != get_sequence_effect_num_inputs(seq_b->type)) { *error_str = "Strips must have the same number of inputs"; return 0; @@ -3769,8 +3773,8 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo Strip *strip; seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - seq->type = SEQ_IMAGE; - seq->blend_mode = SEQ_CROSS; /* so alpha adjustment fade to the strip below */ + seq->type = SEQ_TYPE_IMAGE; + seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); @@ -3818,7 +3822,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - seq->type = SEQ_SOUND; + seq->type = SEQ_TYPE_SOUND_RAM; seq->sound = sound; BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2); seqbase_unique_name_recursive(&scene->ed->seqbase, seq); @@ -3874,8 +3878,8 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo return NULL; seq = alloc_sequence(seqbasep, seq_load->start_frame, seq_load->channel); - seq->type = SEQ_MOVIE; - seq->blend_mode = SEQ_CROSS; /* so alpha adjustment fade to the strip below */ + seq->type = SEQ_TYPE_MOVIE; + seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ seq->anim = an; seq->anim_preseek = IMB_anim_get_preseek(an); @@ -3942,24 +3946,24 @@ static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence seqn->strip->color_balance = MEM_dupallocN(seq->strip->color_balance); } - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { seqn->strip->stripdata = NULL; seqn->seqbase.first = seqn->seqbase.last = NULL; /* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */ /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/ } - else if (seq->type == SEQ_SCENE) { + else if (seq->type == SEQ_TYPE_SCENE) { seqn->strip->stripdata = NULL; if (seq->scene_sound) seqn->scene_sound = sound_scene_add_scene_sound_defaults(sce_audio, seqn); } - else if (seq->type == SEQ_MOVIE) { + else if (seq->type == SEQ_TYPE_MOVIE) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); seqn->anim = NULL; } - else if (seq->type == SEQ_SOUND) { + else if (seq->type == SEQ_TYPE_SOUND_RAM) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); if (seq->scene_sound) @@ -3967,16 +3971,16 @@ static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence seqn->sound->id.us++; } - else if (seq->type == SEQ_IMAGE) { + else if (seq->type == SEQ_TYPE_IMAGE) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); } - else if (seq->type >= SEQ_EFFECT) { + else if (seq->type >= SEQ_TYPE_EFFECT) { if (seq->seq1 && seq->seq1->tmp) seqn->seq1 = seq->seq1->tmp; if (seq->seq2 && seq->seq2->tmp) seqn->seq2 = seq->seq2->tmp; if (seq->seq3 && seq->seq3->tmp) seqn->seq3 = seq->seq3->tmp; - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { struct SeqEffectHandle sh; sh = get_sequence_effect(seq); if (sh.copy) @@ -4004,7 +4008,7 @@ static Sequence *seq_dupli(struct Scene *scene, struct Scene *scene_to, Sequence Sequence *seq_dupli_recursive(struct Scene *scene, struct Scene *scene_to, Sequence *seq, int dupe_flag) { Sequence *seqn = seq_dupli(scene, scene_to, seq, dupe_flag); - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { Sequence *s; for (s = seq->seqbase.first; s; s = s->next) { Sequence *n = seq_dupli_recursive(scene, scene_to, s, dupe_flag); @@ -4033,7 +4037,7 @@ void seqbase_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, } BLI_addtail(nseqbase, seqn); - if (seq->type == SEQ_META) + if (seq->type == SEQ_TYPE_META) seqbase_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag); if (dupe_flag & SEQ_DUPE_CONTEXT) { diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index e6c51ca0786..f458c158fb2 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -508,11 +508,11 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int SEQ_BEGIN(scene->ed, seq) { if (SEQ_HAS_PATH(seq)) { - if (ELEM(seq->type, SEQ_MOVIE, SEQ_SOUND)) { + if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM)) { rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name, visit_cb, absbase, bpath_user_data); } - else if (seq->type == SEQ_IMAGE) { + else if (seq->type == SEQ_TYPE_IMAGE) { /* might want an option not to loop over all strips */ StripElem *se = seq->strip->stripdata; int len = MEM_allocN_len(se) / sizeof(*se); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cdf344beb4d..cce38ff1d90 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4831,8 +4831,8 @@ static void lib_link_scene(FileData *fd, Main *main) if (seq->scene_camera) seq->scene_camera = newlibadr(fd, sce->id.lib, seq->scene_camera); if (seq->sound) { seq->scene_sound = NULL; - if (seq->type == SEQ_HD_SOUND) - seq->type = SEQ_SOUND; + if (seq->type == SEQ_TYPE_SOUND_HD) + seq->type = SEQ_TYPE_SOUND_RAM; else seq->sound = newlibadr(fd, sce->id.lib, seq->sound); if (seq->sound) { @@ -4957,10 +4957,10 @@ static void direct_link_scene(FileData *fd, Scene *sce) seq->effectdata = newdataadr(fd, seq->effectdata); - if (seq->type & SEQ_EFFECT) + if (seq->type & SEQ_TYPE_EFFECT) seq->flag |= SEQ_EFFECT_NOT_LOADED; - if (seq->type == SEQ_SPEED) { + if (seq->type == SEQ_TYPE_SPEED) { SpeedControlVars *s = seq->effectdata; s->frameMap = NULL; } @@ -4969,7 +4969,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) if (seq->strip && seq->strip->done==0) { seq->strip->done = TRUE; - if (ELEM4(seq->type, SEQ_IMAGE, SEQ_MOVIE, SEQ_RAM_SOUND, SEQ_HD_SOUND)) { + if (ELEM4(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { seq->strip->stripdata = newdataadr(fd, seq->strip->stripdata); } else { diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 620d15993a1..5ed39ad5307 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -744,7 +744,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) if (scene->ed && scene->ed->seqbasep) { SEQ_BEGIN (scene->ed, seq) { - if (seq->type == SEQ_HD_SOUND) { + if (seq->type == SEQ_TYPE_SOUND_HD) { char str[FILE_MAX]; BLI_join_dirfile(str, sizeof(str), seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(str, main->name); diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 7b314c31488..46ef2716ade 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1842,7 +1842,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) if (ed) { SEQ_BEGIN (sce->ed, seq) { - if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) + if (seq->type == SEQ_TYPE_IMAGE || seq->type == SEQ_TYPE_MOVIE) seq->flag |= SEQ_MAKE_PREMUL; } SEQ_END diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 655adf97b04..f257994bc1c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2153,19 +2153,19 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if (seq->effectdata) { switch (seq->type) { - case SEQ_COLOR: + case SEQ_TYPE_COLOR: writestruct(wd, DATA, "SolidColorVars", 1, seq->effectdata); break; - case SEQ_SPEED: + case SEQ_TYPE_SPEED: writestruct(wd, DATA, "SpeedControlVars", 1, seq->effectdata); break; - case SEQ_WIPE: + case SEQ_TYPE_WIPE: writestruct(wd, DATA, "WipeVars", 1, seq->effectdata); break; - case SEQ_GLOW: + case SEQ_TYPE_GLOW: writestruct(wd, DATA, "GlowVars", 1, seq->effectdata); break; - case SEQ_TRANSFORM: + case SEQ_TYPE_TRANSFORM: writestruct(wd, DATA, "TransformVars", 1, seq->effectdata); break; } @@ -2185,9 +2185,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if (seq->flag & SEQ_USE_COLOR_BALANCE && strip->color_balance) { writestruct(wd, DATA, "StripColorBalance", 1, strip->color_balance); } - if (seq->type==SEQ_IMAGE) + if (seq->type==SEQ_TYPE_IMAGE) writestruct(wd, DATA, "StripElem", MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), strip->stripdata); - else if (seq->type==SEQ_MOVIE || seq->type==SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) + else if (seq->type==SEQ_TYPE_MOVIE || seq->type==SEQ_TYPE_SOUND_RAM || seq->type == SEQ_TYPE_SOUND_HD) writestruct(wd, DATA, "StripElem", 1, strip->stripdata); strip->done = TRUE; diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index af7f3bd4aed..9827ffdc324 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -676,7 +676,7 @@ static int sound_poll(bContext *C) { Editing *ed = CTX_data_scene(C)->ed; - if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_SOUND) + if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) return 0; return 1; @@ -689,7 +689,7 @@ static int sound_pack_exec(bContext *C, wmOperator *op) Editing *ed = CTX_data_scene(C)->ed; bSound *sound; - if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_SOUND) + if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) return OPERATOR_CANCELLED; sound = ed->act_seq->sound; @@ -751,7 +751,7 @@ static int sound_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even if (RNA_struct_property_is_set(op->ptr, "id")) return sound_unpack_exec(C, op); - if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_SOUND) + if (!ed || !ed->act_seq || ed->act_seq->type != SEQ_TYPE_SOUND_RAM) return OPERATOR_CANCELLED; sound = ed->act_seq->sound; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 483016b7e00..f0ecaf3ab2c 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1057,15 +1057,15 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto case TSE_POSEGRP_BASE: UI_icon_draw(x, y, ICON_GROUP_BONE); break; case TSE_SEQUENCE: - if (te->idcode == SEQ_MOVIE) + if (te->idcode == SEQ_TYPE_MOVIE) UI_icon_draw(x, y, ICON_SEQUENCE); - else if (te->idcode == SEQ_META) + else if (te->idcode == SEQ_TYPE_META) UI_icon_draw(x, y, ICON_DOT); - else if (te->idcode == SEQ_SCENE) + else if (te->idcode == SEQ_TYPE_SCENE) UI_icon_draw(x, y, ICON_SCENE); - else if (te->idcode == SEQ_SOUND) + else if (te->idcode == SEQ_TYPE_SOUND_RAM) UI_icon_draw(x, y, ICON_SOUND); - else if (te->idcode == SEQ_IMAGE) + else if (te->idcode == SEQ_TYPE_IMAGE) UI_icon_draw(x, y, ICON_IMAGE_COL); else UI_icon_draw(x, y, ICON_PARTICLES); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index ff3648fc2b8..63907f530eb 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -899,14 +899,14 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->directdata = seq; te->name = seq->name + 2; - if (seq->type < SEQ_EFFECT) { + if (seq->type < SEQ_TYPE_EFFECT) { /* * This work like the sequence. * If the sequence have a name (not default name) * show it, in other case put the filename. */ - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { p = seq->seqbase.first; while (p) { outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 9eb4c62789e..9301f13c8c0 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -228,8 +228,8 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) } seq = alloc_sequence(ed->seqbasep, start_frame, channel); - seq->type = SEQ_SCENE; - seq->blend_mode = SEQ_CROSS; /* so alpha adjustment fade to the strip below */ + seq->type = SEQ_TYPE_SCENE; + seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ seq->scene = sce_seq; @@ -327,8 +327,8 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) } seq = alloc_sequence(ed->seqbasep, start_frame, channel); - seq->type = SEQ_MOVIECLIP; - seq->blend_mode = SEQ_CROSS; + seq->type = SEQ_TYPE_MOVIECLIP; + seq->blend_mode = SEQ_TYPE_CROSS; seq->clip = clip; if (seq->clip->id.us == 0) @@ -740,14 +740,14 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); strip->us = 1; - if (seq->type == SEQ_COLOR) { + if (seq->type == SEQ_TYPE_COLOR) { SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; RNA_float_get_array(op->ptr, "color", colvars->col); - seq->blend_mode = SEQ_CROSS; /* so alpha adjustment fade to the strip below */ + seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */ } - else if (seq->type == SEQ_ADJUSTMENT) { - seq->blend_mode = SEQ_CROSS; + else if (seq->type == SEQ_TYPE_ADJUSTMENT) { + seq->blend_mode = SEQ_TYPE_CROSS; } /* an unset channel is a special case where we automatically go above @@ -832,6 +832,6 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot) WM_operator_properties_filesel(ot, 0, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); - RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type"); + RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type"); RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", "Initialize the strip with this color (only used when type='COLOR')", 0.0f, 1.0f); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 236baea01be..cb15eed6a37 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -82,23 +82,23 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[ SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; switch (seq->type) { - case SEQ_IMAGE: + case SEQ_TYPE_IMAGE: UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col); break; - case SEQ_META: + case SEQ_TYPE_META: UI_GetThemeColor3ubv(TH_SEQ_META, col); break; - case SEQ_MOVIE: + case SEQ_TYPE_MOVIE: UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col); break; - case SEQ_MOVIECLIP: + case SEQ_TYPE_MOVIECLIP: UI_GetThemeColor3ubv(TH_SEQ_MOVIECLIP, col); break; - case SEQ_SCENE: + case SEQ_TYPE_SCENE: UI_GetThemeColor3ubv(TH_SEQ_SCENE, col); if (seq->scene == curscene) { @@ -107,45 +107,45 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[ break; /* transitions */ - case SEQ_CROSS: - case SEQ_GAMCROSS: - case SEQ_WIPE: + case SEQ_TYPE_CROSS: + case SEQ_TYPE_GAMCROSS: + case SEQ_TYPE_WIPE: UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, col); /* slightly offset hue to distinguish different effects */ - if (seq->type == SEQ_CROSS) rgb_byte_set_hue_float_offset(col, 0.04); - if (seq->type == SEQ_GAMCROSS) rgb_byte_set_hue_float_offset(col, 0.08); - if (seq->type == SEQ_WIPE) rgb_byte_set_hue_float_offset(col, 0.12); + if (seq->type == SEQ_TYPE_CROSS) rgb_byte_set_hue_float_offset(col, 0.04); + if (seq->type == SEQ_TYPE_GAMCROSS) rgb_byte_set_hue_float_offset(col, 0.08); + if (seq->type == SEQ_TYPE_WIPE) rgb_byte_set_hue_float_offset(col, 0.12); break; /* effects */ - case SEQ_TRANSFORM: - case SEQ_SPEED: - case SEQ_ADD: - case SEQ_SUB: - case SEQ_MUL: - case SEQ_ALPHAOVER: - case SEQ_ALPHAUNDER: - case SEQ_OVERDROP: - case SEQ_GLOW: - case SEQ_MULTICAM: - case SEQ_ADJUSTMENT: + case SEQ_TYPE_TRANSFORM: + case SEQ_TYPE_SPEED: + case SEQ_TYPE_ADD: + case SEQ_TYPE_SUB: + case SEQ_TYPE_MUL: + case SEQ_TYPE_ALPHAOVER: + case SEQ_TYPE_ALPHAUNDER: + case SEQ_TYPE_OVERDROP: + case SEQ_TYPE_GLOW: + case SEQ_TYPE_MULTICAM: + case SEQ_TYPE_ADJUSTMENT: UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col); /* slightly offset hue to distinguish different effects */ - if (seq->type == SEQ_ADD) rgb_byte_set_hue_float_offset(col, 0.04); - else if (seq->type == SEQ_SUB) rgb_byte_set_hue_float_offset(col, 0.08); - else if (seq->type == SEQ_MUL) rgb_byte_set_hue_float_offset(col, 0.12); - else if (seq->type == SEQ_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16); - else if (seq->type == SEQ_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20); - else if (seq->type == SEQ_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24); - else if (seq->type == SEQ_GLOW) rgb_byte_set_hue_float_offset(col, 0.28); - else if (seq->type == SEQ_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36); - else if (seq->type == SEQ_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32); - else if (seq->type == SEQ_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40); + if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04); + else if (seq->type == SEQ_TYPE_SUB) rgb_byte_set_hue_float_offset(col, 0.08); + else if (seq->type == SEQ_TYPE_MUL) rgb_byte_set_hue_float_offset(col, 0.12); + else if (seq->type == SEQ_TYPE_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16); + else if (seq->type == SEQ_TYPE_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20); + else if (seq->type == SEQ_TYPE_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24); + else if (seq->type == SEQ_TYPE_GLOW) rgb_byte_set_hue_float_offset(col, 0.28); + else if (seq->type == SEQ_TYPE_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36); + else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32); + else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40); break; - case SEQ_COLOR: + case SEQ_TYPE_COLOR: if (colvars->col) { rgb_float_to_uchar(col, colvars->col); } @@ -154,7 +154,7 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[ } break; - case SEQ_SOUND: + case SEQ_TYPE_SOUND_RAM: UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col); blendcol[0] = blendcol[1] = blendcol[2] = 128; if (seq->flag & SEQ_MUTE) UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20); @@ -362,7 +362,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, float pixelx, short dire } /* draw! */ - if (seq->type < SEQ_EFFECT || + if (seq->type < SEQ_TYPE_EFFECT || get_sequence_effect_num_inputs(seq->type) == 0) { glEnable(GL_BLEND); @@ -409,7 +409,7 @@ static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq) unsigned char col[3], blendcol[3]; View2D *v2d = &ar->v2d; - if (seq->type >= SEQ_EFFECT) return; + if (seq->type >= SEQ_TYPE_EFFECT) return; x1 = seq->startdisp; x2 = seq->enddisp; @@ -521,10 +521,10 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float if (name[0] == '\0') name = give_seqname(seq); - if (seq->type == SEQ_META || seq->type == SEQ_ADJUSTMENT) { + if (seq->type == SEQ_TYPE_META || seq->type == SEQ_TYPE_ADJUSTMENT) { BLI_snprintf(str, sizeof(str), "%d | %s", seq->len, name); } - else if (seq->type == SEQ_SCENE) { + else if (seq->type == SEQ_TYPE_SCENE) { if (seq->scene) { if (seq->scene_camera) { BLI_snprintf(str, sizeof(str), "%d | %s: %s (%s)", @@ -540,7 +540,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float seq->len, name); } } - else if (seq->type == SEQ_MOVIECLIP) { + else if (seq->type == SEQ_TYPE_MOVIECLIP) { if (seq->clip && strcmp(name, seq->clip->id.name + 2) != 0) { BLI_snprintf(str, sizeof(str), "%d | %s: %s", seq->len, name, seq->clip->id.name + 2); @@ -550,19 +550,19 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float seq->len, name); } } - else if (seq->type == SEQ_MULTICAM) { + else if (seq->type == SEQ_TYPE_MULTICAM) { BLI_snprintf(str, sizeof(str), "Cam | %s: %d", name, seq->multicam_source); } - else if (seq->type == SEQ_IMAGE) { + else if (seq->type == SEQ_TYPE_IMAGE) { BLI_snprintf(str, sizeof(str), "%d | %s: %s%s", seq->len, name, seq->strip->dir, seq->strip->stripdata->name); } - else if (seq->type & SEQ_EFFECT) { + else if (seq->type & SEQ_TYPE_EFFECT) { BLI_snprintf(str, sizeof(str), "%d | %s", seq->len, name); } - else if (seq->type == SEQ_SOUND) { + else if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->sound) BLI_snprintf(str, sizeof(str), "%d | %s: %s", seq->len, name, seq->sound->name); @@ -570,7 +570,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float BLI_snprintf(str, sizeof(str), "%d | %s", seq->len, name); } - else if (seq->type == SEQ_MOVIE) { + else if (seq->type == SEQ_TYPE_MOVIE) { BLI_snprintf(str, sizeof(str), "%d | %s: %s%s", seq->len, name, seq->strip->dir, seq->strip->stripdata->name); } @@ -696,7 +696,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline x2 = seq->enddisp; /* draw sound wave */ - if (seq->type == SEQ_SOUND) { + if (seq->type == SEQ_TYPE_SOUND_RAM) { drawseqwave(scene, seq, x1, y1, x2, y2, (ar->v2d.cur.xmax - ar->v2d.cur.xmin) / ar->winx); } @@ -743,7 +743,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline glDisable(GL_LINE_STIPPLE); } - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { drawmeta_contents(scene, seq, x1, y1, x2, y2); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 072cfa00622..c686f8440a9 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -79,21 +79,21 @@ /* XXX */ /* RNA Enums, used in multiple files */ EnumPropertyItem sequencer_prop_effect_types[] = { - {SEQ_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"}, - {SEQ_ADD, "ADD", 0, "Add", "Add effect strip type"}, - {SEQ_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"}, - {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"}, - {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"}, - {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"}, - {SEQ_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"}, - {SEQ_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"}, - {SEQ_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"}, - {SEQ_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"}, - {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"}, - {SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"}, - {SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"}, - {SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, - {SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, + {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"}, + {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"}, + {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"}, + {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"}, + {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"}, + {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"}, + {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"}, + {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"}, + {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"}, + {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"}, + {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"}, + {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"}, + {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"}, + {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, + {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, {0, NULL, 0, NULL, NULL} }; @@ -478,7 +478,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - if (seq->type == SEQ_SOUND && get_sequence_effect_num_inputs(type) != 0) { + if (seq->type == SEQ_TYPE_SOUND_RAM && get_sequence_effect_num_inputs(type) != 0) { *error_str = "Can't apply effects to audio sequence strips"; return 0; } @@ -543,7 +543,7 @@ static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq) if (!seq) return NULL; - else if (!(seq->type & SEQ_EFFECT)) + else if (!(seq->type & SEQ_TYPE_EFFECT)) return ((seq->flag & SELECT) ? NULL : seq); else if (!(seq->flag & SELECT)) { /* try to find replacement for effect inputs */ @@ -584,7 +584,7 @@ static void recurs_del_seq_flag(Scene *scene, ListBase *lb, short flag, short de if ((seq->flag & flag) || deleteall) { BLI_remlink(lb, seq); if (seq == last_seq) BKE_sequencer_active_set(scene, NULL); - if (seq->type == SEQ_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1); + if (seq->type == SEQ_TYPE_META) recurs_del_seq_flag(scene, &seq->seqbase, flag, 1); seq_free_sequence(scene, seq); } seq = seqn; @@ -616,7 +616,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe) if ((seq->startstill) && (cutframe < seq->start)) { /* don't do funny things with METAs ... */ - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { skip_dup = TRUE; seq->startstill = seq->start - cutframe; } @@ -637,7 +637,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe) else if (((seq->start + seq->len) < cutframe) && (seq->endstill)) { seq->endstill -= seq->enddisp - cutframe; /* don't do funny things with METAs ... */ - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { skip_dup = TRUE; } } @@ -712,7 +712,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) if ((seq->startstill) && (cutframe < seq->start)) { /* don't do funny things with METAs ... */ - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { skip_dup = TRUE; seq->startstill = seq->start - cutframe; } @@ -731,7 +731,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) else if (((seq->start + seq->len) < cutframe) && (seq->endstill)) { seq->endstill -= seq->enddisp - cutframe; /* don't do funny things with METAs ... */ - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { skip_dup = TRUE; } } @@ -855,7 +855,7 @@ static void UNUSED_FUNCTION(touch_seq_files) (Scene * scene) SEQP_BEGIN (ed, seq) { if (seq->flag & SELECT) { - if (seq->type == SEQ_MOVIE) { + if (seq->type == SEQ_TYPE_MOVIE) { if (seq->strip && seq->strip->stripdata) { BLI_make_file_string(G.main->name, str, seq->strip->dir, seq->strip->stripdata->name); BLI_file_touch(seq->name); @@ -883,7 +883,7 @@ static void set_filter_seq(Scene *scene) SEQP_BEGIN (ed, seq) { if (seq->flag & SELECT) { - if (seq->type == SEQ_MOVIE) { + if (seq->type == SEQ_TYPE_MOVIE) { seq->flag |= SEQ_FILTERY; reload_sequence_new_file(scene, seq, FALSE); calc_sequence(scene, seq); @@ -1052,7 +1052,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) shuffle_seq(ed->seqbasep, seq, scene); } } - else if (seq->type & SEQ_EFFECT) { + else if (seq->type & SEQ_TYPE_EFFECT) { if (seq->seq1 && (seq->seq1->flag & SELECT)) calc_sequence(scene, seq); else if (seq->seq2 && (seq->seq2->flag & SELECT)) @@ -1368,7 +1368,7 @@ static int sequencer_effect_poll(bContext *C) if (ed) { Sequence *last_seq = BKE_sequencer_active_get(scene); - if (last_seq && (last_seq->type & SEQ_EFFECT)) { + if (last_seq && (last_seq->type & SEQ_TYPE_EFFECT)) { return 1; } } @@ -1626,7 +1626,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* for effects, try to find a replacement input */ for (seq = ed->seqbasep->first; seq; seq = seq->next) - if ((seq->type & SEQ_EFFECT) && !(seq->flag & SELECT)) + if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SELECT)) del_seq_find_replace_recurs(scene, seq); /* delete all selected strips */ @@ -1679,7 +1679,7 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op)) /* for effects, try to find a replacement input */ for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ((seq->type & SEQ_EFFECT) == 0 && (seq->flag & SELECT)) { + if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) { seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0; } } @@ -1692,7 +1692,7 @@ static int sequencer_offset_clear_exec(bContext *C, wmOperator *UNUSED(op)) } for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ((seq->type & SEQ_EFFECT) == 0 && (seq->flag & SELECT)) { + if ((seq->type & SEQ_TYPE_EFFECT) == 0 && (seq->flag & SELECT)) { if (seq_test_overlap(ed->seqbasep, seq)) { shuffle_seq(ed->seqbasep, seq, scene); } @@ -1737,7 +1737,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) seq = ed->seqbasep->first; /* poll checks this is valid */ while (seq) { - if ((seq->flag & SELECT) && (seq->type == SEQ_IMAGE) && (seq->len > 1)) { + if ((seq->flag & SELECT) && (seq->type == SEQ_TYPE_IMAGE) && (seq->len > 1)) { /* remove seq so overlap tests don't conflict, * see seq_free_sequence below for the real free'ing */ BLI_remlink(ed->seqbasep, seq); @@ -1755,7 +1755,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) BLI_addtail(ed->seqbasep, seq_new); seq_new->start = start_ofs; - seq_new->type = SEQ_IMAGE; + seq_new->type = SEQ_TYPE_IMAGE; seq_new->len = 1; seq_new->endstill = step - 1; @@ -1826,7 +1826,7 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op)) Sequence *last_seq = BKE_sequencer_active_get(scene); MetaStack *ms; - if (last_seq && last_seq->type == SEQ_META && last_seq->flag & SELECT) { + if (last_seq && last_seq->type == SEQ_TYPE_META && last_seq->flag & SELECT) { /* Enter Metastrip */ ms = MEM_mallocN(sizeof(MetaStack), "metastack"); BLI_addtail(&ed->metastack, ms); @@ -1904,7 +1904,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) seqm = alloc_sequence(ed->seqbasep, 1, 1); /* channel number set later */ strcpy(seqm->name + 2, "MetaStrip"); - seqm->type = SEQ_META; + seqm->type = SEQ_TYPE_META; seqm->flag = SELECT; seq = ed->seqbasep->first; @@ -1970,7 +1970,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); /* last_seq checks (ed == NULL) */ - if (last_seq == NULL || last_seq->type != SEQ_META) + if (last_seq == NULL || last_seq->type != SEQ_TYPE_META) return OPERATOR_CANCELLED; BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase); @@ -1983,7 +1983,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) /* emtpy meta strip, delete all effects depending on it */ for (seq = ed->seqbasep->first; seq; seq = seq->next) - if ((seq->type & SEQ_EFFECT) && seq_depends_on_meta(seq, last_seq)) + if ((seq->type & SEQ_TYPE_EFFECT) && seq_depends_on_meta(seq, last_seq)) seq->flag |= SEQ_FLAG_DELETE; recurs_del_seq_flag(scene, ed->seqbasep, SEQ_FLAG_DELETE, 0); @@ -2454,14 +2454,14 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op) // XXX - should be a generic function for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) { - if ((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { + if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { calc_sequence(scene, iseq); } } /* do this in a new loop since both effects need to be calculated first */ for (iseq = scene->ed->seqbasep->first; iseq; iseq = iseq->next) { - if ((iseq->type & SEQ_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { + if ((iseq->type & SEQ_TYPE_EFFECT) && (seq_is_parent(iseq, active_seq) || seq_is_parent(iseq, seq))) { /* this may now overlap */ if (seq_test_overlap(ed->seqbasep, iseq) ) { shuffle_seq(ed->seqbasep, iseq, scene); @@ -2512,16 +2512,16 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op)) if (active_seq->strip) { switch (active_seq->type) { - case SEQ_IMAGE: + case SEQ_TYPE_IMAGE: se = give_stripelem(active_seq, scene->r.cfra); break; - case SEQ_MOVIE: + case SEQ_TYPE_MOVIE: se = active_seq->strip->stripdata; break; - case SEQ_SCENE: - case SEQ_META: - case SEQ_RAM_SOUND: - case SEQ_HD_SOUND: + case SEQ_TYPE_SCENE: + case SEQ_TYPE_META: + case SEQ_TYPE_SOUND_RAM: + case SEQ_TYPE_SOUND_HD: default: break; } @@ -2559,7 +2559,7 @@ void SEQUENCER_OT_rendersize(wmOperatorType *ot) static void seq_copy_del_sound(Scene *scene, Sequence *seq) { - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { Sequence *iseq; for (iseq = seq->seqbase.first; iseq; iseq = iseq->next) { seq_copy_del_sound(scene, iseq); @@ -2900,7 +2900,7 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op) /* free previous effect and init new effect */ struct SeqEffectHandle sh; - if ((seq->type & SEQ_EFFECT) == 0) { + if ((seq->type & SEQ_TYPE_EFFECT) == 0) { return OPERATOR_CANCELLED; } @@ -2947,7 +2947,7 @@ void SEQUENCER_OT_change_effect_type(struct wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_CROSS, "Type", "Sequencer effect type"); + ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type"); } static int sequencer_change_path_exec(bContext *C, wmOperator *op) @@ -2958,7 +2958,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) Sequence *seq = BKE_sequencer_active_get(scene); const int is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); - if (seq->type == SEQ_IMAGE) { + if (seq->type == SEQ_TYPE_IMAGE) { char directory[FILE_MAX]; const int len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); StripElem *se; @@ -3028,7 +3028,7 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UN RNA_string_set(op->ptr, "directory", seq->strip->dir); /* set default display depending on seq type */ - if (seq->type == SEQ_IMAGE) { + if (seq->type == SEQ_TYPE_IMAGE) { RNA_boolean_set(op->ptr, "filter_movie", FALSE); } else { diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 3911ec0ef82..261bc575420 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -171,11 +171,11 @@ void ED_sequencer_select_sequence_single(Scene * scene, Sequence * seq, int dese BKE_sequencer_active_set(scene, seq); - if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) { + if ((seq->type == SEQ_TYPE_IMAGE) || (seq->type == SEQ_TYPE_MOVIE)) { if (seq->strip) BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR); } - else if (seq->type == SEQ_SOUND) { + else if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->strip) BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR); } @@ -409,13 +409,13 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) if (seq) { BKE_sequencer_active_set(scene, seq); - if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) { + if ((seq->type == SEQ_TYPE_IMAGE) || (seq->type == SEQ_TYPE_MOVIE)) { if (seq->strip) { BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR); } } else - if (seq->type == SEQ_SOUND) { + if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->strip) { BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR); } @@ -930,11 +930,11 @@ static EnumPropertyItem sequencer_prop_select_grouped_types[] = { {0, NULL, 0, NULL, NULL} }; -#define SEQ_IS_SOUND(_seq) ((_seq->type & SEQ_SOUND) && !(_seq->type & SEQ_EFFECT)) +#define SEQ_IS_SOUND(_seq) ((_seq->type & SEQ_TYPE_SOUND_RAM) && !(_seq->type & SEQ_TYPE_EFFECT)) -#define SEQ_IS_EFFECT(_seq) (_seq->type & SEQ_EFFECT) +#define SEQ_IS_EFFECT(_seq) (_seq->type & SEQ_TYPE_EFFECT) -#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_SCENE, SEQ_MOVIECLIP) || SEQ_HAS_PATH(_seq)) +#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP) || SEQ_HAS_PATH(_seq)) static short select_grouped_type(Editing *ed, Sequence *actseq) { @@ -1008,22 +1008,22 @@ static short select_grouped_data(Editing *ed, Sequence *actseq) } SEQ_END; } - else if (actseq->type == SEQ_SCENE) { + else if (actseq->type == SEQ_TYPE_SCENE) { Scene *sce = actseq->scene; SEQP_BEGIN (ed, seq) { - if (seq->type == SEQ_SCENE && seq->scene == sce) { + if (seq->type == SEQ_TYPE_SCENE && seq->scene == sce) { seq->flag |= SELECT; changed = TRUE; } } SEQ_END; } - else if (actseq->type == SEQ_MOVIECLIP) { + else if (actseq->type == SEQ_TYPE_MOVIECLIP) { MovieClip *clip = actseq->clip; SEQP_BEGIN (ed, seq) { - if (seq->type == SEQ_MOVIECLIP && seq->clip == clip) { + if (seq->type == SEQ_TYPE_MOVIECLIP && seq->clip == clip) { seq->flag |= SELECT; changed = TRUE; } @@ -1038,10 +1038,10 @@ static short select_grouped_effect(Editing *ed, Sequence *actseq) { Sequence *seq; short changed = FALSE; - short effects[SEQ_EFFECT_MAX + 1]; + short effects[SEQ_TYPE_EFFECT_MAX + 1]; int i; - for (i = 0; i <= SEQ_EFFECT_MAX; i++) + for (i = 0; i <= SEQ_TYPE_EFFECT_MAX; i++) effects[i] = FALSE; SEQP_BEGIN (ed, seq) @@ -1087,7 +1087,7 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq) { Sequence *seq = NULL; short changed = FALSE; - short is_audio = ((actseq->type == SEQ_META) || SEQ_IS_SOUND(actseq)); + short is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq)); int startdisp = actseq->startdisp; int enddisp = actseq->enddisp; int machine = actseq->machine; @@ -1109,7 +1109,7 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq) /* Ignore all seqs of incompatible types (audio vs video). */ if ((seq->flag & SELECT) || (seq->startdisp >= enddisp) || (seq->enddisp < startdisp) || (!is_audio && SEQ_IS_SOUND(seq)) || - (is_audio && !((seq->type == SEQ_META) || SEQ_IS_SOUND(seq)))) + (is_audio && !((seq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(seq)))) { continue; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 61dff466387..1d4257ea3d3 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2239,7 +2239,7 @@ void flushTransSeq(TransInfo *t) if ((seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */ seq->start= new_frame - tdsq->start_offset; #else - if (seq->type != SEQ_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */ + if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */ seq->start= new_frame - tdsq->start_offset; #endif if (seq->depth==0) { @@ -2282,7 +2282,7 @@ void flushTransSeq(TransInfo *t) /* calc all meta's then effects [#27953] */ for (seq = seqbasep->first; seq; seq = seq->next) { - if (seq->type == SEQ_META && seq->flag & SELECT) { + if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) { calc_sequence(t->scene, seq); } } @@ -3787,7 +3787,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count *count = 0; *flag = 0; } - else if (seq->type == SEQ_META) { + else if (seq->type == SEQ_TYPE_META) { /* for meta's we only ever need to extend their children, no matter what depth * just check the meta's are in the bounds */ @@ -3844,7 +3844,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count /* Recursive */ - if ((seq->type == SEQ_META) && ((seq->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) == 0)) { + if ((seq->type == SEQ_TYPE_META) && ((seq->flag & (SEQ_LEFTSEL|SEQ_RIGHTSEL)) == 0)) { /* if any handles are selected, don't recurse */ *recursive = TRUE; } @@ -3859,9 +3859,9 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count #ifdef SEQ_TX_NESTED_METAS *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL|SEQ_RIGHTSEL); *count = 1; /* ignore the selection for nested */ - *recursive = (seq->type == SEQ_META); + *recursive = (seq->type == SEQ_TYPE_META); #else - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { /* Meta's can only directly be moved between channels since they * don't have their start and length set directly (children affect that) * since this Meta is nested we don't need any of its data in fact. @@ -4064,7 +4064,7 @@ static void freeSeqData(TransInfo *t) seq= ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev)) { /* check effects strips, we cant change their time */ - if ((seq->type & SEQ_EFFECT) && seq->seq1) { + if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { has_effect= TRUE; } else { @@ -4123,7 +4123,7 @@ static void freeSeqData(TransInfo *t) for (a=0; atotal; a++, td++) { seq= ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev)) { - if ((seq->type & SEQ_EFFECT) && seq->seq1) { + if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { calc_sequence(t->scene, seq); } } @@ -4135,7 +4135,7 @@ static void freeSeqData(TransInfo *t) for (a=0; atotal; a++, td++) { seq= ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev)) { - if ((seq->type & SEQ_EFFECT) && seq->seq1) { + if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) { if (seq_test_overlap(seqbasep, seq)) { shuffle_seq(seqbasep, seq, t->scene); } @@ -4150,7 +4150,7 @@ static void freeSeqData(TransInfo *t) for (seq= seqbasep->first; seq; seq= seq->next) { /* We might want to build a list of effects that need to be updated during transform */ - if (seq->type & SEQ_EFFECT) { + if (seq->type & SEQ_TYPE_EFFECT) { if (seq->seq1 && seq->seq1->flag & SELECT) calc_sequence(t->scene, seq); else if (seq->seq2 && seq->seq2->flag & SELECT) calc_sequence(t->scene, seq); else if (seq->seq3 && seq->seq3->flag & SELECT) calc_sequence(t->scene, seq); @@ -4219,7 +4219,7 @@ static void createTransSeqData(bContext *C, TransInfo *t) Sequence *seq; for (seq= ed->seqbasep->first; seq; seq= seq->next) { /* hack */ - if ((seq->flag & SELECT)==0 && seq->type & SEQ_EFFECT) { + if ((seq->flag & SELECT)==0 && seq->type & SEQ_TYPE_EFFECT) { Sequence *seq_user; int i; for (i=0; i<3; i++) { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index b4dc40a81c3..73b6efedd77 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -72,7 +72,7 @@ typedef struct StripColorBalance { } StripColorBalance; typedef struct StripProxy { - char dir[768]; // custom directory for index and proxy files + char dir[768]; // custom directory for index and proxy files // (defaults to BL_proxy) char file[256]; // custom file @@ -81,7 +81,7 @@ typedef struct StripProxy { short tc; // time code in use short quality; // proxy build quality - short build_size_flags;// size flags (see below) of all proxies + short build_size_flags; // size flags (see below) of all proxies // to build short build_tc_flags; // time code flags (see below) of all tc indices // to build @@ -110,23 +110,23 @@ typedef struct Sequence { void *lib; /* needed (to be like ipo), else it will raise libdata warnings, this should never be used */ char name[64]; /* SEQ_NAME_MAXSTR - name, set by default and needs to be unique, for RNA paths */ - int flag, type; /*flags bitmap (see below) and the type of sequence*/ + int flag, type; /*flags bitmap (see below) and the type of sequence*/ int len; /* the length of the contents of this strip - before handles are applied */ int start, startofs, endofs; int startstill, endstill; int machine, depth; /*machine - the strip channel, depth - the depth in the sequence when dealing with metastrips */ - int startdisp, enddisp; /*starting and ending points in the sequence*/ + int startdisp, enddisp; /*starting and ending points in the sequence*/ float sat; float mul, handsize; short anim_preseek; - short streamindex; /* streamindex for movie or sound files with several streams */ + short streamindex; /* streamindex for movie or sound files with several streams */ int multicam_source; /* for multicam source selection */ - int clip_flag; /* MOVIECLIP render flags */ + int clip_flag; /* MOVIECLIP render flags */ Strip *strip; - struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */ + struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */ struct Scene *scene; struct Object *scene_camera; /* override scene camera */ @@ -139,16 +139,16 @@ typedef struct Sequence { /* pointers for effects: */ struct Sequence *seq1, *seq2, *seq3; - ListBase seqbase; /* list of strips for metastrips */ + ListBase seqbase; /* list of strips for metastrips */ - struct bSound *sound; /* the linked "bSound" object */ + struct bSound *sound; /* the linked "bSound" object */ void *scene_sound; float volume; - float pitch, pan; /* pitch (-0.1..10), pan -2..2 */ + float pitch, pan; /* pitch (-0.1..10), pan -2..2 */ float strobe; - void *effectdata; /* Struct pointer for effect settings */ + void *effectdata; /* Struct pointer for effect settings */ int anim_startofs; /* only use part of animation file */ int anim_endofs; /* is subtle different to startofs / endofs */ @@ -157,8 +157,8 @@ typedef struct Sequence { int blend_mode; float blend_opacity; - /* is sfra needed anymore? - it looks like its only used in one place */ - int sfra, pad; /* starting frame according to the timeline of the scene. */ + /* is sfra needed anymore? - it looks like its only used in one place */ + int sfra, pad; /* starting frame according to the timeline of the scene. */ } Sequence; typedef struct MetaStack { @@ -169,7 +169,7 @@ typedef struct MetaStack { typedef struct Editing { ListBase *seqbasep; /* pointer to the current list of seq's being edited (can be within a meta strip) */ - ListBase seqbase; /* pointer to the top-most seq's */ + ListBase seqbase; /* pointer to the top-most seq's */ ListBase metastack; /* Context vars, used to be static */ @@ -189,12 +189,12 @@ typedef struct WipeVars { } WipeVars; typedef struct GlowVars { - float fMini; /* Minimum intensity to trigger a glow */ + float fMini; /* Minimum intensity to trigger a glow */ float fClamp; - float fBoost; /* Amount to multiply glow intensity */ - float dDist; /* Radius of glow blurring */ - int dQuality; - int bNoComp; /* SHOW/HIDE glow buffer */ + float fBoost; /* Amount to multiply glow intensity */ + float dDist; /* Radius of glow blurring */ + int dQuality; + int bNoComp; /* SHOW/HIDE glow buffer */ } GlowVars; typedef struct TransformVars { @@ -214,7 +214,7 @@ typedef struct SolidColorVars { } SolidColorVars; typedef struct SpeedControlVars { - float * frameMap; + float *frameMap; float globalSpeed; int flags; int length; @@ -226,11 +226,11 @@ typedef struct SpeedControlVars { #define SELECT 1 /* Editor->over_flag */ -#define SEQ_EDIT_OVERLAY_SHOW 1 -#define SEQ_EDIT_OVERLAY_ABS 2 +#define SEQ_EDIT_OVERLAY_SHOW 1 +#define SEQ_EDIT_OVERLAY_ABS 2 -#define SEQ_STRIP_OFSBOTTOM 0.2f -#define SEQ_STRIP_OFSTOP 0.8f +#define SEQ_STRIP_OFSBOTTOM 0.2f +#define SEQ_STRIP_OFSTOP 0.8f /* SpeedControlVars->flags */ #define SEQ_SPEED_INTEGRATE 1 @@ -238,42 +238,42 @@ typedef struct SpeedControlVars { #define SEQ_SPEED_COMPRESS_IPO_Y 4 /* ***************** SEQUENCE ****************** */ -#define SEQ_NAME_MAXSTR 64 +#define SEQ_NAME_MAXSTR 64 /* seq->flag */ -#define SEQ_LEFTSEL (1<<1) -#define SEQ_RIGHTSEL (1<<2) -#define SEQ_OVERLAP (1<<3) -#define SEQ_FILTERY (1<<4) -#define SEQ_MUTE (1<<5) -#define SEQ_MAKE_PREMUL (1<<6) -#define SEQ_REVERSE_FRAMES (1<<7) -#define SEQ_IPO_FRAME_LOCKED (1<<8) -#define SEQ_EFFECT_NOT_LOADED (1<<9) -#define SEQ_FLAG_DELETE (1<<10) -#define SEQ_FLIPX (1<<11) -#define SEQ_FLIPY (1<<12) -#define SEQ_MAKE_FLOAT (1<<13) -#define SEQ_LOCK (1<<14) -#define SEQ_USE_PROXY (1<<15) -#define SEQ_USE_TRANSFORM (1<<16) -#define SEQ_USE_CROP (1<<17) -#define SEQ_USE_COLOR_BALANCE (1<<18) -#define SEQ_USE_PROXY_CUSTOM_DIR (1<<19) - -#define SEQ_USE_PROXY_CUSTOM_FILE (1<<21) -#define SEQ_USE_EFFECT_DEFAULT_FADE (1<<22) +#define SEQ_LEFTSEL (1 << 1) +#define SEQ_RIGHTSEL (1 << 2) +#define SEQ_OVERLAP (1 << 3) +#define SEQ_FILTERY (1 << 4) +#define SEQ_MUTE (1 << 5) +#define SEQ_MAKE_PREMUL (1 << 6) +#define SEQ_REVERSE_FRAMES (1 << 7) +#define SEQ_IPO_FRAME_LOCKED (1 << 8) +#define SEQ_EFFECT_NOT_LOADED (1 << 9) +#define SEQ_FLAG_DELETE (1 << 10) +#define SEQ_FLIPX (1 << 11) +#define SEQ_FLIPY (1 << 12) +#define SEQ_MAKE_FLOAT (1 << 13) +#define SEQ_LOCK (1 << 14) +#define SEQ_USE_PROXY (1 << 15) +#define SEQ_USE_TRANSFORM (1 << 16) +#define SEQ_USE_CROP (1 << 17) +#define SEQ_USE_COLOR_BALANCE (1 << 18) +#define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) + +#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) +#define SEQ_USE_EFFECT_DEFAULT_FADE (1 << 22) // flags for whether those properties are animated or not -#define SEQ_AUDIO_VOLUME_ANIMATED (1<<24) -#define SEQ_AUDIO_PITCH_ANIMATED (1<<25) -#define SEQ_AUDIO_PAN_ANIMATED (1<<26) -#define SEQ_AUDIO_DRAW_WAVEFORM (1<<27) +#define SEQ_AUDIO_VOLUME_ANIMATED (1 << 24) +#define SEQ_AUDIO_PITCH_ANIMATED (1 << 25) +#define SEQ_AUDIO_PAN_ANIMATED (1 << 26) +#define SEQ_AUDIO_DRAW_WAVEFORM (1 << 27) -#define SEQ_INVALID_EFFECT (1<<31) +#define SEQ_INVALID_EFFECT (1 << 31) /* convenience define for all selection flags */ -#define SEQ_ALLSEL (SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL) +#define SEQ_ALLSEL (SELECT + SEQ_LEFTSEL + SEQ_RIGHTSEL) /* deprecated, don't use a flag anymore*/ /*#define SEQ_ACTIVE 1048576*/ @@ -296,51 +296,52 @@ typedef struct SpeedControlVars { #define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS 8 #define SEQ_PROXY_TC_ALL 15 -/* seq->type WATCH IT: SEQ_EFFECT BIT is used to determine if this is an effect strip!!! */ -#define SEQ_IMAGE 0 -#define SEQ_META 1 -#define SEQ_SCENE 2 -#define SEQ_MOVIE 3 -#define SEQ_RAM_SOUND 4 -#define SEQ_HD_SOUND 5 -#define SEQ_SOUND 4 -#define SEQ_MOVIECLIP 6 - -#define SEQ_EFFECT 8 -#define SEQ_CROSS 8 -#define SEQ_ADD 9 -#define SEQ_SUB 10 -#define SEQ_ALPHAOVER 11 -#define SEQ_ALPHAUNDER 12 -#define SEQ_GAMCROSS 13 -#define SEQ_MUL 14 -#define SEQ_OVERDROP 15 -// #define SEQ_PLUGIN 24 /* Deprecated */ -#define SEQ_WIPE 25 -#define SEQ_GLOW 26 -#define SEQ_TRANSFORM 27 -#define SEQ_COLOR 28 -#define SEQ_SPEED 29 -#define SEQ_MULTICAM 30 -#define SEQ_ADJUSTMENT 31 -#define SEQ_EFFECT_MAX 31 +/* seq->type WATCH IT: SEQ_TYPE_EFFECT BIT is used to determine if this is an effect strip!!! */ +enum { + SEQ_TYPE_IMAGE = 0, + SEQ_TYPE_META = 1, + SEQ_TYPE_SCENE = 2, + SEQ_TYPE_MOVIE = 3, + SEQ_TYPE_SOUND_RAM = 4, + SEQ_TYPE_SOUND_HD = 5, + SEQ_TYPE_MOVIECLIP = 6, + + SEQ_TYPE_EFFECT = 8, + SEQ_TYPE_CROSS = 8, + SEQ_TYPE_ADD = 9, + SEQ_TYPE_SUB = 10, + SEQ_TYPE_ALPHAOVER = 11, + SEQ_TYPE_ALPHAUNDER = 12, + SEQ_TYPE_GAMCROSS = 13, + SEQ_TYPE_MUL = 14, + SEQ_TYPE_OVERDROP = 15, + /* SEQ_TYPE_PLUGIN = 24, */ /* Deprecated */ + SEQ_TYPE_WIPE = 25, + SEQ_TYPE_GLOW = 26, + SEQ_TYPE_TRANSFORM = 27, + SEQ_TYPE_COLOR = 28, + SEQ_TYPE_SPEED = 29, + SEQ_TYPE_MULTICAM = 30, + SEQ_TYPE_ADJUSTMENT = 31, + SEQ_TYPE_EFFECT_MAX = 31 +}; #define STRIPELEM_FAILED 0 #define STRIPELEM_OK 1 #define STRIPELEM_PREVIEW_DONE 1 -#define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1<<0) -#define SEQ_MOVIECLIP_RENDER_STABILIZED (1<<1) +#define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1 << 0) +#define SEQ_MOVIECLIP_RENDER_STABILIZED (1 << 1) #define SEQ_BLEND_REPLACE 0 -/* all other BLEND_MODEs are simple SEQ_EFFECT ids and therefore identical +/* all other BLEND_MODEs are simple SEQ_TYPE_EFFECT ids and therefore identical * to the table above. (Only those effects that handle _exactly_ two inputs, * otherwise, you can't really blend, right :) !) */ -#define SEQ_HAS_PATH(_seq) (ELEM4((_seq)->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_RAM_SOUND, SEQ_HD_SOUND)) +#define SEQ_HAS_PATH(_seq) (ELEM4((_seq)->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) #endif diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 9082bb42be5..1edf144452d 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -64,7 +64,7 @@ static void meta_tmp_ref(Sequence *seq_par, Sequence *seq) { for (; seq; seq = seq->next) { seq->tmp = seq_par; - if (seq->type == SEQ_META) { + if (seq->type == SEQ_TYPE_META) { meta_tmp_ref(seq, seq->seqbase.first); } } @@ -396,47 +396,47 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr) Sequence *seq = (Sequence *)ptr->data; switch (seq->type) { - case SEQ_IMAGE: + case SEQ_TYPE_IMAGE: return &RNA_ImageSequence; - case SEQ_META: + case SEQ_TYPE_META: return &RNA_MetaSequence; - case SEQ_SCENE: + case SEQ_TYPE_SCENE: return &RNA_SceneSequence; - case SEQ_MOVIE: + case SEQ_TYPE_MOVIE: return &RNA_MovieSequence; - case SEQ_MOVIECLIP: + case SEQ_TYPE_MOVIECLIP: return &RNA_MovieClipSequence; - case SEQ_SOUND: + case SEQ_TYPE_SOUND_RAM: return &RNA_SoundSequence; - case SEQ_CROSS: + case SEQ_TYPE_CROSS: return &RNA_CrossSequence; - case SEQ_ADD: + case SEQ_TYPE_ADD: return &RNA_AddSequence; - case SEQ_SUB: + case SEQ_TYPE_SUB: return &RNA_SubtractSequence; - case SEQ_ALPHAOVER: + case SEQ_TYPE_ALPHAOVER: return &RNA_AlphaOverSequence; - case SEQ_ALPHAUNDER: + case SEQ_TYPE_ALPHAUNDER: return &RNA_AlphaUnderSequence; - case SEQ_GAMCROSS: + case SEQ_TYPE_GAMCROSS: return &RNA_GammaCrossSequence; - case SEQ_MUL: + case SEQ_TYPE_MUL: return &RNA_MultiplySequence; - case SEQ_OVERDROP: + case SEQ_TYPE_OVERDROP: return &RNA_OverDropSequence; - case SEQ_MULTICAM: + case SEQ_TYPE_MULTICAM: return &RNA_MulticamSequence; - case SEQ_ADJUSTMENT: + case SEQ_TYPE_ADJUSTMENT: return &RNA_AdjustmentSequence; - case SEQ_WIPE: + case SEQ_TYPE_WIPE: return &RNA_WipeSequence; - case SEQ_GLOW: + case SEQ_TYPE_GLOW: return &RNA_GlowSequence; - case SEQ_TRANSFORM: + case SEQ_TYPE_TRANSFORM: return &RNA_TransformSequence; - case SEQ_COLOR: + case SEQ_TYPE_COLOR: return &RNA_ColorSequence; - case SEQ_SPEED: + case SEQ_TYPE_SPEED: return &RNA_SpeedControlSequence; default: return &RNA_Sequence; @@ -469,7 +469,7 @@ static void rna_Sequence_filepath_set(PointerRNA *ptr, const char *value) { Sequence *seq = (Sequence *)(ptr->data); - if (seq->type == SEQ_SOUND && seq->sound) { + if (seq->type == SEQ_TYPE_SOUND_RAM && seq->sound) { /* for sound strips we need to update the sound as well. * arguably, this could load in a new sound rather than modify an existing one. * but while using the sequencer its most likely your not using the sound in the game engine too. @@ -967,14 +967,14 @@ static void rna_def_strip_color_balance(BlenderRNA *brna) EnumPropertyItem blend_mode_items[] = { {SEQ_BLEND_REPLACE, "REPLACE", 0, "Replace", ""}, - {SEQ_CROSS, "CROSS", 0, "Cross", ""}, - {SEQ_ADD, "ADD", 0, "Add", ""}, - {SEQ_SUB, "SUBTRACT", 0, "Subtract", ""}, - {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""}, - {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""}, - {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""}, - {SEQ_MUL, "MULTIPLY", 0, "Multiply", ""}, - {SEQ_OVERDROP, "OVER_DROP", 0, "Over Drop", ""}, + {SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""}, + {SEQ_TYPE_ADD, "ADD", 0, "Add", ""}, + {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""}, + {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""}, + {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""}, + {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""}, + {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""}, + {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Over Drop", ""}, {0, NULL, 0, NULL, NULL} }; @@ -984,27 +984,27 @@ static void rna_def_sequence(BlenderRNA *brna) PropertyRNA *prop; static const EnumPropertyItem seq_type_items[] = { - {SEQ_IMAGE, "IMAGE", 0, "Image", ""}, - {SEQ_META, "META", 0, "Meta", ""}, - {SEQ_SCENE, "SCENE", 0, "Scene", ""}, - {SEQ_MOVIE, "MOVIE", 0, "Movie", ""}, - {SEQ_MOVIECLIP, "MOVIECLIP", 0, "Clip", ""}, - {SEQ_SOUND, "SOUND", 0, "Sound", ""}, - {SEQ_CROSS, "CROSS", 0, "Cross", ""}, - {SEQ_ADD, "ADD", 0, "Add", ""}, - {SEQ_SUB, "SUBTRACT", 0, "Subtract", ""}, - {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""}, - {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""}, - {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""}, - {SEQ_MUL, "MULTIPLY", 0, "Multiply", ""}, - {SEQ_OVERDROP, "OVER_DROP", 0, "Over Drop", ""}, - {SEQ_WIPE, "WIPE", 0, "Wipe", ""}, - {SEQ_GLOW, "GLOW", 0, "Glow", ""}, - {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", ""}, - {SEQ_COLOR, "COLOR", 0, "Color", ""}, - {SEQ_SPEED, "SPEED", 0, "Speed", ""}, - {SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, - {SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, + {SEQ_TYPE_IMAGE, "IMAGE", 0, "Image", ""}, + {SEQ_TYPE_META, "META", 0, "Meta", ""}, + {SEQ_TYPE_SCENE, "SCENE", 0, "Scene", ""}, + {SEQ_TYPE_MOVIE, "MOVIE", 0, "Movie", ""}, + {SEQ_TYPE_MOVIECLIP, "MOVIECLIP", 0, "Clip", ""}, + {SEQ_TYPE_SOUND_RAM, "SOUND", 0, "Sound", ""}, + {SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""}, + {SEQ_TYPE_ADD, "ADD", 0, "Add", ""}, + {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""}, + {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""}, + {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""}, + {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""}, + {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""}, + {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Over Drop", ""}, + {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", ""}, + {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", ""}, + {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", ""}, + {SEQ_TYPE_COLOR, "COLOR", 0, "Color", ""}, + {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""}, + {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, + {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 2fb882d96a1..bbc772770ea 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -104,7 +104,7 @@ static Sequence *rna_Sequences_new_clip(ID *id, Editing *ed, ReportList *reports Scene *scene = (Scene *)id; Sequence *seq; - seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_MOVIECLIP, clip->name); + seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_MOVIECLIP, clip->name); seq->clip = clip; seq->len = BKE_movieclip_get_duration(clip); id_us_plus((ID *)clip); @@ -123,7 +123,7 @@ static Sequence *rna_Sequences_new_scene(ID *id, Editing *ed, ReportList *report Scene *scene = (Scene *)id; Sequence *seq; - seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_SCENE, NULL); + seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_SCENE, NULL); seq->scene = sce_seq; seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1; seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0); @@ -143,7 +143,7 @@ static Sequence *rna_Sequences_new_image(ID *id, Editing *ed, ReportList *report Scene *scene = (Scene *)id; Sequence *seq; - seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_IMAGE, file); + seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_IMAGE, file); seq->len = 1; if (seq->strip->stripdata->name[0] == '\0') { @@ -174,7 +174,7 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report return NULL; } - seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_MOVIE, file); + seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_MOVIE, file); seq->anim = an; seq->anim_preseek = IMB_anim_get_preseek(an); seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); @@ -200,7 +200,7 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor return NULL; } - seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_SOUND, sound->name); + seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_SOUND_RAM, sound->name); seq->sound = sound; seq->len = ceil((double)sound_get_length(sound) * FPS); @@ -411,21 +411,21 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) FunctionRNA *func; static EnumPropertyItem seq_effect_items[] = { - {SEQ_CROSS, "CROSS", 0, "Cross", ""}, - {SEQ_ADD, "ADD", 0, "Add", ""}, - {SEQ_SUB, "SUBTRACT", 0, "Subtract", ""}, - {SEQ_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""}, - {SEQ_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""}, - {SEQ_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""}, - {SEQ_MUL, "MULTIPLY", 0, "Multiply", ""}, - {SEQ_OVERDROP, "OVER_DROP", 0, "Over Drop", ""}, - {SEQ_WIPE, "WIPE", 0, "Wipe", ""}, - {SEQ_GLOW, "GLOW", 0, "Glow", ""}, - {SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", ""}, - {SEQ_COLOR, "COLOR", 0, "Color", ""}, - {SEQ_SPEED, "SPEED", 0, "Speed", ""}, - {SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, - {SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, + {SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""}, + {SEQ_TYPE_ADD, "ADD", 0, "Add", ""}, + {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""}, + {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""}, + {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""}, + {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""}, + {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""}, + {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Over Drop", ""}, + {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", ""}, + {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", ""}, + {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", ""}, + {SEQ_TYPE_COLOR, "COLOR", 0, "Color", ""}, + {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""}, + {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""}, + {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 170d2efd60c..8f5230e4b2b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1636,7 +1636,7 @@ int RE_seq_render_active(Scene *scene, RenderData *rd) return 0; for (seq= ed->seqbase.first; seq; seq= seq->next) { - if (seq->type != SEQ_SOUND) + if (seq->type != SEQ_TYPE_SOUND_RAM) return 1; } @@ -1761,7 +1761,7 @@ static int check_valid_camera(Scene *scene, Object *camera_override) check_comp= 0; while (seq) { - if (seq->type == SEQ_SCENE && seq->scene) { + if (seq->type == SEQ_TYPE_SCENE && seq->scene) { if (!seq->scene_camera) { if (!seq->scene->camera && !BKE_scene_camera_find(seq->scene)) { if (seq->scene == scene) { -- cgit v1.2.3 From 8a500eea9a7414747eeb45d97b8581a507322db6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 Jun 2012 16:15:24 +0000 Subject: Avoid imbuf loading when getting movie clip size This prevents high memory usage by non-proxied frames when doing mask parenting. Description from code: Originally was needed to support image sequences with different image dimensions, which might be useful for such things as reconstruction of unordered image sequence, or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded cache lookups and even unwanted non-proxied files loading when doing mask parenting, so let's disable this for now and assume image sequence consists of images with equal sizes --- source/blender/blenkernel/intern/movieclip.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index de12926f3eb..985fc433c13 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -916,7 +916,17 @@ int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user) void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, int *height) { +#if 0 + /* originally was needed to support image sequences with different image dimensions, + * which might be useful for such things as reconstruction of unordered image sequence, + * or painting/rotoscoping of non-equal-sized images, but this ended up in unneeded + * cache lookups and even unwanted non-proxied files loading when doing mask parenting, + * so let's disable this for now and assume image sequence consists of images with + * equal sizes (sergey) + */ if (user->framenr == clip->lastframe) { +#endif + if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) { *width = clip->lastsize[0]; *height = clip->lastsize[1]; } -- cgit v1.2.3 From 64c45caff963c30cb9d4f6c0e94036ffa8363882 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 Jun 2012 16:36:19 +0000 Subject: Remove checks for valid frame from poll function in clip editor space This results in some buttons not disabled when there's no currently displaying frame, but this saves lots of cache lookups and threading loks for every frame update. --- source/blender/editors/include/ED_clip.h | 2 - source/blender/editors/space_clip/clip_editor.c | 33 --------------- source/blender/editors/space_clip/tracking_ops.c | 54 ++++++++++++------------ 3 files changed, 27 insertions(+), 62 deletions(-) diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 6b1028525a7..1d42954a416 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -47,8 +47,6 @@ int ED_space_clip_poll(struct bContext *C); int ED_space_clip_view_clip_poll(struct bContext *C); int ED_space_clip_tracking_poll(struct bContext *C); -int ED_space_clip_tracking_size_poll(struct bContext *C); -int ED_space_clip_tracking_frame_poll(struct bContext *C); int ED_space_clip_maskedit_poll(struct bContext *C); int ED_space_clip_maskedit_mask_poll(bContext *C); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index ab100b46f70..bcda1d59555 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -96,39 +96,6 @@ int ED_space_clip_tracking_poll(bContext *C) return FALSE; } -int ED_space_clip_tracking_size_poll(bContext *C) -{ - if (ED_space_clip_tracking_poll(C)) { - MovieClip *clip = CTX_data_edit_movieclip(C); - - if (clip) { - SpaceClip *sc = CTX_wm_space_clip(C); - int width, height; - - BKE_movieclip_get_size(clip, &sc->user, &width, &height); - - return width > 0 && height > 0; - } - } - - return FALSE; -} - -int ED_space_clip_tracking_frame_poll(bContext *C) -{ - if (ED_space_clip_tracking_poll(C)) { - MovieClip *clip = CTX_data_edit_movieclip(C); - - if (clip) { - SpaceClip *sc = CTX_wm_space_clip(C); - - return BKE_movieclip_has_frame(clip, &sc->user); - } - } - - return FALSE; -} - int ED_space_clip_maskedit_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 7073fdb3542..fdd4dfc57d0 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -107,6 +107,7 @@ static int add_marker_exec(bContext *C, wmOperator *op) int width, height; ED_space_clip_size(sc, &width, &height); + if (!width || !height) return OPERATOR_CANCELLED; @@ -144,7 +145,7 @@ void CLIP_OT_add_marker(wmOperatorType *ot) /* api callbacks */ ot->invoke = add_marker_invoke; ot->exec = add_marker_exec; - ot->poll = ED_space_clip_tracking_size_poll; + ot->poll = ED_space_clip_tracking_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -638,7 +639,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) ot->idname = "CLIP_OT_slide_marker"; /* api callbacks */ - ot->poll = ED_space_clip_tracking_size_poll; + ot->poll = ED_space_clip_tracking_poll; ot->invoke = slide_marker_invoke; ot->modal = slide_marker_modal; @@ -1308,7 +1309,7 @@ void CLIP_OT_select_grouped(wmOperatorType *ot) /* api callbacks */ ot->exec = select_groped_exec; - ot->poll = ED_space_clip_tracking_size_poll; + ot->poll = ED_space_clip_tracking_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1693,7 +1694,7 @@ void CLIP_OT_track_markers(wmOperatorType *ot) /* api callbacks */ ot->exec = track_markers_exec; ot->invoke = track_markers_invoke; - ot->poll = ED_space_clip_tracking_frame_poll; + ot->poll = ED_space_clip_tracking_poll; ot->modal = track_markers_modal; /* flags */ @@ -2134,19 +2135,17 @@ static Object *get_orientation_object(bContext *C) static int set_orientation_poll(bContext *C) { - if (ED_space_clip_tracking_size_poll(C)) { - Scene *scene = CTX_data_scene(C); - SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip(sc); - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); + Scene *scene = CTX_data_scene(C); + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { - return TRUE; - } - else { - return OBACT != NULL; - } + if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { + return TRUE; + } + else { + return OBACT != NULL; } return FALSE; @@ -2744,16 +2743,12 @@ void CLIP_OT_set_scale(wmOperatorType *ot) static int set_solution_scale_poll(bContext *C) { - if (ED_space_clip_tracking_size_poll(C)) { - SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip(sc); - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - - return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0; - } + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - return 0; + return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0; } static int set_solution_scale_exec(bContext *C, wmOperator *op) @@ -2963,6 +2958,11 @@ static int detect_features_exec(bContext *C, wmOperator *op) int framenr = ED_space_clip_clip_framenr(sc); bGPDlayer *layer = NULL; + if (!ibuf) { + BKE_report(op->reports, RPT_ERROR, "Feature detection requires valid clip frame"); + return OPERATOR_CANCELLED; + } + if (placement != 0) { layer = detect_get_layer(clip); place_outside_layer = placement == 2; @@ -3003,7 +3003,7 @@ void CLIP_OT_detect_features(wmOperatorType *ot) /* api callbacks */ ot->exec = detect_features_exec; - ot->poll = ED_space_clip_tracking_frame_poll; + ot->poll = ED_space_clip_tracking_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3156,7 +3156,7 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) /* api callbacks */ ot->exec = join_tracks_exec; - ot->poll = ED_space_clip_tracking_size_poll; + ot->poll = ED_space_clip_tracking_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -- cgit v1.2.3 From 49a5141cded6db36642461dc24064e6b695609af Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 7 Jun 2012 17:55:26 +0000 Subject: [#31739] Collada: New Export selections 'Include Armatures' --- source/blender/collada/ArmatureExporter.cpp | 58 ++++++++++++---------- source/blender/collada/ArmatureExporter.h | 4 +- source/blender/collada/DocumentExporter.cpp | 6 ++- source/blender/collada/ExportSettings.h | 1 + source/blender/collada/GeometryExporter.cpp | 29 ++++------- source/blender/collada/GeometryExporter.h | 2 +- source/blender/collada/SceneExporter.cpp | 52 ++++++++++++++++--- source/blender/collada/collada.cpp | 6 ++- source/blender/collada/collada.h | 6 ++- source/blender/collada/collada_utils.cpp | 39 +++++++++++++++ source/blender/collada/collada_utils.h | 3 ++ source/blender/makesrna/intern/rna_scene_api.c | 6 ++- source/blender/windowmanager/intern/wm_operators.c | 11 +++- 13 files changed, 160 insertions(+), 63 deletions(-) diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 9d59be39f33..107a3fc5796 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -37,6 +37,14 @@ #include "BKE_action.h" #include "BKE_armature.h" + +extern "C" { +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +} + #include "ED_armature.h" #include "BLI_listbase.h" @@ -45,6 +53,8 @@ #include "ArmatureExporter.h" #include "SceneExporter.h" +#include "collada_utils.h" + // XXX exporter writes wrong data for shared armatures. A separate // controller should be written for each armature-mesh binding how do // we make controller ids then? @@ -66,12 +76,12 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene* sce, bool ArmatureExporter::is_skinned_mesh(Object *ob) { - return get_assigned_armature(ob) != NULL; + return bc_get_assigned_armature(ob) != NULL; } -void ArmatureExporter::add_instance_controller(Object *ob) +bool ArmatureExporter::add_instance_controller(Object *ob) { - Object *ob_arm = get_assigned_armature(ob); + Object *ob_arm = bc_get_assigned_armature(ob); bArmature *arm = (bArmature*)ob_arm->data; const std::string& controller_id = get_controller_id(ob_arm, ob); @@ -79,6 +89,9 @@ void ArmatureExporter::add_instance_controller(Object *ob) COLLADASW::InstanceController ins(mSW); ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); + Mesh *me = (Mesh *)ob->data; + if (!me->dvert) return false; + // write root bone URLs Bone *bone; for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) { @@ -89,6 +102,7 @@ void ArmatureExporter::add_instance_controller(Object *ob) InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob); ins.add(); + return true; } void ArmatureExporter::export_controllers(Scene *sce) @@ -105,7 +119,7 @@ void ArmatureExporter::export_controllers(Scene *sce) void ArmatureExporter::operator()(Object *ob) { - Object *ob_arm = get_assigned_armature(ob); + Object *ob_arm = bc_get_assigned_armature(ob); if (ob_arm /*&& !already_written(ob_arm)*/) export_controller(ob, ob_arm); @@ -139,27 +153,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vectorparent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { - ob_arm = ob->parent; - } - else { - ModifierData *mod = (ModifierData*)ob->modifiers.first; - while (mod) { - if (mod->type == eModifierType_Armature) { - ob_arm = ((ArmatureModifierData*)mod)->object; - } - - mod = mod->next; - } - } - - return ob_arm; -} - std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm) { return get_joint_id(bone, ob_arm); @@ -325,7 +318,16 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm) */ bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me = (Mesh*)ob->data; + Mesh *me; + + if ( this->export_settings->apply_modifiers ) { + me = bc_to_mesh_apply_modifiers(scene, ob); + } + else { + me = (Mesh*)ob->data; + } + BKE_mesh_tessface_ensure(me); + if (!me->dvert) return; std::string controller_name = id_name(ob_arm); @@ -393,6 +395,10 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm) add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); + if (this->export_settings->apply_modifiers) + { + BKE_libblock_free_us(&(G.main->mesh), me); + } closeSkin(); closeController(); } diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index e9ee38d36cf..beef77af767 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -64,7 +64,7 @@ public: bool is_skinned_mesh(Object *ob); - void add_instance_controller(Object *ob); + bool add_instance_controller(Object *ob); void export_controllers(Scene *sce); @@ -85,8 +85,6 @@ private: void find_objects_using_armature(Object *ob_arm, std::vector& objects, Scene *sce); #endif - Object *get_assigned_armature(Object *ob); - std::string get_joint_sid(Bone *bone, Object *ob_arm); // Scene, SceneExporter and the list of child_objects diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 19fc30a2790..69f302eaec7 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -262,8 +262,10 @@ void DocumentExporter::exportCurrentScene(Scene *sce) // ArmatureExporter arm_exporter(&sw, this->export_settings); - if (has_object_type(sce, OB_ARMATURE)) { - arm_exporter.export_controllers(sce); + if (this->export_settings->include_armatures) { + if (has_object_type(sce, OB_ARMATURE)) { + arm_exporter.export_controllers(sce); + } } // diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index f0d3f810831..a6ae29bf2b2 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -32,6 +32,7 @@ struct ExportSettings public: bool selected; bool apply_modifiers; + bool include_armatures; bool include_bone_children; bool use_object_instantiation; bool second_life; diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 6df16165e4b..53d7f1e6449 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -49,6 +49,7 @@ extern "C" { #include "BKE_material.h" #include "BKE_mesh.h" #include "collada_internal.h" +#include "collada_utils.h" // TODO: optimize UV sets by making indexed list with duplicates removed GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) {} @@ -65,25 +66,6 @@ void GeometryExporter::exportGeom(Scene *sce) closeLibrary(); } -Mesh * GeometryExporter::get_mesh(Object *ob, int apply_modifiers) -{ - Mesh *tmpmesh; - if (!apply_modifiers) - { - tmpmesh = (Mesh*)ob->data; - } - else - { - CustomDataMask mask = CD_MASK_MESH; - DerivedMesh *dm = mesh_create_derived_view(mScene, ob, mask); - tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here - DM_to_mesh(dm, tmpmesh, ob); - dm->release(dm); - } - BKE_mesh_tessface_ensure(tmpmesh); - return tmpmesh; -} - void GeometryExporter::operator()(Object *ob) { // XXX don't use DerivedMesh, Mesh instead? @@ -93,7 +75,14 @@ void GeometryExporter::operator()(Object *ob) #endif bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me = get_mesh(ob, this->export_settings->apply_modifiers); + Mesh *me; + if ( this->export_settings->apply_modifiers ) { + me = bc_to_mesh_apply_modifiers(mScene, ob); + } + else { + me = (Mesh*)ob->data; + } + BKE_mesh_tessface_ensure(me); std::string geom_id = get_geometry_id(ob, use_instantiation); std::vector nor; diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index aae095e819e..23cdcc0a5ba 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -105,7 +105,7 @@ private: const ExportSettings *export_settings; - Mesh * get_mesh(Object *ob, int apply_modifiers); + Mesh * get_mesh(Scene *sce, Object *ob, int apply_modifiers); }; struct GeometryFunctor { diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index d258f4ef5e1..510107272cd 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -25,6 +25,7 @@ */ #include "SceneExporter.h" +#include "collada_utils.h" SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings) : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings) @@ -40,19 +41,36 @@ void SceneExporter::exportScene(Scene *sce) closeLibrary(); } +// Returns true if the parent chain does not contain any selected object +// Otherwise return false (ob has selected predecessor) +bool is_exported_base_node(Object *ob, bool selection_only) { + + if (selection_only && ob->flag & SELECT) { + // Move up towards root object, + // stop at first selected predecessor's child, + // or at root, if no parent was selected + while (ob->parent && (ob->parent->type==OB_ARMATURE || !(ob->parent->flag & SELECT))) + { + ob = ob->parent; + } + } + + return !ob->parent; +} + void SceneExporter::exportHierarchy(Scene *sce) { Base *base= (Base*) sce->base.first; while (base) { Object *ob = base->object; - if (!ob->parent) { + bool is_export_base_node = is_exported_base_node(ob, this->export_settings->selected); + if (is_export_base_node) { if (sce->lay & ob->lay) { switch (ob->type) { case OB_MESH: case OB_CAMERA: case OB_LAMP: - case OB_ARMATURE: case OB_EMPTY: if (this->export_settings->selected && !(ob->flag & SELECT)) { break; @@ -70,6 +88,14 @@ void SceneExporter::exportHierarchy(Scene *sce) void SceneExporter::writeNodes(Object *ob, Scene *sce) { + + // Add associated armature first if available + if (this->export_settings->include_armatures) { + Object *ob_arm = bc_get_assigned_armature(ob); + if(ob_arm != NULL) + writeNodes(ob_arm, sce); + } + COLLADASW::Node node(mSW); node.setNodeId(translate_id(id_name(ob))); node.setNodeName(translate_id(id_name(ob))); @@ -80,8 +106,19 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob); std::list child_objects; + // XXX Not sure about this. + // For me this looks more like a very special case for a very special purpose. + // Wouldn't it be better to have only one option here ? + // + // - include children + // + // Instead of "include_bone_children" ? + // then we could just ask: + // if (this->export_settings->include_children) + // ... + if (this->export_settings->include_armatures + && this->export_settings->include_bone_children) { - if (this->export_settings->include_bone_children) { // list child objects Base *b = (Base*) sce->base.first; while (b) { @@ -105,7 +142,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) } - if (ob->type == OB_MESH && is_skinned_mesh) + if (ob->type == OB_MESH && this->export_settings->include_armatures && is_skinned_mesh) // for skinned mesh we write obmat in TransformWriter::add_node_transform_identity(node); else @@ -113,10 +150,11 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) // if (ob->type == OB_MESH) { - if (is_skinned_mesh) { - arm_exporter->add_instance_controller(ob); + bool instance_controller_created = false; + if (this->export_settings->include_armatures && is_skinned_mesh) { + instance_controller_created = arm_exporter->add_instance_controller(ob); } - else { + if (!instance_controller_created){ COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 951fecec049..e880082c9ec 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -54,14 +54,18 @@ extern "C" const char *filepath, int selected, int apply_modifiers, + + int include_armatures, int include_bone_children, + int use_object_instantiation, - int second_life) + int second_life ) { ExportSettings export_settings; export_settings.selected = selected != 0; export_settings.apply_modifiers = apply_modifiers != 0; + export_settings.include_armatures = include_armatures != 0; export_settings.include_bone_children = include_bone_children != 0; export_settings.second_life = second_life != 0; export_settings.use_object_instantiation = use_object_instantiation != 0; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 67aaf1ff6c7..646c8469e6b 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -38,13 +38,17 @@ extern "C" { */ int collada_import(bContext *C, const char *filepath); int collada_export( - Scene *sce, + Scene *sce, const char *filepath, int selected, int apply_modifiers, + + int include_armatures, int include_bone_children, + int use_object_instantiation, int second_life); + #ifdef __cplusplus } #endif diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 8b7a28e5fbe..8693441d7c8 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -32,8 +32,10 @@ #include "COLLADAFWMeshPrimitive.h" #include "COLLADAFWMeshVertexData.h" +#include "DNA_modifier_types.h" #include "DNA_customdata_types.h" #include "DNA_object_types.h" +#include "DNA_mesh_types.h" #include "DNA_scene_types.h" #include "BLI_math.h" @@ -42,8 +44,13 @@ #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_object.h" +#include "BKE_mesh.h" #include "BKE_scene.h" +extern "C" { +#include "BKE_DerivedMesh.h" +} + #include "WM_api.h" // XXX hrm, see if we can do without this #include "WM_types.h" @@ -125,3 +132,35 @@ Object *bc_add_object(Scene *scene, int type, const char *name) return ob; } +Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob) +{ + Mesh *tmpmesh; + CustomDataMask mask = CD_MASK_MESH; + DerivedMesh *dm = mesh_create_derived_view(scene, ob, mask); + tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here + DM_to_mesh(dm, tmpmesh, ob); + dm->release(dm); + return tmpmesh; +} + +Object *bc_get_assigned_armature(Object *ob) +{ + Object *ob_arm = NULL; + + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod = (ModifierData*)ob->modifiers.first; + while (mod) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData*)mod)->object; + } + + mod = mod->next; + } + } + + return ob_arm; +} + diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 1f5d2b1d8da..9882b44d94c 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -36,6 +36,7 @@ #include #include "DNA_object_types.h" +#include "DNA_mesh_types.h" #include "DNA_customdata_types.h" #include "DNA_texture_types.h" #include "BKE_context.h" @@ -50,5 +51,7 @@ extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_sp extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); extern Object *bc_add_object(Scene *scene, int type, const char *name); +extern Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob); +extern Object *bc_get_assigned_armature(Object *ob); #endif diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 09e0428058a..b2ff36285e6 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -90,11 +90,14 @@ static void rna_Scene_collada_export( const char *filepath, int selected, int apply_modifiers, + int include_armatures, int include_bone_children, int use_object_instantiation, int second_life) { - collada_export(scene, filepath, selected, apply_modifiers, include_bone_children, use_object_instantiation, second_life); + collada_export(scene, filepath, selected, apply_modifiers, + include_armatures, include_bone_children, + use_object_instantiation, second_life); } #endif @@ -124,6 +127,7 @@ void RNA_api_scene(StructRNA *srna) RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */ parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements"); parm = RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers (in Preview resolution)"); + parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Include armature(s) used by the exported objects"); parm = RNA_def_boolean(func, "include_bone_children", 0, "Include Bone Children", "Include all objects attached to bones of selected Armature(s)"); parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instantiation", "Instantiate multiple Objects from same Data"); parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life"); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1cf58b4345b..ed023e42ea3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2162,7 +2162,11 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED static int wm_collada_export_exec(bContext *C, wmOperator *op) { char filename[FILE_MAX]; - int selected, second_life, apply_modifiers, include_bone_children, use_object_instantiation; + int selected, second_life, + include_armatures, + apply_modifiers, + include_bone_children, + use_object_instantiation; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -2174,6 +2178,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* Options panel */ selected = RNA_boolean_get(op->ptr, "selected"); apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); + include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); include_bone_children = RNA_boolean_get(op->ptr, "include_bone_children"); use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); second_life = RNA_boolean_get(op->ptr, "second_life"); @@ -2186,6 +2191,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) filename, selected, apply_modifiers, + include_armatures, include_bone_children, use_object_instantiation, second_life)) { @@ -2216,6 +2222,9 @@ static void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers (Preview Resolution)"); + RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures", + "Include armature(s) used by the exported objects"); + RNA_def_boolean(ot->srna, "include_bone_children", 0, "Include Bone Children", "Include all objects attached to bones of selected Armature(s)"); -- cgit v1.2.3 From fd271f34fe10b020336c32547f2b75d6dd7de14e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 Jun 2012 17:57:49 +0000 Subject: Remove unused ibuf argument from draw_gpencil_2dimage It was used by sequencer only and it wasn't ported for a while already. This change allows to save cahce lookup for image and clip editors. --- source/blender/editors/gpencil/drawgpencil.c | 9 +++++---- source/blender/editors/include/ED_gpencil.h | 2 +- source/blender/editors/space_clip/clip_draw.c | 14 ++++---------- source/blender/editors/space_image/image_draw.c | 9 +-------- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 8d771f0dc58..1823bbce3a1 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -669,7 +669,7 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, // ............................ /* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */ -void draw_gpencil_2dimage(bContext *C, ImBuf *ibuf) +void draw_gpencil_2dimage(bContext *C /* , ImBuf *ibuf */) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -678,8 +678,6 @@ void draw_gpencil_2dimage(bContext *C, ImBuf *ibuf) int offsx, offsy, sizex, sizey; int dflag = GP_DRAWDATA_NOSTATUS; - /* check that we have grease-pencil stuff to draw */ - if (ELEM(NULL, sa, ibuf)) return; gpd = gpencil_data_get_active(C); // XXX if (gpd == NULL) return; @@ -706,7 +704,10 @@ void draw_gpencil_2dimage(bContext *C, ImBuf *ibuf) { SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first; float zoom, zoomx, zoomy; - + + /* check that we have grease-pencil stuff to draw */ + if (ELEM(NULL, sa, ibuf)) return; + /* calculate accessory values */ zoom = (float)(SEQ_ZOOM_FAC(sseq->zoom)); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index bd3e4371a79..2040d4b9c32 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -76,7 +76,7 @@ void ED_operatortypes_gpencil(void); /* ------------ Grease-Pencil Drawing API ------------------ */ /* drawgpencil.c */ -void draw_gpencil_2dimage(struct bContext *C, struct ImBuf *ibuf); +void draw_gpencil_2dimage(struct bContext *C /* , struct ImBuf *ibuf */); void draw_gpencil_view2d(struct bContext *C, short onlyv2d); void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, short only3d); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 62ea0b00ff8..cca72e7469a 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1457,7 +1457,6 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip(sc); - ImBuf *ibuf; if (!clip) return; @@ -1466,16 +1465,11 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) /* if manual calibration is used then grease pencil data is already * drawed in draw_distortion */ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) { - ibuf = ED_space_clip_get_buffer(sc); - - if (ibuf) { - glPushMatrix(); - glMultMatrixf(sc->unistabmat); - draw_gpencil_2dimage(C, ibuf); + glPushMatrix(); + glMultMatrixf(sc->unistabmat); + draw_gpencil_2dimage(C); - IMB_freeImBuf(ibuf); - glPopMatrix(); - } + glPopMatrix(); } } else { diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index aab628180c8..0440aff3f65 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -564,16 +564,9 @@ void draw_image_grease_pencil(bContext *C, short onlyv2d) { /* draw in View2D space? */ if (onlyv2d) { - /* assume that UI_view2d_ortho(C) has been called... */ - SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C); - void *lock; - ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); - /* draw grease-pencil ('image' strokes) */ //if (sima->flag & SI_DISPGP) - draw_gpencil_2dimage(C, ibuf); - - ED_space_image_release_buffer(sima, lock); + draw_gpencil_2dimage(C); } else { /* assume that UI_view2d_restore(C) has been called... */ -- cgit v1.2.3 From 1c46e63d4d46e4b809ff5f01a2f8c534b6f3e2fd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 7 Jun 2012 18:10:25 +0000 Subject: Tooltips shouldn't have dot at the end of sentence --- source/blender/makesrna/intern/rna_cloth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 82a838010f6..3b4f87d8b95 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -547,7 +547,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) RNA_def_property_string_funcs(prop, "rna_CollSettings_selfcol_vgroup_get", "rna_CollSettings_selfcol_vgroup_length", "rna_CollSettings_selfcol_vgroup_set"); RNA_def_property_ui_text(prop, "Selfcollision Vertex Group", - "Vertex group to define vertices which are not used during self collisions."); + "Vertex group to define vertices which are not used during self collisions"); RNA_def_property_update(prop, 0, "rna_cloth_update"); } -- cgit v1.2.3 From 32530c28274c9c0de0707b39a6be9e4bafe7b257 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 7 Jun 2012 18:21:07 +0000 Subject: Quite some warnings... --- source/blender/blenkernel/BKE_mask.h | 2 +- source/blender/blenkernel/intern/mask.c | 2 +- source/blender/editors/mask/mask_add.c | 2 +- source/blender/editors/mesh/editmesh_knife.c | 2 +- source/blender/editors/sculpt_paint/paint_hide.c | 3 +-- source/blender/editors/sculpt_paint/sculpt.c | 4 ++-- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index a93e811557a..8a8281dafa0 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -99,7 +99,7 @@ void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float n[2]); float BKE_mask_point_weight_scalar(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); -float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, float u); +float BKE_mask_point_weight(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw); void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 0a6063a6b21..aaae58a6ab7 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -816,7 +816,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const fl return bezt_next->weight; } else { - float cur_u, cur_w, next_u, next_w, fac; + float cur_u = 0.0f, cur_w = 0.0f, next_u = 0.0f, next_w = 0.0f, fac; /* Quite warnings */ int i; for (i = 0; i < point->tot_uw + 1; i++) { diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index f81496c377a..a8363524dd7 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -411,7 +411,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float tangent_co[2]; int do_cyclic_correct = FALSE; int do_recalc_src = FALSE; /* when extruding from endpoints only */ - int do_prev; /* use prev point rather then next?? */ + int do_prev = FALSE; /* use prev point rather then next?? */ if (!masklay) { return FALSE; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 6bbcd1d253e..f154aec2eb4 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2247,7 +2247,7 @@ static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, Li ListBase *chain; BMVert *v; BMIter iter; - int nh, nf, i, j, k, m, ax, ay, ok, sep, bestsep; + int nh, nf, i, j, k, m, ax, ay, ok, sep = 0 /* Quite warnings */, bestsep; int besti[2], bestj[2]; float d, bestd; diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index cd8b9164862..89c328e71d8 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -265,7 +265,7 @@ static void get_pbvh_nodes(PBVH *pbvh, float clip_planes[4][4], PartialVisArea mode) { - BLI_pbvh_SearchCallback cb; + BLI_pbvh_SearchCallback cb = NULL; /* select search callback */ switch (mode) { @@ -277,7 +277,6 @@ static void get_pbvh_nodes(PBVH *pbvh, break; case PARTIALVIS_ALL: case PARTIALVIS_MASKED: - cb = NULL; break; } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index e069a6b9663..6a9257ecb6a 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -753,8 +753,8 @@ static float tex_strength(SculptSession *ss, Brush *br, float point[3], else if (ss->texcache) { float rotation = -mtex->rot; float symm_point[3], point_2d[2]; - float x, y; - float radius; + float x = 0.0f, y = 0.0f; /* Quite warnings */ + float radius = 1.0f; /* Quite warnings */ /* if the active area is being applied for symmetry, flip it * across the symmetry axis and rotate it back to the original -- cgit v1.2.3 From bdf9e023466756b6a75722cfa05ce75150e5ad75 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 18:24:36 +0000 Subject: new sequence strip type for masks. --- release/scripts/startup/bl_ui/space_clip.py | 18 ++++ release/scripts/startup/bl_ui/space_sequencer.py | 43 +++++++- source/blender/blenkernel/BKE_mask.h | 5 +- source/blender/blenkernel/intern/mask.c | 80 ++++++++++----- source/blender/blenkernel/intern/sequencer.c | 96 +++++++++++++++++- source/blender/blenloader/intern/readfile.c | 4 + .../compositor/operations/COM_MaskOperation.cpp | 2 +- source/blender/editors/include/UI_resources.h | 1 + source/blender/editors/interface/resources.c | 12 +++ .../editors/space_sequencer/sequencer_add.c | 108 ++++++++++++++++++++- .../editors/space_sequencer/sequencer_draw.c | 17 +++- .../editors/space_sequencer/sequencer_intern.h | 1 + .../editors/space_sequencer/sequencer_ops.c | 1 + .../editors/space_sequencer/sequencer_select.c | 13 ++- .../editors/space_sequencer/space_sequencer.c | 6 ++ source/blender/makesdna/DNA_mask_types.h | 2 + source/blender/makesdna/DNA_sequence_types.h | 2 + source/blender/makesdna/DNA_userdef_types.h | 4 +- source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/RNA_enum_types.h | 3 +- source/blender/makesrna/intern/rna_mask.c | 40 ++++++++ source/blender/makesrna/intern/rna_sequencer.c | 23 +++++ source/blender/makesrna/intern/rna_sequencer_api.c | 38 ++++++++ .../nodes/composite/nodes/node_composite_mask.c | 2 +- source/blender/windowmanager/intern/wm_operators.c | 10 ++ 25 files changed, 485 insertions(+), 47 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 0174762fcc8..4bec1ad18ba 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -790,6 +790,24 @@ class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): col.prop(sc, "show_mask_smooth") +# TODO, move into its own file +class CLIP_PT_mask(CLIP_PT_mask_view_panel, Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Mask Settings" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + layout = self.layout + + sc = context.space_data + mask = sc.mask + + col = layout.column(align=True) + col.prop(mask, "frame_start") + col.prop(mask, "frame_end") + + class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 732f675c208..276e8e5ae1d 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -198,6 +198,12 @@ class SEQUENCER_MT_add(Menu): else: layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip...") + if len(bpy.data.masks) > 10: + layout.operator_context = 'INVOKE_DEFAULT' + layout.operator("sequencer.mask_strip_add", text="Masks...") + else: + layout.operator_menu_enum("sequencer.mask_strip_add", "mask", text="Mask...") + layout.operator("sequencer.movie_strip_add", text="Movie") layout.operator("sequencer.image_strip_add", text="Image") layout.operator("sequencer.sound_strip_add", text="Sound") @@ -670,6 +676,35 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): layout.label(text="Original frame range" + ": %d-%d (%d)" % (sta, end, end - sta + 1)) +class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): + bl_label = "Mask" + + @classmethod + def poll(cls, context): + if not cls.has_sequencer(context): + return False + + strip = act_strip(context) + if not strip: + return False + + return (strip.type == 'MASK') + + def draw(self, context): + layout = self.layout + + strip = act_strip(context) + + layout.template_ID(strip, "mask") + + mask = strip.mask + + if mask: + sta = mask.frame_start + end = mask.frame_end + layout.label(text="Original frame range" + ": %d-%d (%d)" % (sta, end, end - sta + 1)) + + class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): bl_label = "Filter" @@ -682,10 +717,10 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): if not strip: return False - return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'META', - 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER', - 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', - 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', + return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'MASK', + 'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER', + 'ALPHA_UNDER', 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', + 'OVER_DROP', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'MULTICAM', 'SPEED', 'ADJUSTMENT'} def draw(self, context): diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 8a8281dafa0..32f86bd3ebe 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -120,6 +120,7 @@ void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *u void BKE_mask_update_display(struct Mask *mask, float ctime); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); +void BKE_mask_evaluate(struct Mask *mask, float ctime, const int do_newframe); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); @@ -165,7 +166,9 @@ void BKE_mask_layer_shape_changed_add(struct MaskLayer *masklay, int index, void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, int count); /* rasterization */ -void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer); +int BKE_mask_get_duration(struct Mask *mask); +void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer, + const short do_aspect_correct, const short do_linear); #define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index aaae58a6ab7..b942b633aef 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -951,6 +951,10 @@ Mask *BKE_mask_new(const char *name) mask = mask_alloc(mask_name); + /* arbitrary defaults */ + mask->sfra = 1; + mask->efra = 100; + return mask; } @@ -2040,7 +2044,7 @@ static void m_invert_vn_vn(float *array, const float f, const int size) } } -static void linear_clamp_vn_vn(float *array, const int size) +static void clamp_vn_vn_linear(float *array, const int size) { float *arr = array + (size - 1); @@ -2053,8 +2057,26 @@ static void linear_clamp_vn_vn(float *array, const int size) } } +static void clamp_vn_vn(float *array, const int size) +{ + float *arr = array + (size - 1); + + int i = size; + while (i--) { + if (*arr < 0.0f) *arr = 0.0f; + else if (*arr > 1.0f) *arr = 1.0f; + arr--; + } +} + +int BKE_mask_get_duration(Mask *mask) +{ + return MAX2(1, mask->efra - mask->sfra); +} + /* rasterization */ -void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) +void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer, + const short do_aspect_correct, const short do_linear) { MaskLayer *masklay; @@ -2087,31 +2109,32 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, &tot_diff_feather_points); - /* TODO, make this optional! */ - if (width != height) { - float *fp; - float *ffp; - int i; - float asp; - - if (width < height) { - fp = &diff_points[0][0]; - ffp = tot_diff_feather_points ? &diff_feather_points[0][0] : NULL; - asp = (float)width / (float)height; - } - else { - fp = &diff_points[0][1]; - ffp = tot_diff_feather_points ? &diff_feather_points[0][1] : NULL; - asp = (float)height / (float)width; - } + if (do_aspect_correct) { + if (width != height) { + float *fp; + float *ffp; + int i; + float asp; + + if (width < height) { + fp = &diff_points[0][0]; + ffp = tot_diff_feather_points ? &diff_feather_points[0][0] : NULL; + asp = (float)width / (float)height; + } + else { + fp = &diff_points[0][1]; + ffp = tot_diff_feather_points ? &diff_feather_points[0][1] : NULL; + asp = (float)height / (float)width; + } - for (i = 0; i < tot_diff_point; i++, fp += 2) { - (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; - } + for (i = 0; i < tot_diff_point; i++, fp += 2) { + (*fp) = (((*fp) - 0.5f) / asp) + 0.5f; + } - if (tot_diff_feather_points) { - for (i = 0; i < tot_diff_feather_points; i++, ffp += 2) { - (*ffp) = (((*ffp) - 0.5f) / asp) + 0.5f; + if (tot_diff_feather_points) { + for (i = 0; i < tot_diff_feather_points; i++, ffp += 2) { + (*ffp) = (((*ffp) - 0.5f) / asp) + 0.5f; + } } } } @@ -2173,7 +2196,12 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer) } /* clamp at the end */ - linear_clamp_vn_vn(buffer, buffer_size); + if (do_linear) { + clamp_vn_vn_linear(buffer, buffer_size); + } + else { + clamp_vn_vn(buffer, buffer_size); + } } MEM_freeN(buffer_tmp); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 699e0b1cd97..97733404b09 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -29,7 +29,6 @@ * \ingroup bke */ - #include #include #include @@ -40,6 +39,7 @@ #include "DNA_sequence_types.h" #include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -61,6 +61,7 @@ #include "BKE_movieclip.h" #include "BKE_fcurve.h" #include "BKE_scene.h" +#include "BKE_mask.h" #include "BKE_utildefines.h" #include "RNA_access.h" @@ -669,9 +670,9 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) int prev_startdisp = 0, prev_enddisp = 0; /* note: don't rename the strip, will break animation curves */ - if (ELEM6(seq->type, + if (ELEM7(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, - SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP) == 0) + SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0) { return; } @@ -725,6 +726,15 @@ void reload_sequence_new_file(Scene *scene, Sequence *seq, int lock_range) case SEQ_TYPE_MOVIECLIP: seq->len = BKE_movieclip_get_duration(seq->clip); + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + break; + case SEQ_TYPE_MASK: + seq->len = BKE_mask_get_duration(seq->mask); + seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; if (seq->len < 0) { @@ -903,7 +913,8 @@ static const char *give_seqname_by_type(int type) case SEQ_TYPE_SCENE: return "Scene"; case SEQ_TYPE_MOVIE: return "Movie"; case SEQ_TYPE_MOVIECLIP: return "Clip"; - case SEQ_TYPE_SOUND_RAM: return "Audio"; + case SEQ_TYPE_MASK: return "Mask"; + case SEQ_TYPE_SOUND_RAM: return "Audio"; case SEQ_TYPE_CROSS: return "Cross"; case SEQ_TYPE_GAMCROSS: return "Gamma Cross"; case SEQ_TYPE_ADD: return "Add"; @@ -2044,6 +2055,75 @@ static ImBuf *seq_render_movieclip_strip( return ibuf; } + +static ImBuf *seq_render_mask_strip( + SeqRenderData context, Sequence *seq, float nr) +{ + /* TODO - add option to rasterize to alpha imbuf? */ + ImBuf *ibuf = NULL; + float *maskbuf; + int i; + + if (!seq->mask) { + return NULL; + } + + BKE_mask_evaluate(seq->mask, (int)(seq->mask->sfra + nr), TRUE); + + maskbuf = MEM_callocN(sizeof(float) * context.rectx * context.recty, __func__); + + if (seq->flag & SEQ_MAKE_FLOAT) { + /* pixels */ + float *fp_src; + float *fp_dst; + + ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rectfloat); + + BKE_mask_rasterize(seq->mask, + context.rectx, context.recty, + maskbuf, + TRUE, FALSE); + + fp_src = maskbuf; + fp_dst = ibuf->rect_float; + i = context.rectx * context.recty; + while(--i) { + fp_dst[0] = fp_dst[1] = fp_dst[2] = *fp_src; + fp_dst[3] = 1.0f; + + fp_src += 1; + fp_dst += 4; + } + } + else { + /* pixels */ + float *fp_src; + unsigned char *ub_dst; + + ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); + + BKE_mask_rasterize(seq->mask, + context.rectx, context.recty, + maskbuf, + TRUE, FALSE); + + fp_src = maskbuf; + ub_dst = (unsigned char *)ibuf->rect; + i = context.rectx * context.recty; + while(--i) { + ub_dst[0] = ub_dst[1] = ub_dst[2] = (unsigned char)(*fp_src * 255.0f); /* already clamped */ + ub_dst[3] = 255; + + fp_src += 1; + ub_dst += 4; + } + } + + MEM_freeN(maskbuf); + + return ibuf; +} + static ImBuf *seq_render_scene_strip( SeqRenderData context, Sequence *seq, float nr) { @@ -2359,6 +2439,14 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) copy_to_ibuf_still(context, seq, nr, ibuf); break; } + case SEQ_TYPE_MASK: + { + /* ibuf is alwats new */ + ibuf = seq_render_mask_strip(context, seq, nr); + + copy_to_ibuf_still(context, seq, nr, ibuf); + break; + } } if (ibuf == NULL) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cce38ff1d90..85d597ccbdd 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4828,6 +4828,10 @@ static void lib_link_scene(FileData *fd, Main *main) seq->clip = newlibadr(fd, sce->id.lib, seq->clip); seq->clip->id.us++; } + if (seq->mask) { + seq->mask = newlibadr(fd, sce->id.lib, seq->mask); + seq->mask->id.us++; + } if (seq->scene_camera) seq->scene_camera = newlibadr(fd, sce->id.lib, seq->scene_camera); if (seq->sound) { seq->scene_sound = NULL; diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index a742306f440..a7c1de323f1 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -75,7 +75,7 @@ void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers float *buffer; buffer = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); - BKE_mask_rasterize(mask, width, height, buffer); + BKE_mask_rasterize(mask, width, height, buffer, TRUE, TRUE); this->rasterizedMask = buffer; } diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 2ef5277a3c6..51df30d6c28 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -151,6 +151,7 @@ enum { TH_SEQ_MOVIE, TH_SEQ_MOVIECLIP, + TH_SEQ_MASK, TH_SEQ_IMAGE, TH_SEQ_SCENE, TH_SEQ_AUDIO, diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 2e70a941a54..02f34873ea7 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -372,6 +372,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->movie; break; case TH_SEQ_MOVIECLIP: cp = ts->movieclip; break; + case TH_SEQ_MASK: + cp = ts->mask; break; case TH_SEQ_IMAGE: cp = ts->image; break; case TH_SEQ_SCENE: @@ -819,6 +821,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tseq.back, 116, 116, 116, 255); rgba_char_args_set(btheme->tseq.movie, 81, 105, 135, 255); rgba_char_args_set(btheme->tseq.movieclip, 32, 32, 143, 255); + rgba_char_args_set(btheme->tseq.mask, 152, 78, 62, 255); rgba_char_args_set(btheme->tseq.image, 109, 88, 129, 255); rgba_char_args_set(btheme->tseq.scene, 78, 152, 62, 255); rgba_char_args_set(btheme->tseq.audio, 46, 143, 143, 255); @@ -1899,6 +1902,15 @@ void init_userdef_do_versions(void) } } + if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 11)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + if (btheme->tseq.movieclip[0] == 0) { + rgba_char_args_set(btheme->tseq.mask, 152, 78, 62, 255); + } + } + } + /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { U.texcollectrate = 60; diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 9301f13c8c0..26bedd14d6e 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -46,6 +46,7 @@ #include "BLI_utildefines.h" #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "DNA_userdef_types.h" #include "BKE_context.h" @@ -54,6 +55,8 @@ #include "BKE_main.h" #include "BKE_sequencer.h" #include "BKE_movieclip.h" +#include "BKE_sequencer.h" +#include "BKE_mask.h" #include "BKE_report.h" #include "WM_api.h" @@ -360,7 +363,6 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, wmEvent *event) { if (!ED_operator_sequencer_active(C)) { @@ -377,11 +379,10 @@ static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, wmE // return WM_menu_invoke(C, op, event); } - void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Add MovieClip Strip"; ot->idname = "SEQUENCER_OT_movieclip_strip_add"; @@ -392,16 +393,113 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot) ot->exec = sequencer_add_movieclip_strip_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", ""); RNA_def_enum_funcs(prop, RNA_movieclip_itemf); ot->prop = prop; } +static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Editing *ed = BKE_sequencer_editing_get(scene, TRUE); + + Mask *mask; + + Sequence *seq; /* generic strip vars */ + Strip *strip; + + int start_frame, channel; /* operator props */ + + start_frame = RNA_int_get(op->ptr, "frame_start"); + channel = RNA_int_get(op->ptr, "channel"); + + mask = BLI_findlink(&CTX_data_main(C)->mask, RNA_enum_get(op->ptr, "mask")); + + if (mask == NULL) { + BKE_report(op->reports, RPT_ERROR, "Mask not found"); + return OPERATOR_CANCELLED; + } + + seq = alloc_sequence(ed->seqbasep, start_frame, channel); + seq->type = SEQ_TYPE_MASK; + seq->blend_mode = SEQ_TYPE_CROSS; + seq->mask = mask; + + if (seq->mask->id.us == 0) + seq->mask->id.us = 1; + + /* basic defaults */ + seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); + seq->len = BKE_mask_get_duration(mask); + strip->us = 1; + + BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2); + seqbase_unique_name_recursive(&ed->seqbase, seq); + + calc_sequence_disp(scene, seq); + BKE_sequencer_sort(scene); + + if (RNA_boolean_get(op->ptr, "replace_sel")) { + ED_sequencer_deselect_all(scene); + BKE_sequencer_active_set(scene, seq); + seq->flag |= SELECT; + } + + if (RNA_boolean_get(op->ptr, "overlap") == FALSE) { + if (seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + } + + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); + + return OPERATOR_FINISHED; +} + +static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + if (!ED_operator_sequencer_active(C)) { + BKE_report(op->reports, RPT_ERROR, "Sequencer area not active"); + return OPERATOR_CANCELLED; + } + + if (!RNA_struct_property_is_set(op->ptr, "mask")) + return WM_enum_search_invoke(C, op, event); + + sequencer_generic_invoke_xy__internal(C, op, event, 0); + return sequencer_add_mask_strip_exec(C, op); + // needs a menu + // return WM_menu_invoke(C, op, event); +} + + +void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Add Mask Strip"; + ot->idname = "SEQUENCER_OT_mask_strip_add"; + ot->description = "Add a mask strip to the sequencer"; + + /* api callbacks */ + ot->invoke = sequencer_add_mask_strip_invoke; + ot->exec = sequencer_add_mask_strip_exec; + + ot->poll = ED_operator_scene_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); + prop = RNA_def_enum(ot->srna, "mask", DummyRNA_NULL_items, 0, "Mask", ""); + RNA_def_enum_funcs(prop, RNA_mask_itemf); + ot->prop = prop; +} + static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoadFunc seq_load_func) { diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index cb15eed6a37..eb943451b1f 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -40,6 +40,7 @@ #include "IMB_imbuf_types.h" #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" @@ -97,7 +98,11 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[ case SEQ_TYPE_MOVIECLIP: UI_GetThemeColor3ubv(TH_SEQ_MOVIECLIP, col); break; - + + case SEQ_TYPE_MASK: + UI_GetThemeColor3ubv(TH_SEQ_MASK, col); /* TODO */ + break; + case SEQ_TYPE_SCENE: UI_GetThemeColor3ubv(TH_SEQ_SCENE, col); @@ -550,6 +555,16 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float seq->len, name); } } + else if (seq->type == SEQ_TYPE_MASK) { + if (seq->mask && strcmp(name, seq->mask->id.name + 2) != 0) { + BLI_snprintf(str, sizeof(str), "%d | %s: %s", + seq->len, name, seq->mask->id.name + 2); + } + else { + BLI_snprintf(str, sizeof(str), "%d | %s", + seq->len, name); + } + } else if (seq->type == SEQ_TYPE_MULTICAM) { BLI_snprintf(str, sizeof(str), "Cam | %s: %d", name, seq->multicam_source); diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 19cd7ed4ad4..25a322c6905 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -138,6 +138,7 @@ void SEQUENCER_OT_select_grouped(struct wmOperatorType *ot); void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot); void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot); void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot); +void SEQUENCER_OT_mask_strip_add(struct wmOperatorType *ot); void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot); void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot); void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 3a02c90f99a..79ecd9f7481 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -105,6 +105,7 @@ void sequencer_operatortypes(void) /* sequencer_add.c */ WM_operatortype_append(SEQUENCER_OT_scene_strip_add); WM_operatortype_append(SEQUENCER_OT_movieclip_strip_add); + WM_operatortype_append(SEQUENCER_OT_mask_strip_add); WM_operatortype_append(SEQUENCER_OT_movie_strip_add); WM_operatortype_append(SEQUENCER_OT_sound_strip_add); WM_operatortype_append(SEQUENCER_OT_image_strip_add); diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 261bc575420..b03edfc61b9 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -934,7 +934,7 @@ static EnumPropertyItem sequencer_prop_select_grouped_types[] = { #define SEQ_IS_EFFECT(_seq) (_seq->type & SEQ_TYPE_EFFECT) -#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP) || SEQ_HAS_PATH(_seq)) +#define SEQ_USE_DATA(_seq) (ELEM3(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq)) static short select_grouped_type(Editing *ed, Sequence *actseq) { @@ -1030,6 +1030,17 @@ static short select_grouped_data(Editing *ed, Sequence *actseq) } SEQ_END; } + else if (actseq->type == SEQ_TYPE_MASK) { + struct Mask *mask = actseq->mask; + SEQP_BEGIN (ed, seq) + { + if (seq->type == SEQ_TYPE_MASK && seq->mask == mask) { + seq->flag |= SELECT; + changed = TRUE; + } + } + SEQ_END; + } return changed; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 4168cb9ac77..cc59a05b781 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -482,6 +482,12 @@ static void sequencer_preview_area_listener(ARegion *ar, wmNotifier *wmn) break; } break; + + case NC_MASK: + if (wmn->action == NA_EDITED) { + ED_region_tag_redraw(ar); + } + break; } } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 23f33729f69..626242c1a8d 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -46,6 +46,8 @@ typedef struct Mask { ListBase masklayers; /* mask layers */ int masklay_act; /* index of active mask layer (-1 == None) */ int masklay_tot; /* total number of mask layers */ + + int sfra, efra; /* frames, used by the sequencer */ } Mask; typedef struct MaskParent { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 73b6efedd77..161c448476d 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -132,6 +132,7 @@ typedef struct Sequence { struct anim *anim; /* for MOVIE strips */ struct MovieClip *clip; /* for MOVIECLIP strips */ + struct Mask *mask; /* for MASK strips */ float effect_fader; float speed_fader; @@ -305,6 +306,7 @@ enum { SEQ_TYPE_SOUND_RAM = 4, SEQ_TYPE_SOUND_HD = 5, SEQ_TYPE_MOVIECLIP = 6, + SEQ_TYPE_MASK = 7, SEQ_TYPE_EFFECT = 8, SEQ_TYPE_CROSS = 8, diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index f06a2b6f80a..5465dbf6e3c 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -236,7 +236,7 @@ typedef struct ThemeSpace { char syntaxl[4], syntaxn[4], syntaxb[4]; // syntax for textwindow and nodes char syntaxv[4], syntaxc[4]; - char movie[4], movieclip[4], image[4], scene[4], audio[4]; // for sequence editor + char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4]; // for sequence editor char effect[4], hpad0[4], transition[4], meta[4]; char editmesh_active[4]; @@ -249,7 +249,7 @@ typedef struct ThemeSpace { char bundle_solid[4]; char path_before[4], path_after[4]; char camera_path[4]; - char hpad[7]; + char hpad[3]; char preview_back[4]; char preview_stitch_face[4]; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index c9914a35a14..37455563ee0 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -295,6 +295,7 @@ extern StructRNA RNA_Macro; extern StructRNA RNA_MagicTexture; extern StructRNA RNA_MarbleTexture; extern StructRNA RNA_MaskModifier; +extern StructRNA RNA_MaskSequence; extern StructRNA RNA_Material; extern StructRNA RNA_MaterialHalo; extern StructRNA RNA_MaterialPhysics; diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index d2eeaa72fed..473ab7485b0 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -144,6 +144,7 @@ EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, st EnumPropertyItem *RNA_scene_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int *free); EnumPropertyItem *RNA_movieclip_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int *free); EnumPropertyItem *RNA_movieclip_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int *free); - +EnumPropertyItem *RNA_mask_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int *free); +EnumPropertyItem *RNA_mask_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int *free); #endif /* __RNA_ENUM_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 51d370d5a88..f25aba6193b 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -312,6 +312,29 @@ static void rna_MaskLayer_spline_add(ID *id, MaskLayer *masklay, int number) WM_main_add_notifier(NC_MASK|NA_EDITED, mask); } +static void rna_Mask_start_frame_set(PointerRNA *ptr, int value) +{ + Mask *data = (Mask *)ptr->data; + /* MINFRAME not MINAFRAME, since some output formats can't taken negative frames */ + CLAMP(value, MINFRAME, MAXFRAME); + data->sfra = value; + + if (data->sfra >= data->efra) { + data->efra = MIN2(data->sfra, MAXFRAME); + } +} + +static void rna_Mask_end_frame_set(PointerRNA *ptr, int value) +{ + Mask *data = (Mask *)ptr->data; + CLAMP(value, MINFRAME, MAXFRAME); + data->efra = value; + + if (data->sfra >= data->efra) { + data->sfra = MAX2(data->efra, MINFRAME); + } +} + #else static void rna_def_maskParent(BlenderRNA *brna) @@ -644,6 +667,23 @@ static void rna_def_mask(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_Mask_layer_active_index_get", "rna_Mask_layer_active_index_set", "rna_Mask_layer_active_index_range"); RNA_def_property_ui_text(prop, "Active Shape Index", "Index of active layer in list of all mask's layers"); + /* frame range */ + 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, "sfra"); + RNA_def_property_int_funcs(prop, NULL, "rna_Mask_start_frame_set", NULL); + RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Start Frame", "First frame of the mask (used for sequencer)"); + RNA_def_property_update(prop, NC_SCENE | ND_FRAME_RANGE, NULL); + + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_sdna(prop, NULL, "efra"); + RNA_def_property_int_funcs(prop, NULL, "rna_Mask_end_frame_set", NULL); + RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "End Frame", "Final frame of the mask (used for sequencer)"); + RNA_def_property_update(prop, NC_SCENE | ND_FRAME_RANGE, NULL); + /* pointers */ rna_def_animdata_common(srna); } diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 1edf144452d..fb8ba2f863e 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -406,6 +406,8 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr) return &RNA_MovieSequence; case SEQ_TYPE_MOVIECLIP: return &RNA_MovieClipSequence; + case SEQ_TYPE_MASK: + return &RNA_MaskSequence; case SEQ_TYPE_SOUND_RAM: return &RNA_SoundSequence; case SEQ_TYPE_CROSS: @@ -989,6 +991,7 @@ static void rna_def_sequence(BlenderRNA *brna) {SEQ_TYPE_SCENE, "SCENE", 0, "Scene", ""}, {SEQ_TYPE_MOVIE, "MOVIE", 0, "Movie", ""}, {SEQ_TYPE_MOVIECLIP, "MOVIECLIP", 0, "Clip", ""}, + {SEQ_TYPE_MASK, "MASK", 0, "Mask", ""}, {SEQ_TYPE_SOUND_RAM, "SOUND", 0, "Sound", ""}, {SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""}, {SEQ_TYPE_ADD, "ADD", 0, "Add", ""}, @@ -1505,6 +1508,8 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "MovieClip Sequence", "Sequence strip to load a video from the clip editor"); RNA_def_struct_sdna(srna, "Sequence"); + /* TODO - add clip property? */ + prop = RNA_def_property(srna, "undistort", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_UNDISTORTED); RNA_def_property_ui_text(prop, "Undistort Clip", "Use the undistorted version of the clip"); @@ -1519,6 +1524,23 @@ static void rna_def_movieclip(BlenderRNA *brna) rna_def_input(srna); } +static void rna_def_mask(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MaskSequence", "Sequence"); + RNA_def_struct_ui_text(srna, "Mask Sequence", "Sequence strip to load a video from a mask"); + RNA_def_struct_sdna(srna, "Sequence"); + + prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mask", "Mask that this sequence uses"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + + rna_def_filter_video(srna); + rna_def_input(srna); +} static void rna_def_sound(BlenderRNA *brna) { @@ -1883,6 +1905,7 @@ void RNA_def_sequencer(BlenderRNA *brna) rna_def_scene(brna); rna_def_movie(brna); rna_def_movieclip(brna); + rna_def_mask(brna); rna_def_sound(brna); rna_def_effect(brna); rna_def_effects(brna); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index bbc772770ea..e20435a07cd 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -45,6 +45,7 @@ extern EnumPropertyItem blend_mode_items[]; #include "DNA_image_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_mask_types.h" #include "DNA_sound_types.h" #include "BLI_path_util.h" /* BLI_split_dirfile */ @@ -52,6 +53,7 @@ extern EnumPropertyItem blend_mode_items[]; #include "BKE_image.h" #include "BKE_library.h" /* id_us_plus */ #include "BKE_movieclip.h" +#include "BKE_mask.h" #include "BKE_report.h" #include "BKE_sequencer.h" @@ -116,6 +118,25 @@ static Sequence *rna_Sequences_new_clip(ID *id, Editing *ed, ReportList *reports return seq; } +static Sequence *rna_Sequences_new_mask(ID *id, Editing *ed, ReportList *reports, + const char *name, Mask *mask, int channel, + int start_frame) +{ + Scene *scene = (Scene *)id; + Sequence *seq; + + seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_MASK, mask->id.name); + seq->mask = mask; + seq->len = BKE_mask_get_duration(mask); + id_us_plus((ID *)mask); + + calc_sequence_disp(scene, seq); + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); + + return seq; +} + static Sequence *rna_Sequences_new_scene(ID *id, Editing *ed, ReportList *reports, const char *name, Scene *sce_seq, int channel, int start_frame) @@ -451,6 +472,23 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence"); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "new_mask", "rna_Sequences_new_mask"); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Add a new movie clip sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "mask", "Mask", "", "Mask to add"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel", + "The channel for the new sequence", 0, MAXSEQ - 1); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "", + "The start frame for the new sequence", -MAXFRAME, MAXFRAME); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence"); + RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "new_scene", "rna_Sequences_new_scene"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a new scene sequence"); diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index c90c7918660..01461aec08d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -81,7 +81,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); res = stackbuf->rect; - BKE_mask_rasterize(mask, sx, sy, res); + BKE_mask_rasterize(mask, sx, sy, res, TRUE, TRUE); /* pass on output and free */ out[0]->data = stackbuf; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ed023e42ea3..425baac25fd 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -4166,3 +4166,13 @@ EnumPropertyItem *RNA_movieclip_local_itemf(bContext *C, PointerRNA *ptr, Proper { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, TRUE); } + +EnumPropertyItem *RNA_mask_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) +{ + return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, FALSE); +} +EnumPropertyItem *RNA_mask_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) +{ + return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, TRUE); +} + -- cgit v1.2.3 From 186f542b791a97ea151bcc9a28b6a7edcfdb358b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 18:33:36 +0000 Subject: remove casts to short when allocating new imbufs. --- source/blender/blenkernel/intern/image.c | 8 ++++---- source/blender/blenkernel/intern/seqeffects.c | 6 +++--- source/blender/blenkernel/intern/sequencer.c | 9 ++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 9dc5463edab..d733092e792 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -119,8 +119,8 @@ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ if (ibuf->rect) { /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect); + tbuf1 = IMB_allocImBuf(ibuf->x, (ibuf->y >> 1), (unsigned char)32, (int)IB_rect); + tbuf2 = IMB_allocImBuf(ibuf->x, (ibuf->y >> 1), (unsigned char)32, (int)IB_rect); ibuf->x *= 2; @@ -147,8 +147,8 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ if (ibuf->rect) { /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect); + tbuf1 = IMB_allocImBuf(ibuf->x, (ibuf->y >> 1), (unsigned char)32, IB_rect); + tbuf2 = IMB_allocImBuf(ibuf->x, (ibuf->y >> 1), (unsigned char)32, IB_rect); ibuf->x *= 2; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 5e41c009fd3..6e5149d7924 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -77,7 +77,7 @@ static ImBuf *prepare_effect_imbufs( if (!ibuf1 && !ibuf2 && !ibuf3) { /* hmmm, global float option ? */ - out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect); + out = IMB_allocImBuf(x, y, 32, IB_rect); } else if ((ibuf1 && ibuf1->rect_float) || (ibuf2 && ibuf2->rect_float) || @@ -85,10 +85,10 @@ static ImBuf *prepare_effect_imbufs( { /* if any inputs are rectfloat, output is float too */ - out = IMB_allocImBuf((short)x, (short)y, 32, IB_rectfloat); + out = IMB_allocImBuf(x, y, 32, IB_rectfloat); } else { - out = IMB_allocImBuf((short)x, (short)y, 32, IB_rect); + out = IMB_allocImBuf(x, y, 32, IB_rect); } if (ibuf1 && !ibuf1->rect_float && out->rect_float) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 97733404b09..4f47a7f6f44 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1919,8 +1919,7 @@ static ImBuf *seq_render_effect_strip_impl( input[0] = seq->seq1; input[1] = seq->seq2; input[2] = seq->seq3; if (!sh.execute) { /* effect not supported in this version... */ - out = IMB_allocImBuf((short)context.rectx, - (short)context.recty, 32, IB_rect); + out = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); return out; } @@ -1997,7 +1996,7 @@ static ImBuf *seq_render_effect_strip_impl( } if (out == NULL) { - out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect); + out = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); } return out; @@ -2450,7 +2449,7 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) } if (ibuf == NULL) - ibuf = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect); + ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); if (ibuf->x != context.rectx || ibuf->y != context.recty) use_preprocess = TRUE; @@ -2565,7 +2564,7 @@ static ImBuf *seq_render_strip_stack( break; case EARLY_USE_INPUT_1: if (i == 0) { - out = IMB_allocImBuf((short)context.rectx, (short)context.recty, 32, IB_rect); + out = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); } break; case EARLY_DO_EFFECT: -- cgit v1.2.3 From 36db2a2cff58d3bd3dd0f7e8e0d2fbec36e32412 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 7 Jun 2012 19:24:49 +0000 Subject: initial support for editing masks in the sequencer, currently only draw the mask. --- source/blender/editors/mask/mask_edit.c | 28 +++++++---- .../editors/space_sequencer/sequencer_draw.c | 55 ++++++++++++++++++++++ .../editors/space_sequencer/space_sequencer.c | 26 +++++++++- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 9bfcd2a9886..6a59279934e 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -35,6 +35,8 @@ #include "BKE_context.h" #include "BKE_mask.h" +#include "DNA_scene_types.h" + #include "WM_api.h" #include "WM_types.h" @@ -132,16 +134,24 @@ void ED_mask_point_pos__reverse(bContext *C, float x, float y, float *xr, float void ED_mask_size(bContext *C, int *width, int *height) { - SpaceClip *sc = CTX_wm_space_clip(C); - - if (sc) { - ED_space_clip_mask_size(sc, width, height); - } - else { - /* possible other spaces from which mask editing is available */ - *width = 0; - *height = 0; + ScrArea *sa = CTX_wm_area(C); + if (sa && sa->spacedata.first) { + if (sa->spacetype == SPACE_CLIP) { + SpaceClip *sc = sa->spacedata.first; + ED_space_clip_mask_size(sc, width, height); + return; + } + else if (sa->spacetype == SPACE_SEQ) { + Scene *scene = CTX_data_scene(C); + *width = (scene->r.size * scene->r.xsch) / 100; + *height = (scene->r.size * scene->r.ysch) / 100; + return; + } } + + /* possible other spaces from which mask editing is available */ + *width = 0; + *height = 0; } void ED_mask_aspect(bContext *C, float *aspx, float *aspy) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index eb943451b1f..b674943b2dc 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -59,7 +59,9 @@ #include "ED_anim_api.h" #include "ED_markers.h" +#include "ED_mask.h" #include "ED_types.h" +#include "ED_space_api.h" #include "UI_interface.h" #include "UI_resources.h" @@ -984,6 +986,59 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* ortho at pixel level */ UI_view2d_view_restore(C); + + //if (sc->mode == SC_MODE_MASKEDIT) { + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + Sequence *seq_act = BKE_sequencer_active_get(scene); + + if (seq_act && seq_act->type == SEQ_TYPE_MASK && seq_act->mask) { + int x, y; + int width, height; + float zoomx, zoomy; + + /* frame image */ + float maxdim; + float xofs, yofs; + + /* find window pixel coordinates of origin */ + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); + + width = v2d->tot.xmax - v2d->tot.xmin; + height = v2d->tot.ymax - v2d->tot.ymin; + + zoomx = (float)(ar->winrct.xmax - ar->winrct.xmin + 1) / (float)((ar->v2d.cur.xmax - ar->v2d.cur.xmin)); + zoomy = (float)(ar->winrct.ymax - ar->winrct.ymin + 1) / (float)((ar->v2d.cur.ymax - ar->v2d.cur.ymin)); + + x += v2d->tot.xmin * zoomx; + y += v2d->tot.ymin * zoomy; + + /* frame the image */ + maxdim = maxf(width, height); + if (width == height) { + xofs = yofs = 0; + } + else if (width < height) { + xofs = ((height - width) / -2.0f) * zoomx; + yofs = 0.0f; + } + else { /* (width > height) */ + xofs = 0.0f; + yofs = ((width - height) / -2.0f) * zoomy; + } + + /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ + glPushMatrix(); + glTranslatef(x + xofs, y + yofs, 0); + glScalef(maxdim * zoomx, maxdim * zoomy, 0); + + ED_mask_draw((bContext *)C, 0, 0); // sc->mask_draw_flag, sc->mask_draw_type + + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + + glPopMatrix(); + } + } + } #if 0 diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index cc59a05b781..3643f92d334 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -33,6 +33,7 @@ #include #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "MEM_guardedalloc.h" @@ -380,6 +381,29 @@ static void sequencer_dropboxes(void) /* ************* end drop *********** */ +const char *sequencer_context_dir[] = {"edit_mask", NULL}; + +static int sequencer_context(const bContext *C, const char *member, bContextDataResult *result) +{ + Scene *scene = CTX_data_scene(C); + + if (CTX_data_dir(member)) { + CTX_data_dir_set(result, sequencer_context_dir); + + return TRUE; + } + else if (CTX_data_equals(member, "edit_mask")) { + Sequence *seq_act = BKE_sequencer_active_get(scene); + if (seq_act && seq_act->type == SEQ_TYPE_MASK && seq_act->mask) { + CTX_data_id_pointer_set(result, &seq_act->mask->id); + } + return TRUE; + } + + return FALSE; +} + + /* add handlers, stuff you only do once or on area/region changes */ static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar) { @@ -545,6 +569,7 @@ void ED_spacetype_sequencer(void) st->duplicate = sequencer_duplicate; st->operatortypes = sequencer_operatortypes; st->keymap = sequencer_keymap; + st->context = sequencer_context; st->dropboxes = sequencer_dropboxes; st->refresh = sequencer_refresh; @@ -597,4 +622,3 @@ void ED_spacetype_sequencer(void) sequencer_view3d_cb = ED_view3d_draw_offscreen_imbuf_simple; } } - -- cgit v1.2.3 From a6f3e15d6ec95e9649c08f50b41385ea293275e2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 05:46:00 +0000 Subject: - remove redundant NULL checks from mallocn's local linked list functions. - minor changes to warning cleanup. --- intern/guardedalloc/intern/mallocn.c | 12 +++++++++++- intern/raskter/raskter.c | 8 ++++---- source/blender/editors/mask/mask_add.c | 3 ++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index cad0e549060..4a30388c047 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -290,7 +290,9 @@ static void make_memhead_header(MemHead *memh, size_t len, const char *str) memt->tag3 = MEMTAG3; addtail(membase, &memh->next); - if (memh->next) memh->nextname = MEMNEXT(memh->next)->name; + if (memh->next) { + memh->nextname = MEMNEXT(memh->next)->name; + } totblock++; mem_in_use += len; @@ -681,8 +683,12 @@ static void addtail(volatile localListBase *listbase, void *vlink) { struct localLink *link = vlink; + /* for a generic API general error checks here is fine but + * the use here they will never be NULL */ +#if 0 if (link == NULL) return; if (listbase == NULL) return; +#endif link->next = NULL; link->prev = listbase->last; @@ -696,8 +702,12 @@ static void remlink(volatile localListBase *listbase, void *vlink) { struct localLink *link = vlink; + /* for a generic API general error checks here is fine but + * the use here they will never be NULL */ +#if 0 if (link == NULL) return; if (listbase == NULL) return; +#endif if (link->next) link->next->prev = link->prev; if (link->prev) link->prev->next = link->next; diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 26fec52dc80..9bf1779a608 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -170,7 +170,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) +static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) { int x_curr; /* current pixel position in X */ int y_curr; /* current scan line being drawn */ @@ -426,9 +426,9 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts, * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -int rast_scan_feather(struct r_fill_context *ctx, - float (*base_verts_f)[2], int num_base_verts, - struct poly_vert *feather_verts, float (*feather_verts_f)[2], int num_feather_verts) +static int rast_scan_feather(struct r_fill_context *ctx, + float (*base_verts_f)[2], int num_base_verts, + struct poly_vert *feather_verts, float (*feather_verts_f)[2], int num_feather_verts) { int x_curr; /* current pixel position in X */ int y_curr; /* current scan line being drawn */ diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index a8363524dd7..0bc9adb6577 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -411,7 +411,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float tangent_co[2]; int do_cyclic_correct = FALSE; int do_recalc_src = FALSE; /* when extruding from endpoints only */ - int do_prev = FALSE; /* use prev point rather then next?? */ + int do_prev; /* use prev point rather then next?? */ if (!masklay) { return FALSE; @@ -448,6 +448,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const do_recalc_src = TRUE; } else { + do_prev = FALSE; /* quiet warning */ /* should never get here */ BLI_assert(0); } -- cgit v1.2.3 From 26ca0008ee8081dfcd2e894613dc87c5b5f52c72 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 05:53:30 +0000 Subject: typo/style edits --- intern/guardedalloc/intern/mallocn.c | 8 ++++---- intern/raskter/raskter.c | 7 ++++--- source/blender/editors/space_outliner/outliner_tools.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index 4a30388c047..f1a83583715 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -683,8 +683,8 @@ static void addtail(volatile localListBase *listbase, void *vlink) { struct localLink *link = vlink; - /* for a generic API general error checks here is fine but - * the use here they will never be NULL */ + /* for a generic API error checks here is fine but + * the limited use here they will never be NULL */ #if 0 if (link == NULL) return; if (listbase == NULL) return; @@ -702,8 +702,8 @@ static void remlink(volatile localListBase *listbase, void *vlink) { struct localLink *link = vlink; - /* for a generic API general error checks here is fine but - * the use here they will never be NULL */ + /* for a generic API error checks here is fine but + * the limited use here they will never be NULL */ #if 0 if (link == NULL) return; if (listbase == NULL) return; diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 9bf1779a608..081a7c6bdbd 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -189,7 +189,8 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i * If the number of verts specified to render as a polygon is less than 3, * return immediately. Obviously we cant render a poly with sides < 3. The * return for this we set to 1, simply so it can be distinguished from the - * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter.cwhich is a failure to allocate memory. + * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter. + * which is a failure to allocate memory. */ if (num_verts < 3) { return(1); @@ -384,8 +385,8 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i int PLX_raskterize(float (*base_verts)[2], int num_base_verts, float *buf, int buf_x, int buf_y) { - int i; /* i: Loop counter. */ - struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ + int i; /* i: Loop counter. */ + struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct r_fill_context ctx = {0}; /* diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index e656b1242ab..3d01de1c67a 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -651,7 +651,7 @@ static EnumPropertyItem prop_group_op_types[] = { {0, "UNLINK", 0, "Unlink Group", ""}, {1, "LOCAL", 0, "Make Local Group", ""}, {2, "LINK", 0, "Link Group Objects to Scene", ""}, - {3, "INSTANCE", 0, "Instance Group in Scene", ""}, + {3, "INSTANCE", 0, "Instance Groups in Scene", ""}, {4, "TOGVIS", 0, "Toggle Visible Group", ""}, {5, "TOGSEL", 0, "Toggle Selectable", ""}, {6, "TOGREN", 0, "Toggle Renderable", ""}, -- cgit v1.2.3 From 0593651165f33e6f6f1a427affec10fa04e161cf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 06:04:29 +0000 Subject: code cleanup: assign values to enums in DNA --- source/blender/makesdna/DNA_action_types.h | 674 ++++++++++++++--------------- 1 file changed, 337 insertions(+), 337 deletions(-) diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 9cb5ca5da55..b61916f7bfa 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -50,37 +50,37 @@ struct GHash; /* Data point for motion path (mpv) */ typedef struct bMotionPathVert { - float co[3]; /* coordinates of point in 3D-space */ - int flag; /* quick settings */ + float co[3]; /* coordinates of point in 3D-space */ + int flag; /* quick settings */ } bMotionPathVert; /* bMotionPathVert->flag */ typedef enum eMotionPathVert_Flag { - /* vert is selected */ - MOTIONPATH_VERT_SEL = (1<<0) + /* vert is selected */ + MOTIONPATH_VERT_SEL = (1 << 0) } eMotionPathVert_Flag; /* ........ */ /* Motion Path data cache (mpath) - * - for elements providing transforms (i.e. Objects or PoseChannels) + * - for elements providing transforms (i.e. Objects or PoseChannels) */ typedef struct bMotionPath { - bMotionPathVert *points; /* path samples */ - int length; /* the number of cached verts */ + bMotionPathVert *points; /* path samples */ + int length; /* the number of cached verts */ - int start_frame; /* for drawing paths, the start frame number */ - int end_frame; /* for drawing paths, the end frame number */ + int start_frame; /* for drawing paths, the start frame number */ + int end_frame; /* for drawing paths, the end frame number */ - int flag; /* baking settings - eMotionPath_Flag */ + int flag; /* baking settings - eMotionPath_Flag */ } bMotionPath; /* bMotionPath->flag */ typedef enum eMotionPath_Flag { - /* (for bones) path represents the head of the bone */ - MOTIONPATH_FLAG_BHEAD = (1<<0), - /* motion path is being edited */ - MOTIONPATH_FLAG_EDIT = (1<<1) + /* (for bones) path represents the head of the bone */ + MOTIONPATH_FLAG_BHEAD = (1 << 0), + /* motion path is being edited */ + MOTIONPATH_FLAG_EDIT = (1 << 1) } eMotionPath_Flag; /* Visualisation General --------------------------- */ @@ -89,83 +89,83 @@ typedef enum eMotionPath_Flag { /* Animation Visualisation Settings (avs) */ typedef struct bAnimVizSettings { /* Onion-Skinning Settings ----------------- */ - int ghost_sf, ghost_ef; /* start and end frames of ghost-drawing range (only used for GHOST_TYPE_RANGE) */ - int ghost_bc, ghost_ac; /* number of frames before/after current frame to show */ + int ghost_sf, ghost_ef; /* start and end frames of ghost-drawing range (only used for GHOST_TYPE_RANGE) */ + int ghost_bc, ghost_ac; /* number of frames before/after current frame to show */ - short ghost_type; /* eOnionSkin_Types */ - short ghost_step; /* number of frames between each ghost shown (not for GHOST_TYPE_KEYS) */ + short ghost_type; /* eOnionSkin_Types */ + short ghost_step; /* number of frames between each ghost shown (not for GHOST_TYPE_KEYS) */ - short ghost_flag; /* eOnionSkin_Flag */ + short ghost_flag; /* eOnionSkin_Flag */ /* General Settings ------------------------ */ - short recalc; /* eAnimViz_RecalcFlags */ + short recalc; /* eAnimViz_RecalcFlags */ /* Motion Path Settings ------------------- */ - short path_type; /* eMotionPath_Types */ - short path_step; /* number of frames between points indicated on the paths */ + short path_type; /* eMotionPath_Types */ + short path_step; /* number of frames between points indicated on the paths */ - short path_viewflag; /* eMotionPaths_ViewFlag */ - short path_bakeflag; /* eMotionPaths_BakeFlag */ + short path_viewflag; /* eMotionPaths_ViewFlag */ + short path_bakeflag; /* eMotionPaths_BakeFlag */ - int path_sf, path_ef; /* start and end frames of path-calculation range */ - int path_bc, path_ac; /* number of frames before/after current frame to show */ + int path_sf, path_ef; /* start and end frames of path-calculation range */ + int path_bc, path_ac; /* number of frames before/after current frame to show */ } bAnimVizSettings; /* bAnimVizSettings->recalc */ typedef enum eAnimViz_RecalcFlags { - /* motionpaths need recalculating */ - ANIMVIZ_RECALC_PATHS = (1<<0) + /* motionpaths need recalculating */ + ANIMVIZ_RECALC_PATHS = (1 << 0) } eAnimViz_RecalcFlags; /* bAnimVizSettings->ghost_type */ typedef enum eOnionSkin_Types { - /* no ghosts at all */ + /* no ghosts at all */ GHOST_TYPE_NONE = 0, - /* around current frame */ - GHOST_TYPE_ACFRA, - /* show ghosts within the specified frame range */ - GHOST_TYPE_RANGE, - /* show ghosts on keyframes within the specified range only */ - GHOST_TYPE_KEYS + /* around current frame */ + GHOST_TYPE_ACFRA = 1, + /* show ghosts within the specified frame range */ + GHOST_TYPE_RANGE = 2, + /* show ghosts on keyframes within the specified range only */ + GHOST_TYPE_KEYS = 3 } eOnionSkin_Types; /* bAnimVizSettings->ghost_flag */ typedef enum eOnionSkin_Flag { - /* only show selected bones in ghosts */ - GHOST_FLAG_ONLYSEL = (1<<0) + /* only show selected bones in ghosts */ + GHOST_FLAG_ONLYSEL = (1 << 0) } eOnionSkin_Flag; /* bAnimVizSettings->path_type */ typedef enum eMotionPaths_Types { - /* show the paths along their entire ranges */ + /* show the paths along their entire ranges */ MOTIONPATH_TYPE_RANGE = 0, - /* only show the parts of the paths around the current frame */ - MOTIONPATH_TYPE_ACFRA + /* only show the parts of the paths around the current frame */ + MOTIONPATH_TYPE_ACFRA = 1, } eMotionPath_Types; /* bAnimVizSettings->path_viewflag */ typedef enum eMotionPaths_ViewFlag { - /* show frames on path */ - MOTIONPATH_VIEW_FNUMS = (1<<0), - /* show keyframes on path */ - MOTIONPATH_VIEW_KFRAS = (1<<1), - /* show keyframe/frame numbers */ - MOTIONPATH_VIEW_KFNOS = (1<<2), - /* find keyframes in whole action (instead of just in matching group name) */ - MOTIONPATH_VIEW_KFACT = (1<<3) + /* show frames on path */ + MOTIONPATH_VIEW_FNUMS = (1 << 0), + /* show keyframes on path */ + MOTIONPATH_VIEW_KFRAS = (1 << 1), + /* show keyframe/frame numbers */ + MOTIONPATH_VIEW_KFNOS = (1 << 2), + /* find keyframes in whole action (instead of just in matching group name) */ + MOTIONPATH_VIEW_KFACT = (1 << 3) } eMotionPath_ViewFlag; /* bAnimVizSettings->path_bakeflag */ typedef enum eMotionPaths_BakeFlag { - /* motion paths directly associated with this block of settings needs updating */ - MOTIONPATH_BAKE_NEEDS_RECALC = (1<<0), - /* for bones - calculate head-points for curves instead of tips */ - MOTIONPATH_BAKE_HEADS = (1<<1), - /* motion paths exist for AnimVizSettings instance - set when calc for first time, and unset when clearing */ - MOTIONPATH_BAKE_HAS_PATHS = (1<<2) + /* motion paths directly associated with this block of settings needs updating */ + MOTIONPATH_BAKE_NEEDS_RECALC = (1 << 0), + /* for bones - calculate head-points for curves instead of tips */ + MOTIONPATH_BAKE_HEADS = (1 << 1), + /* motion paths exist for AnimVizSettings instance - set when calc for first time, and unset when clearing */ + MOTIONPATH_BAKE_HAS_PATHS = (1 << 2) } eMotionPath_BakeFlag; /* ************************************************ */ @@ -179,142 +179,142 @@ typedef enum eMotionPaths_BakeFlag { * with respect to the restposition of Armature bones */ typedef struct bPoseChannel { - struct bPoseChannel *next, *prev; + struct bPoseChannel *next, *prev; - IDProperty *prop; /* User-Defined Properties on this PoseChannel */ + IDProperty *prop; /* User-Defined Properties on this PoseChannel */ - ListBase constraints;/* Constraints that act on this PoseChannel */ - char name[64]; /* need to match bone name length: MAXBONENAME */ + ListBase constraints; /* Constraints that act on this PoseChannel */ + char name[64]; /* need to match bone name length: MAXBONENAME */ - short flag; /* dynamic, for detecting transform changes */ - short ikflag; /* settings for IK bones */ - short protectflag; /* protect channels from being transformed */ - short agrp_index; /* index of action-group this bone belongs to (0 = default/no group) */ - char constflag; /* for quick detecting which constraints affect this channel */ - char selectflag; /* copy of bone flag, so you can work with library armatures, not for runtime use */ - char pad0[6]; + short flag; /* dynamic, for detecting transform changes */ + short ikflag; /* settings for IK bones */ + short protectflag; /* protect channels from being transformed */ + short agrp_index; /* index of action-group this bone belongs to (0 = default/no group) */ + char constflag; /* for quick detecting which constraints affect this channel */ + char selectflag; /* copy of bone flag, so you can work with library armatures, not for runtime use */ + char pad0[6]; - struct Bone *bone; /* set on read file or rebuild pose */ - struct bPoseChannel *parent; /* set on read file or rebuild pose */ - struct bPoseChannel *child; /* set on read file or rebuild pose, the 'ik' child, for b-bones */ - - struct ListBase iktree; /* "IK trees" - only while evaluating pose */ - struct ListBase siktree; /* Spline-IK "trees" - only while evaluating pose */ - - bMotionPath *mpath; /* motion path cache for this bone */ - struct Object *custom; /* draws custom object instead of default bone shape */ - struct bPoseChannel *custom_tx; /* odd feature, display with another bones transform. + struct Bone *bone; /* set on read file or rebuild pose */ + struct bPoseChannel *parent; /* set on read file or rebuild pose */ + struct bPoseChannel *child; /* set on read file or rebuild pose, the 'ik' child, for b-bones */ + + struct ListBase iktree; /* "IK trees" - only while evaluating pose */ + struct ListBase siktree; /* Spline-IK "trees" - only while evaluating pose */ + + bMotionPath *mpath; /* motion path cache for this bone */ + struct Object *custom; /* draws custom object instead of default bone shape */ + struct bPoseChannel *custom_tx; /* odd feature, display with another bones transform. * needed in rare cases for advanced rigs, * since the alternative is highly complicated - campbell */ - /* transforms - written in by actions or transform */ - float loc[3]; - float size[3]; - - /* rotations - written in by actions or transform (but only one representation gets used at any time) */ - float eul[3]; /* euler rotation */ - float quat[4]; /* quaternion rotation */ - float rotAxis[3], rotAngle; /* axis-angle rotation */ - short rotmode; /* eRotationModes - rotation representation to use */ - short pad; + /* transforms - written in by actions or transform */ + float loc[3]; + float size[3]; + + /* rotations - written in by actions or transform (but only one representation gets used at any time) */ + float eul[3]; /* euler rotation */ + float quat[4]; /* quaternion rotation */ + float rotAxis[3], rotAngle; /* axis-angle rotation */ + short rotmode; /* eRotationModes - rotation representation to use */ + short pad; - float chan_mat[4][4]; /* matrix result of loc/quat/size , and where we put deform in, see next line */ - float pose_mat[4][4]; /* constraints accumulate here. in the end, pose_mat = bone->arm_mat * chan_mat + float chan_mat[4][4]; /* matrix result of loc/quat/size , and where we put deform in, see next line */ + float pose_mat[4][4]; /* constraints accumulate here. in the end, pose_mat = bone->arm_mat * chan_mat * this matrix is object space */ - float constinv[4][4]; /* inverse result of constraints. + float constinv[4][4]; /* inverse result of constraints. * doesn't include effect of restposition, parent, and local transform*/ - float pose_head[3]; /* actually pose_mat[3] */ - float pose_tail[3]; /* also used for drawing help lines... */ + float pose_head[3]; /* actually pose_mat[3] */ + float pose_tail[3]; /* also used for drawing help lines... */ - float limitmin[3], limitmax[3]; /* DOF constraint, note! - these are stored in degrees, not radians */ - float stiffness[3]; /* DOF stiffness */ - float ikstretch; - float ikrotweight; /* weight of joint rotation constraint */ - float iklinweight; /* weight of joint stretch constraint */ + float limitmin[3], limitmax[3]; /* DOF constraint, note! - these are stored in degrees, not radians */ + float stiffness[3]; /* DOF stiffness */ + float ikstretch; + float ikrotweight; /* weight of joint rotation constraint */ + float iklinweight; /* weight of joint stretch constraint */ - void *temp; /* use for outliner */ + void *temp; /* use for outliner */ } bPoseChannel; /* PoseChannel (transform) flags */ typedef enum ePchan_Flag { - /* has transforms */ - POSE_LOC = (1<<0), - POSE_ROT = (1<<1), - POSE_SIZE = (1<<2), - /* old IK/cache stuff... */ - POSE_IK_MAT = (1<<3), - POSE_UNUSED2 = (1<<4), - POSE_UNUSED3 = (1<<5), - POSE_UNUSED4 = (1<<6), - POSE_UNUSED5 = (1<<7), - /* has Standard IK */ - POSE_HAS_IK = (1<<8), - /* IK/Pose solving*/ - POSE_CHAIN = (1<<9), - POSE_DONE = (1<<10), - /* visualisation */ - POSE_KEY = (1<<11), - POSE_STRIDE = (1<<12), - /* standard IK solving */ - POSE_IKTREE = (1<<13), - /* has Spline IK */ - POSE_HAS_IKS = (1<<14), - /* spline IK solving */ - POSE_IKSPLINE = (1<<15) + /* has transforms */ + POSE_LOC = (1 << 0), + POSE_ROT = (1 << 1), + POSE_SIZE = (1 << 2), + /* old IK/cache stuff... */ + POSE_IK_MAT = (1 << 3), + POSE_UNUSED2 = (1 << 4), + POSE_UNUSED3 = (1 << 5), + POSE_UNUSED4 = (1 << 6), + POSE_UNUSED5 = (1 << 7), + /* has Standard IK */ + POSE_HAS_IK = (1 << 8), + /* IK/Pose solving*/ + POSE_CHAIN = (1 << 9), + POSE_DONE = (1 << 10), + /* visualisation */ + POSE_KEY = (1 << 11), + POSE_STRIDE = (1 << 12), + /* standard IK solving */ + POSE_IKTREE = (1 << 13), + /* has Spline IK */ + POSE_HAS_IKS = (1 << 14), + /* spline IK solving */ + POSE_IKSPLINE = (1 << 15) } ePchan_Flag; /* PoseChannel constflag (constraint detection) */ typedef enum ePchan_ConstFlag { - PCHAN_HAS_IK = (1<<0), - PCHAN_HAS_CONST = (1<<1), - /* only used for drawing Posemode, not stored in channel */ - PCHAN_HAS_ACTION = (1<<2), - PCHAN_HAS_TARGET = (1<<3), - /* only for drawing Posemode too */ - PCHAN_HAS_STRIDE = (1<<4), - /* spline IK */ - PCHAN_HAS_SPLINEIK = (1<<5) + PCHAN_HAS_IK = (1 << 0), + PCHAN_HAS_CONST = (1 << 1), + /* only used for drawing Posemode, not stored in channel */ + PCHAN_HAS_ACTION = (1 << 2), + PCHAN_HAS_TARGET = (1 << 3), + /* only for drawing Posemode too */ + PCHAN_HAS_STRIDE = (1 << 4), + /* spline IK */ + PCHAN_HAS_SPLINEIK = (1 << 5) } ePchan_ConstFlag; /* PoseChannel->ikflag */ typedef enum ePchan_IkFlag { - BONE_IK_NO_XDOF = (1<<0), - BONE_IK_NO_YDOF = (1<<1), - BONE_IK_NO_ZDOF = (1<<2), + BONE_IK_NO_XDOF = (1 << 0), + BONE_IK_NO_YDOF = (1 << 1), + BONE_IK_NO_ZDOF = (1 << 2), - BONE_IK_XLIMIT = (1<<3), - BONE_IK_YLIMIT = (1<<4), - BONE_IK_ZLIMIT = (1<<5), - - BONE_IK_ROTCTL = (1<<6), - BONE_IK_LINCTL = (1<<7), + BONE_IK_XLIMIT = (1 << 3), + BONE_IK_YLIMIT = (1 << 4), + BONE_IK_ZLIMIT = (1 << 5), + + BONE_IK_ROTCTL = (1 << 6), + BONE_IK_LINCTL = (1 << 7), - BONE_IK_NO_XDOF_TEMP = (1<<10), - BONE_IK_NO_YDOF_TEMP = (1<<11), - BONE_IK_NO_ZDOF_TEMP = (1<<12) + BONE_IK_NO_XDOF_TEMP = (1 << 10), + BONE_IK_NO_YDOF_TEMP = (1 << 11), + BONE_IK_NO_ZDOF_TEMP = (1 << 12) } ePchan_IkFlag; /* PoseChannel->rotmode and Object->rotmode */ typedef enum eRotationModes { - /* quaternion rotations (default, and for older Blender versions) */ - ROT_MODE_QUAT = 0, - /* euler rotations - keep in sync with enum in BLI_math.h */ - ROT_MODE_EUL = 1, /* Blender 'default' (classic) - must be as 1 to sync with BLI_math_rotation.h defines */ + /* quaternion rotations (default, and for older Blender versions) */ + ROT_MODE_QUAT = 0, + /* euler rotations - keep in sync with enum in BLI_math.h */ + ROT_MODE_EUL = 1, /* Blender 'default' (classic) - must be as 1 to sync with BLI_math_rotation.h defines */ ROT_MODE_XYZ = 1, - ROT_MODE_XZY, - ROT_MODE_YXZ, - ROT_MODE_YZX, - ROT_MODE_ZXY, - ROT_MODE_ZYX, + ROT_MODE_XZY = 2, + ROT_MODE_YXZ = 3, + ROT_MODE_YZX = 4, + ROT_MODE_ZXY = 5, + ROT_MODE_ZYX = 6, /* NOTE: space is reserved here for 18 other possible * euler rotation orders not implemented */ - /* axis angle rotations */ + /* axis angle rotations */ ROT_MODE_AXISANGLE = -1, - ROT_MODE_MIN = ROT_MODE_AXISANGLE, /* sentinel for Py API */ + ROT_MODE_MIN = ROT_MODE_AXISANGLE, /* sentinel for Py API */ ROT_MODE_MAX = ROT_MODE_ZYX } eRotationModes; @@ -326,46 +326,46 @@ typedef enum eRotationModes { * though there is a define for it (hack for the outliner). */ typedef struct bPose { - ListBase chanbase; /* list of pose channels, PoseBones in RNA */ - struct GHash *chanhash; /* ghash for quicker string lookups */ + ListBase chanbase; /* list of pose channels, PoseBones in RNA */ + struct GHash *chanhash; /* ghash for quicker string lookups */ short flag, pad; - unsigned int proxy_layer; /* proxy layer: copy from armature, gets synced */ + unsigned int proxy_layer; /* proxy layer: copy from armature, gets synced */ int pad1; - float ctime; /* local action time of this pose */ - float stride_offset[3]; /* applied to object */ - float cyclic_offset[3]; /* result of match and cycles, applied in BKE_pose_where_is() */ + float ctime; /* local action time of this pose */ + float stride_offset[3]; /* applied to object */ + float cyclic_offset[3]; /* result of match and cycles, applied in BKE_pose_where_is() */ - ListBase agroups; /* list of bActionGroups */ + ListBase agroups; /* list of bActionGroups */ - int active_group; /* index of active group (starts from 1) */ - int iksolver; /* ik solver to use, see ePose_IKSolverType */ - void *ikdata; /* temporary IK data, depends on the IK solver. Not saved in file */ - void *ikparam; /* IK solver parameters, structure depends on iksolver */ + int active_group; /* index of active group (starts from 1) */ + int iksolver; /* ik solver to use, see ePose_IKSolverType */ + void *ikdata; /* temporary IK data, depends on the IK solver. Not saved in file */ + void *ikparam; /* IK solver parameters, structure depends on iksolver */ - bAnimVizSettings avs; /* settings for visualization of bone animation */ + bAnimVizSettings avs; /* settings for visualization of bone animation */ char proxy_act_bone[64]; /* proxy active bone name, MAXBONENAME */ } bPose; /* Pose->flag */ typedef enum ePose_Flags { - /* results in BKE_pose_rebuild being called */ - POSE_RECALC = (1<<0), - /* prevents any channel from getting overridden by anim from IPO */ - POSE_LOCKED = (1<<1), - /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ - POSE_DO_UNLOCK = (1<<2), - /* pose has constraints which depend on time (used when depsgraph updates for a new frame) */ - POSE_CONSTRAINTS_TIMEDEPEND = (1<<3), - /* recalculate bone paths */ - POSE_RECALCPATHS = (1<<4), - /* set by BKE_pose_rebuild to give a chance to the IK solver to rebuild IK tree */ - POSE_WAS_REBUILT = (1<<5), - /* set by game_copy_pose to indicate that this pose is used in the game engine */ - POSE_GAME_ENGINE = (1<<6) + /* results in BKE_pose_rebuild being called */ + POSE_RECALC = (1 << 0), + /* prevents any channel from getting overridden by anim from IPO */ + POSE_LOCKED = (1 << 1), + /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ + POSE_DO_UNLOCK = (1 << 2), + /* pose has constraints which depend on time (used when depsgraph updates for a new frame) */ + POSE_CONSTRAINTS_TIMEDEPEND = (1 << 3), + /* recalculate bone paths */ + POSE_RECALCPATHS = (1 << 4), + /* set by BKE_pose_rebuild to give a chance to the IK solver to rebuild IK tree */ + POSE_WAS_REBUILT = (1 << 5), + /* set by game_copy_pose to indicate that this pose is used in the game engine */ + POSE_GAME_ENGINE = (1 << 6) } ePose_Flags; /* IK Solvers ------------------------------------ */ @@ -378,37 +378,37 @@ typedef enum ePose_IKSolverType { /* header for all bPose->ikparam structures */ typedef struct bIKParam { - int iksolver; + int iksolver; } bIKParam; /* bPose->ikparam when bPose->iksolver=1 */ typedef struct bItasc { - int iksolver; + int iksolver; float precision; short numiter; short numstep; float minstep; float maxstep; - short solver; + short solver; short flag; float feedback; - float maxvel; /* max velocity to SDLS solver */ - float dampmax; /* maximum damping for DLS solver */ - float dampeps; /* threshold of singular value from which the damping start progressively */ + float maxvel; /* max velocity to SDLS solver */ + float dampmax; /* maximum damping for DLS solver */ + float dampeps; /* threshold of singular value from which the damping start progressively */ } bItasc; /* bItasc->flag */ typedef enum eItasc_Flags { - ITASC_AUTO_STEP = (1<<0), - ITASC_INITIAL_REITERATION = (1<<1), - ITASC_REITERATION = (1<<2), - ITASC_SIMULATION = (1<<3) + ITASC_AUTO_STEP = (1 << 0), + ITASC_INITIAL_REITERATION = (1 << 1), + ITASC_REITERATION = (1 << 2), + ITASC_SIMULATION = (1 << 3) } eItasc_Flags; /* bItasc->solver */ typedef enum eItasc_Solver { - ITASC_SOLVER_SDLS = 0, /* selective damped least square, suitable for CopyPose constraint */ - ITASC_SOLVER_DLS /* damped least square with numerical filtering of damping */ + ITASC_SOLVER_SDLS = 0, /* selective damped least square, suitable for CopyPose constraint */ + ITASC_SOLVER_DLS = 1, /* damped least square with numerical filtering of damping */ } eItasc_Solver; /* ************************************************ */ @@ -434,34 +434,34 @@ typedef enum eItasc_Solver { typedef struct bActionGroup { struct bActionGroup *next, *prev; - ListBase channels; /* Note: this must not be touched by standard listbase functions which would clear links to other channels */ + ListBase channels; /* Note: this must not be touched by standard listbase functions which would clear links to other channels */ - int flag; /* settings for this action-group */ - int customCol; /* index of custom color set to use when used for bones (0=default - used for all old files, -1=custom set) */ - char name[64]; /* name of the group */ + int flag; /* settings for this action-group */ + int customCol; /* index of custom color set to use when used for bones (0=default - used for all old files, -1=custom set) */ + char name[64]; /* name of the group */ - ThemeWireColor cs; /* color set to use when customCol == -1 */ + ThemeWireColor cs; /* color set to use when customCol == -1 */ } bActionGroup; /* Action Group flags */ typedef enum eActionGroup_Flag { - /* group is selected */ - AGRP_SELECTED = (1<<0), - /* group is 'active' / last selected one */ - AGRP_ACTIVE = (1<<1), - /* keyframes/channels belonging to it cannot be edited */ - AGRP_PROTECTED = (1<<2), - /* for UI (DopeSheet), sub-channels are shown */ - AGRP_EXPANDED = (1<<3), - /* sub-channels are not evaluated */ - AGRP_MUTED = (1<<4), - /* sub-channels are not visible in Graph Editor */ - AGRP_NOTVISIBLE = (1<<5), - /* for UI (Graph Editor), sub-channels are shown */ - AGRP_EXPANDED_G = (1<<6), - - AGRP_TEMP = (1<<30), - AGRP_MOVED = (1<<31) + /* group is selected */ + AGRP_SELECTED = (1 << 0), + /* group is 'active' / last selected one */ + AGRP_ACTIVE = (1 << 1), + /* keyframes/channels belonging to it cannot be edited */ + AGRP_PROTECTED = (1 << 2), + /* for UI (DopeSheet), sub-channels are shown */ + AGRP_EXPANDED = (1 << 3), + /* sub-channels are not evaluated */ + AGRP_MUTED = (1 << 4), + /* sub-channels are not visible in Graph Editor */ + AGRP_NOTVISIBLE = (1 << 5), + /* for UI (Graph Editor), sub-channels are shown */ + AGRP_EXPANDED_G = (1 << 6), + + AGRP_TEMP = (1 << 30), + AGRP_MOVED = (1 << 31) } eActionGroup_Flag; @@ -478,31 +478,31 @@ typedef enum eActionGroup_Flag { * affects a group of related settings (as defined by the user). */ typedef struct bAction { - ID id; /* ID-serialisation for relinking */ + ID id; /* ID-serialisation for relinking */ - ListBase curves; /* function-curves (FCurve) */ - ListBase chanbase; /* legacy data - Action Channels (bActionChannel) in pre-2.5 animation system */ - ListBase groups; /* groups of function-curves (bActionGroup) */ - ListBase markers; /* markers local to the Action (used to provide Pose-Libraries) */ + ListBase curves; /* function-curves (FCurve) */ + ListBase chanbase; /* legacy data - Action Channels (bActionChannel) in pre-2.5 animation system */ + ListBase groups; /* groups of function-curves (bActionGroup) */ + ListBase markers; /* markers local to the Action (used to provide Pose-Libraries) */ - int flag; /* settings for this action */ - int active_marker; /* index of the active marker */ + int flag; /* settings for this action */ + int active_marker; /* index of the active marker */ - int idroot; /* type of ID-blocks that action can be assigned to (if 0, will be set to whatever ID first evaluates it) */ + int idroot; /* type of ID-blocks that action can be assigned to (if 0, will be set to whatever ID first evaluates it) */ int pad; } bAction; /* Flags for the action */ typedef enum eAction_Flags { - /* flags for displaying in UI */ - ACT_COLLAPSED = (1<<0), - ACT_SELECTED = (1<<1), - - /* flags for evaluation/editing */ - ACT_MUTED = (1<<9), - ACT_PROTECTED = (1<<10), - ACT_DISABLED = (1<<11) + /* flags for displaying in UI */ + ACT_COLLAPSED = (1 << 0), + ACT_SELECTED = (1 << 1), + + /* flags for evaluation/editing */ + ACT_MUTED = (1 << 9), + ACT_PROTECTED = (1 << 10), + ACT_DISABLED = (1 << 11) } eAction_Flags; @@ -511,67 +511,67 @@ typedef enum eAction_Flags { /* Storage for Dopesheet/Grease-Pencil Editor data */ typedef struct bDopeSheet { - ID *source; /* currently ID_SCE (for Dopesheet), and ID_SC (for Grease Pencil) */ - ListBase chanbase; /* cache for channels (only initialized when pinned) */ // XXX not used! + ID *source; /* currently ID_SCE (for Dopesheet), and ID_SC (for Grease Pencil) */ + ListBase chanbase; /* cache for channels (only initialized when pinned) */ // XXX not used! - struct Group *filter_grp; /* object group for ADS_FILTER_ONLYOBGROUP filtering option */ - char searchstr[64]; /* string to search for in displayed names of F-Curves for ADS_FILTER_BY_FCU_NAME filtering option */ + struct Group *filter_grp; /* object group for ADS_FILTER_ONLYOBGROUP filtering option */ + char searchstr[64]; /* string to search for in displayed names of F-Curves for ADS_FILTER_BY_FCU_NAME filtering option */ - int filterflag; /* flags to use for filtering data */ - int flag; /* standard flags */ + int filterflag; /* flags to use for filtering data */ + int flag; /* standard flags */ - int renameIndex; /* index+1 of channel to rename - only gets set by renaming operator */ + int renameIndex; /* index+1 of channel to rename - only gets set by renaming operator */ int pad; } bDopeSheet; /* DopeSheet filter-flag */ typedef enum eDopeSheet_FilterFlag { - /* general filtering */ - ADS_FILTER_ONLYSEL = (1<<0), /* only include channels relating to selected data */ - - /* temporary filters */ - ADS_FILTER_ONLYDRIVERS = (1<<1), /* for 'Drivers' editor - only include Driver data from AnimData */ - ADS_FILTER_ONLYNLA = (1<<2), /* for 'NLA' editor - only include NLA data from AnimData */ - ADS_FILTER_SELEDIT = (1<<3), /* for Graph Editor - used to indicate whether to include a filtering flag or not */ - - /* general filtering 2 */ - ADS_FILTER_SUMMARY = (1<<4), /* for 'DopeSheet' Editors - include 'summary' line */ - ADS_FILTER_ONLYOBGROUP = (1<<5), /* only the objects in the specified object group get used */ - - /* datatype-based filtering */ - ADS_FILTER_NOSHAPEKEYS = (1<<6), - ADS_FILTER_NOMESH = (1<<7), - ADS_FILTER_NOOBJ = (1<<8), /* for animdata on object level, if we only want to concentrate on materials/etc. */ - ADS_FILTER_NOLAT = (1<<9), - ADS_FILTER_NOCAM = (1<<10), - ADS_FILTER_NOMAT = (1<<11), - ADS_FILTER_NOLAM = (1<<12), - ADS_FILTER_NOCUR = (1<<13), - ADS_FILTER_NOWOR = (1<<14), - ADS_FILTER_NOSCE = (1<<15), - ADS_FILTER_NOPART = (1<<16), - ADS_FILTER_NOMBA = (1<<17), - ADS_FILTER_NOARM = (1<<18), - ADS_FILTER_NONTREE = (1<<19), - ADS_FILTER_NOTEX = (1<<20), - ADS_FILTER_NOSPK = (1<<21), - - /* NLA-specific filters */ - ADS_FILTER_NLA_NOACT = (1<<25), /* if the AnimData block has no NLA data, don't include to just show Action-line */ - - /* general filtering 3 */ - ADS_FILTER_INCL_HIDDEN = (1<<26), /* include 'hidden' channels too (i.e. those from hidden Objects/Bones) */ - ADS_FILTER_BY_FCU_NAME = (1<<27), /* for F-Curves, filter by the displayed name (i.e. to isolate all Location curves only) */ - - /* combination filters (some only used at runtime) */ - ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM|ADS_FILTER_NOMAT|ADS_FILTER_NOLAM|ADS_FILTER_NOCUR|ADS_FILTER_NOPART|ADS_FILTER_NOARM|ADS_FILTER_NOSPK) + /* general filtering */ + ADS_FILTER_ONLYSEL = (1 << 0), /* only include channels relating to selected data */ + + /* temporary filters */ + ADS_FILTER_ONLYDRIVERS = (1 << 1), /* for 'Drivers' editor - only include Driver data from AnimData */ + ADS_FILTER_ONLYNLA = (1 << 2), /* for 'NLA' editor - only include NLA data from AnimData */ + ADS_FILTER_SELEDIT = (1 << 3), /* for Graph Editor - used to indicate whether to include a filtering flag or not */ + + /* general filtering 2 */ + ADS_FILTER_SUMMARY = (1 << 4), /* for 'DopeSheet' Editors - include 'summary' line */ + ADS_FILTER_ONLYOBGROUP = (1 << 5), /* only the objects in the specified object group get used */ + + /* datatype-based filtering */ + ADS_FILTER_NOSHAPEKEYS = (1 << 6), + ADS_FILTER_NOMESH = (1 << 7), + ADS_FILTER_NOOBJ = (1 << 8), /* for animdata on object level, if we only want to concentrate on materials/etc. */ + ADS_FILTER_NOLAT = (1 << 9), + ADS_FILTER_NOCAM = (1 << 10), + ADS_FILTER_NOMAT = (1 << 11), + ADS_FILTER_NOLAM = (1 << 12), + ADS_FILTER_NOCUR = (1 << 13), + ADS_FILTER_NOWOR = (1 << 14), + ADS_FILTER_NOSCE = (1 << 15), + ADS_FILTER_NOPART = (1 << 16), + ADS_FILTER_NOMBA = (1 << 17), + ADS_FILTER_NOARM = (1 << 18), + ADS_FILTER_NONTREE = (1 << 19), + ADS_FILTER_NOTEX = (1 << 20), + ADS_FILTER_NOSPK = (1 << 21), + + /* NLA-specific filters */ + ADS_FILTER_NLA_NOACT = (1 << 25), /* if the AnimData block has no NLA data, don't include to just show Action-line */ + + /* general filtering 3 */ + ADS_FILTER_INCL_HIDDEN = (1 << 26), /* include 'hidden' channels too (i.e. those from hidden Objects/Bones) */ + ADS_FILTER_BY_FCU_NAME = (1 << 27), /* for F-Curves, filter by the displayed name (i.e. to isolate all Location curves only) */ + + /* combination filters (some only used at runtime) */ + ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM | ADS_FILTER_NOMAT | ADS_FILTER_NOLAM | ADS_FILTER_NOCUR | ADS_FILTER_NOPART | ADS_FILTER_NOARM | ADS_FILTER_NOSPK) } eDopeSheet_FilterFlag; /* DopeSheet general flags */ typedef enum eDopeSheet_Flag { - ADS_FLAG_SUMMARY_COLLAPSED = (1<<0), /* when summary is shown, it is collapsed, so all other channels get hidden */ - ADS_FLAG_SHOW_DBFILTERS = (1<<1) /* show filters for datablocks */ + ADS_FLAG_SUMMARY_COLLAPSED = (1 << 0), /* when summary is shown, it is collapsed, so all other channels get hidden */ + ADS_FLAG_SHOW_DBFILTERS = (1 << 1) /* show filters for datablocks */ } eDopeSheet_Flag; @@ -579,72 +579,72 @@ typedef enum eDopeSheet_Flag { /* Action Editor Space. This is defined here instead of in DNA_space_types.h */ typedef struct SpaceAction { struct SpaceLink *next, *prev; - ListBase regionbase; /* storage of regions for inactive spaces */ + ListBase regionbase; /* storage of regions for inactive spaces */ int spacetype; float blockscale; short blockhandler[8]; - View2D v2d DNA_DEPRECATED; /* copied to region */ + View2D v2d DNA_DEPRECATED; /* copied to region */ - bAction *action; /* the currently active action */ - bDopeSheet ads; /* the currently active context (when not showing action) */ + bAction *action; /* the currently active action */ + bDopeSheet ads; /* the currently active context (when not showing action) */ - char mode, autosnap; /* mode: editing context; autosnap: automatic keyframe snapping mode */ - short flag; /* flag: bitmapped settings; */ - float timeslide; /* for Time-Slide transform mode drawing - current frame? */ + char mode, autosnap; /* mode: editing context; autosnap: automatic keyframe snapping mode */ + short flag; /* flag: bitmapped settings; */ + float timeslide; /* for Time-Slide transform mode drawing - current frame? */ } SpaceAction; /* SpaceAction flag */ typedef enum eSAction_Flag { - /* during transform (only set for TimeSlide) */ - SACTION_MOVING = (1<<0), - /* show sliders */ - SACTION_SLIDERS = (1<<1), - /* draw time in seconds instead of time in frames */ - SACTION_DRAWTIME = (1<<2), - /* don't filter action channels according to visibility */ + /* during transform (only set for TimeSlide) */ + SACTION_MOVING = (1 << 0), + /* show sliders */ + SACTION_SLIDERS = (1 << 1), + /* draw time in seconds instead of time in frames */ + SACTION_DRAWTIME = (1 << 2), + /* don't filter action channels according to visibility */ //SACTION_NOHIDE = (1<<3), // XXX depreceated... old animation system - /* don't kill overlapping keyframes after transform */ - SACTION_NOTRANSKEYCULL = (1<<4), - /* don't include keyframes that are out of view */ + /* don't kill overlapping keyframes after transform */ + SACTION_NOTRANSKEYCULL = (1 << 4), + /* don't include keyframes that are out of view */ //SACTION_HORIZOPTIMISEON = (1<<5), // XXX depreceated... old irrelevant trick - /* show pose-markers (local to action) in Action Editor mode */ - SACTION_POSEMARKERS_SHOW = (1<<6), - /* don't draw action channels using group colors (where applicable) */ - SACTION_NODRAWGCOLORS = (1<<7), - /* don't draw current frame number beside frame indicator */ - SACTION_NODRAWCFRANUM = (1<<8), - /* temporary flag to force channel selections to be synced with main */ - SACTION_TEMP_NEEDCHANSYNC = (1<<9), - /* don't perform realtime updates */ - SACTION_NOREALTIMEUPDATES = (1<<10), - /* move markers as well as keyframes */ - SACTION_MARKERS_MOVE = (1<<11) + /* show pose-markers (local to action) in Action Editor mode */ + SACTION_POSEMARKERS_SHOW = (1 << 6), + /* don't draw action channels using group colors (where applicable) */ + SACTION_NODRAWGCOLORS = (1 << 7), + /* don't draw current frame number beside frame indicator */ + SACTION_NODRAWCFRANUM = (1 << 8), + /* temporary flag to force channel selections to be synced with main */ + SACTION_TEMP_NEEDCHANSYNC = (1 << 9), + /* don't perform realtime updates */ + SACTION_NOREALTIMEUPDATES = (1 << 10), + /* move markers as well as keyframes */ + SACTION_MARKERS_MOVE = (1 << 11) } eSAction_Flag; /* SpaceAction Mode Settings */ typedef enum eAnimEdit_Context { - /* action on the active object */ - SACTCONT_ACTION = 0, - /* list of all shapekeys on the active object, linked with their F-Curves */ - SACTCONT_SHAPEKEY, - /* editing of gpencil data */ - SACTCONT_GPENCIL, - /* dopesheet (default) */ - SACTCONT_DOPESHEET + /* action on the active object */ + SACTCONT_ACTION = 0, + /* list of all shapekeys on the active object, linked with their F-Curves */ + SACTCONT_SHAPEKEY = 1, + /* editing of gpencil data */ + SACTCONT_GPENCIL = 2, + /* dopesheet (default) */ + SACTCONT_DOPESHEET = 3 } eAnimEdit_Context; /* SpaceAction AutoSnap Settings (also used by other Animation Editors) */ typedef enum eAnimEdit_AutoSnap { - /* no auto-snap */ - SACTSNAP_OFF = 0, - /* snap to 1.0 frame/second intervals */ - SACTSNAP_STEP, - /* snap to actual frames/seconds (nla-action time) */ - SACTSNAP_FRAME, - /* snap to nearest marker */ - SACTSNAP_MARKER + /* no auto-snap */ + SACTSNAP_OFF = 0, + /* snap to 1.0 frame/second intervals */ + SACTSNAP_STEP = 1, + /* snap to actual frames/seconds (nla-action time) */ + SACTSNAP_FRAME = 2, + /* snap to nearest marker */ + SACTSNAP_MARKER = 3 } eAnimEdit_AutoSnap; @@ -652,7 +652,7 @@ typedef enum eAnimEdit_AutoSnap { /* Legacy Data */ /* WARNING: Action Channels are now depreceated... they were part of the old animation system! - * (ONLY USED FOR DO_VERSIONS...) + * (ONLY USED FOR DO_VERSIONS...) * * Action Channels belong to Actions. They are linked with an IPO block, and can also own * Constraint Channels in certain situations. @@ -663,27 +663,27 @@ typedef enum eAnimEdit_AutoSnap { * to the position of the group in the list, and their position within the group. */ typedef struct bActionChannel { - struct bActionChannel *next, *prev; - bActionGroup *grp; /* Action Group this Action Channel belongs to */ + struct bActionChannel *next, *prev; + bActionGroup *grp; /* Action Group this Action Channel belongs to */ - struct Ipo *ipo; /* IPO block this action channel references */ - ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */ + struct Ipo *ipo; /* IPO block this action channel references */ + ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */ - int flag; /* settings accessed via bitmapping */ - char name[64]; /* channel name, MAX_NAME */ - int temp; /* temporary setting - may be used to indicate group that channel belongs to during syncing */ + int flag; /* settings accessed via bitmapping */ + char name[64]; /* channel name, MAX_NAME */ + int temp; /* temporary setting - may be used to indicate group that channel belongs to during syncing */ } bActionChannel; /* Action Channel flags (ONLY USED FOR DO_VERSIONS...) */ typedef enum ACHAN_FLAG { - ACHAN_SELECTED = (1<<0), - ACHAN_HILIGHTED = (1<<1), - ACHAN_HIDDEN = (1<<2), - ACHAN_PROTECTED = (1<<3), - ACHAN_EXPANDED = (1<<4), - ACHAN_SHOWIPO = (1<<5), - ACHAN_SHOWCONS = (1<<6), - ACHAN_MOVED = (1<<31) + ACHAN_SELECTED = (1 << 0), + ACHAN_HILIGHTED = (1 << 1), + ACHAN_HIDDEN = (1 << 2), + ACHAN_PROTECTED = (1 << 3), + ACHAN_EXPANDED = (1 << 4), + ACHAN_SHOWIPO = (1 << 5), + ACHAN_SHOWCONS = (1 << 6), + ACHAN_MOVED = (1 << 31) } ACHAN_FLAG; #endif -- cgit v1.2.3 From b0c868c3b38663817678ae198ad84e7369d7957c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 06:11:24 +0000 Subject: number enums --- source/blender/editors/include/ED_anim_api.h | 38 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4f24d254cbf..d91b29bb281 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -89,15 +89,15 @@ typedef struct bAnimContext { /* Main Data container types */ typedef enum eAnimCont_Types { - ANIMCONT_NONE = 0, /* invalid or no data */ - ANIMCONT_ACTION, /* action (bAction) */ - ANIMCONT_SHAPEKEY, /* shapekey (Key) */ - ANIMCONT_GPENCIL, /* grease pencil (screen) */ - ANIMCONT_DOPESHEET, /* dopesheet (bDopesheet) */ - ANIMCONT_FCURVES, /* animation F-Curves (bDopesheet) */ - ANIMCONT_DRIVERS, /* drivers (bDopesheet) */ - ANIMCONT_NLA, /* nla (bDopesheet) */ - ANIMCONT_CHANNEL /* animation channel (bAnimListElem) */ + ANIMCONT_NONE = 0, /* invalid or no data */ + ANIMCONT_ACTION = 1, /* action (bAction) */ + ANIMCONT_SHAPEKEY = 2, /* shapekey (Key) */ + ANIMCONT_GPENCIL = 3, /* grease pencil (screen) */ + ANIMCONT_DOPESHEET = 4, /* dopesheet (bDopesheet) */ + ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */ + ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */ + ANIMCONT_NLA = 7, /* nla (bDopesheet) */ + ANIMCONT_CHANNEL = 8 /* animation channel (bAnimListElem) */ } eAnimCont_Types; /* --------------- Channels -------------------- */ @@ -341,20 +341,20 @@ short ANIM_animdata_context_getdata(bAnimContext *ac); /* flag-setting behavior */ typedef enum eAnimChannels_SetFlag { - ACHANNEL_SETFLAG_CLEAR = 0, /* turn off */ - ACHANNEL_SETFLAG_ADD, /* turn on */ - ACHANNEL_SETFLAG_INVERT, /* on->off, off->on */ - ACHANNEL_SETFLAG_TOGGLE /* some on -> all off // all on */ + ACHANNEL_SETFLAG_CLEAR = 0, /* turn off */ + ACHANNEL_SETFLAG_ADD = 1, /* turn on */ + ACHANNEL_SETFLAG_INVERT = 2, /* on->off, off->on */ + ACHANNEL_SETFLAG_TOGGLE = 3 /* some on -> all off // all on */ } eAnimChannels_SetFlag; /* types of settings for AnimChannels */ typedef enum eAnimChannel_Settings { - ACHANNEL_SETTING_SELECT = 0, - ACHANNEL_SETTING_PROTECT, // warning: for drawing UI's, need to check if this is off (maybe inverse this later) - ACHANNEL_SETTING_MUTE, - ACHANNEL_SETTING_EXPAND, - ACHANNEL_SETTING_VISIBLE, /* only for Graph Editor */ - ACHANNEL_SETTING_SOLO /* only for NLA Tracks */ + ACHANNEL_SETTING_SELECT = 0, + ACHANNEL_SETTING_PROTECT = 1, /* warning: for drawing UI's, need to check if this is off (maybe inverse this later) */ + ACHANNEL_SETTING_MUTE = 2, + ACHANNEL_SETTING_EXPAND = 3, + ACHANNEL_SETTING_VISIBLE = 4, /* only for Graph Editor */ + ACHANNEL_SETTING_SOLO = 5 /* only for NLA Tracks */ } eAnimChannel_Settings; -- cgit v1.2.3 From fc07b1fce3a6f1d6962840859c763bd192fbdcd7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 07:54:46 +0000 Subject: Mask editing: remove use_parent property and use check if paren't id is set instead --- release/scripts/startup/bl_ui/space_clip.py | 35 ++++++++++++------------ source/blender/blenkernel/intern/mask.c | 3 -- source/blender/editors/mask/mask_draw.c | 2 +- source/blender/editors/mask/mask_relationships.c | 4 +-- source/blender/makesdna/DNA_mask_types.h | 5 ++-- source/blender/makesrna/intern/rna_mask.c | 7 ----- 6 files changed, 22 insertions(+), 34 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 4bec1ad18ba..c87c506d326 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -716,28 +716,27 @@ class CLIP_PT_active_mask_point(Panel): col.prop(point, "handle_type") col = layout.column() - col.prop(parent, "use_parent", text="Parent") - if parent.use_parent: - # Currently only parenting yo movie clip is allowed, so do not - # ver-oplicate things for now and use single template_ID - #col.template_any_ID(parent, "id", "id_type", text="") + # Currently only parenting yo movie clip is allowed, so do not + # ver-oplicate things for now and use single template_ID + #col.template_any_ID(parent, "id", "id_type", text="") - col.template_ID(parent, "id") + col.label("Parent:") + col.prop(parent, "id", text="") - if parent.id_type == 'MOVIECLIP' and parent.id: - clip = parent.id - tracking = clip.tracking + if parent.id_type == 'MOVIECLIP' and parent.id: + clip = parent.id + tracking = clip.tracking - col.prop_search(parent, "parent", tracking, - "objects", icon='OBJECT_DATA', text="Object:") + col.prop_search(parent, "parent", tracking, + "objects", icon='OBJECT_DATA', text="Object:") - if parent.parent and parent.parent in tracking.objects: - object = tracking.objects[parent.parent] - col.prop_search(parent, "sub_parent", object, - "tracks", icon='ANIM_DATA', text="Track:") - else: - col.prop_search(parent, "sub_parent", tracking, - "tracks", icon='ANIM_DATA', text="Track:") + if parent.parent in tracking.objects: + object = tracking.objects[parent.parent] + col.prop_search(parent, "sub_parent", object, + "tracks", icon='ANIM_DATA', text="Track:") + else: + col.prop_search(parent, "sub_parent", tracking, + "tracks", icon='ANIM_DATA', text="Track:") class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel): diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b942b633aef..66f10aca652 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1143,9 +1143,6 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[ if (!parent) return FALSE; - if ((parent->flag & MASK_PARENT_ACTIVE) == 0) - return FALSE; - if (parent->id_type == ID_MC) { if (parent->id) { MovieClip *clip = (MovieClip *) parent->id; diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index a26ae5ea3c0..e1efb6d841b 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -100,7 +100,7 @@ static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline) MaskSplinePoint *point = &points_array[i]; BezTriple *bezt = &point->bezt; - if (point->parent.flag & MASK_PARENT_ACTIVE) { + if (point->parent.id) { glVertex2f(bezt->vec[1][0], bezt->vec[1][1]); diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 0e893ee2f9f..7c0a598ba9f 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -66,7 +66,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(point)) { - point->parent.flag &= ~MASK_PARENT_ACTIVE; + point->parent.id = NULL; } } } @@ -141,8 +141,6 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) strcpy(point->parent.parent, tracking->name); strcpy(point->parent.sub_parent, track->name); - point->parent.flag |= MASK_PARENT_ACTIVE; - copy_v2_v2(point->parent.parent_orig, parmask_pos); } } diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 626242c1a8d..e4c27a57d85 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -51,7 +51,8 @@ typedef struct Mask { } Mask; typedef struct MaskParent { - int flag; /* parenting flags */ + // int flag; /* parenting flags */ /* not used */ + int pad; int id_type; /* type of parenting */ ID *id; /* ID block of entity to which mask/spline is parented to * in case of parenting to movie tracking data set to MovieClip datablock */ @@ -130,7 +131,7 @@ typedef struct MaskLayer { } MaskLayer; /* MaskParent->flag */ -#define MASK_PARENT_ACTIVE (1 << 0) +/* #define MASK_PARENT_ACTIVE (1 << 0) */ /* UNUSED */ /* MaskSpline->flag */ /* reserve (1 << 0) for SELECT */ diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index f25aba6193b..42c893eca16 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -349,13 +349,6 @@ static void rna_def_maskParent(BlenderRNA *brna) srna = RNA_def_struct(brna, "MaskParent", NULL); RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for masking element"); - /* use_parent */ - prop = RNA_def_property(srna, "use_parent", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_PARENT_ACTIVE); - RNA_def_property_ui_text(prop, "Use Parent", "Use parenting for this layer"); - RNA_def_property_update(prop, 0, "rna_Mask_update_data"); - /* Target Properties - ID-block to Drive */ prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ID"); -- cgit v1.2.3 From 54297c8d133d2e144685c1820d7fbd2e01c8fe51 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 07:55:15 +0000 Subject: Clip editor: cleanup up header One side of change is related on making code easier to follow, due it started being quite messy because of all in-lined mode/view checks. Now there's a bit of code duplication, but it's much easier to see what's going on there. Another side of patch is related on re-arranging elements in header in a way that follows rule "depending elements are placed after elements they depends on". This might be a bit against mostly-used-based elements placement, but now it's much easier to figure out where to add new option. Also it fits better other blender's areas such as image editor header, i.e. --- release/scripts/startup/bl_ui/space_clip.py | 107 ++++++++++++++++++---------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index c87c506d326..10361eeef0d 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -25,7 +25,7 @@ from bpy.types import Panel, Header, Menu class CLIP_HT_header(Header): bl_space_type = 'CLIP_EDITOR' - def draw(self, context): + def _draw_tracking(self, context): layout = self.layout sc = context.space_data @@ -41,39 +41,37 @@ class CLIP_HT_header(Header): if sc.view == 'CLIP': if clip: sub.menu("CLIP_MT_select") + sub.menu("CLIP_MT_clip") + sub.menu("CLIP_MT_track") + sub.menu("CLIP_MT_reconstruction") + else: + sub.menu("CLIP_MT_clip") - sub.menu("CLIP_MT_clip") - - if clip: - if sc.mode == 'MASKEDIT': - sub.menu("CLIP_MT_mask") - else: - sub.menu("CLIP_MT_track") - sub.menu("CLIP_MT_reconstruction") - - if sc.mode != 'MASKEDIT': - layout.prop(sc, "view", text="", expand=True) + row = layout.row() + row.template_ID(sc, "clip", open='clip.open') if clip: + tracking = clip.tracking + active_object = tracking.objects.active + if sc.view == 'CLIP': layout.prop(sc, "mode", text="") + layout.prop(sc, "view", text="", expand=True) layout.prop(sc, "pivot_point", text="", icon_only=True) - if sc.mode == 'MASKEDIT': - toolsettings = context.tool_settings + r = active_object.reconstruction - row = layout.row(align=True) - row.prop(toolsettings, "use_proportional_edit_mask", - text="", icon_only=True) - if toolsettings.use_proportional_edit_objects: - row.prop(toolsettings, "proportional_edit_falloff", - text="", icon_only=True) + if r.is_valid and sc.view == 'CLIP': + layout.label(text="Average solve error: %.4f" % + (r.average_error)) elif sc.view == 'GRAPH': + layout.prop(sc, "view", text="", expand=True) + row = layout.row(align=True) if sc.show_filters: row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_DOWN', - text="Filters") + text="Filters") sub = row.column() sub.active = clip.tracking.reconstruction.is_valid @@ -82,32 +80,63 @@ class CLIP_HT_header(Header): row.prop(sc, "show_graph_tracks", icon='ANIM', text="") else: row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_RIGHT', - text="Filters") + text="Filters") + elif sc.view == 'DOPESHEET': + layout.prop(sc, "view", text="", expand=True) + + layout.label(text="Sort by:") + layout.prop(sc, "dopesheet_sort_method", text="") + layout.prop(sc, "invert_dopesheet_sort", text="Invert") + else: + layout.prop(sc, "view", text="", expand=True) + + def _draw_masking(self, context): + layout = self.layout + + toolsettings = context.tool_settings + sc = context.space_data + clip = sc.clip + + row = layout.row(align=True) + row.template_header() + + if context.area.show_menus: + sub = row.row(align=True) + sub.menu("CLIP_MT_view") + + if clip: + sub.menu("CLIP_MT_select") + sub.menu("CLIP_MT_clip") + sub.menu("CLIP_MT_mask") + else: + sub.menu("CLIP_MT_clip") row = layout.row() row.template_ID(sc, "clip", open='clip.open') - if sc.mode == 'MASKEDIT': - row = layout.row() - row.template_ID(sc, "mask", new="mask.new") + layout.prop(sc, "mode", text="") - if clip: - tracking = clip.tracking - active = tracking.objects.active + row = layout.row() + row.template_ID(sc, "mask", new="mask.new") - if active and not active.is_camera: - r = active.reconstruction - else: - r = tracking.reconstruction + layout.prop(sc, "pivot_point", text="", icon_only=True) - if r.is_valid and sc.view == 'CLIP': - layout.label(text="Average solve error: %.4f" % - (r.average_error)) + row = layout.row(align=True) + row.prop(toolsettings, "use_proportional_edit_mask", + text="", icon_only=True) + if toolsettings.use_proportional_edit_mask: + row.prop(toolsettings, "proportional_edit_falloff", + text="", icon_only=True) - if sc.view == 'DOPESHEET': - layout.label(text="Sort by:") - layout.prop(sc, "dopesheet_sort_method", text="") - layout.prop(sc, "invert_dopesheet_sort", text="Invert") + def draw(self, context): + layout = self.layout + + sc = context.space_data + + if sc.mode in {'TRACKING', 'RECONSTRUCTION', 'DISTORTION'}: + self._draw_tracking(context) + else: + self._draw_masking(context) layout.template_running_jobs() -- cgit v1.2.3 From 87211a49ab1c249d5c885706ba9130ed3bd0e0b4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 08:17:34 +0000 Subject: Fix #31743: Applying Smooth modifier to a curve crashes Blender Actually there were two different issues involved here: - Recently enabled Smooth modifier wasn't actually designed for curves, so it in fact requires a bit bigger work to make it working. For now added check for object's typy in this modifier and if it's not mesh, it wouldn't try to use edges. The reason why it worked in 3d viewport is that creating DM from curve while displist is still ocntrcuting for would result in empty CDDM and that leads to not taking edges into account, only vertexCos passed to modifier would be used. This makes it behaving a bit differently from if it was a mesh, but still gives quite reasonable result. Would leave actual fix for a guy who enabled smooth modifier. - Another issue is related on ensuring sculpt mask layer after applying modifier. This shall happen only for meshes. --- source/blender/editors/object/object_modifier.c | 6 ++++-- source/blender/modifiers/intern/MOD_smooth.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 7dd17e59f6f..d6b5fb9fc10 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -642,8 +642,10 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BLI_remlink(&ob->modifiers, md); modifier_free(md); - /* ensure mesh paint mask layer remains after applying */ - ED_sculpt_mask_layers_ensure(ob, NULL); + if (ob->type == OB_MESH) { + /* ensure mesh paint mask layer remains after applying */ + ED_sculpt_mask_layers_ensure(ob, NULL); + } return 1; } diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 1313f5aa3ef..7b230d7365d 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -118,8 +118,14 @@ static void smoothModifier_do( fac = smd->fac; facm = 1 - fac; - medges = dm->getEdgeArray(dm); - numDMEdges = dm->getNumEdges(dm); + if (ob->type == OB_MESH) { + medges = dm->getEdgeArray(dm); + numDMEdges = dm->getNumEdges(dm); + } + else { + medges = NULL; + numDMEdges = 0; + } modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index); -- cgit v1.2.3 From e446c6af1fbf92bad71644ac687b5b24c4c824fd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 08:24:08 +0000 Subject: Fix #31748: Blender crashes when typing "al" after opening spacebar menu. Crash was introduced by own refactoring of poll functions in clip editor. --- source/blender/editors/space_clip/tracking_ops.c | 34 +++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index fdd4dfc57d0..f3a96ef7a79 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -2135,17 +2135,20 @@ static Object *get_orientation_object(bContext *C) static int set_orientation_poll(bContext *C) { - Scene *scene = CTX_data_scene(C); SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip(sc); - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { - return TRUE; - } - else { - return OBACT != NULL; + if (sc) { + Scene *scene = CTX_data_scene(C); + MovieClip *clip = ED_space_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); + + if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { + return TRUE; + } + else { + return OBACT != NULL; + } } return FALSE; @@ -2744,11 +2747,16 @@ void CLIP_OT_set_scale(wmOperatorType *ot) static int set_solution_scale_poll(bContext *C) { SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip(sc); - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0; + if (sc) { + MovieClip *clip = ED_space_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); + + return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0; + } + + return FALSE; } static int set_solution_scale_exec(bContext *C, wmOperator *op) -- cgit v1.2.3 From 95641388471d178552fea26bb477c13536bd58ef Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 09:15:45 +0000 Subject: Another fix for #31743: check for DM's verts number matches passed number of vertices Now bevelled splines shall work in the same way as meshes. --- source/blender/modifiers/intern/MOD_smooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 7b230d7365d..545e2135344 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -118,7 +118,7 @@ static void smoothModifier_do( fac = smd->fac; facm = 1 - fac; - if (ob->type == OB_MESH) { + if (dm->getNumVerts(dm) == numVerts) { medges = dm->getEdgeArray(dm); numDMEdges = dm->getNumEdges(dm); } -- cgit v1.2.3 From de7fe937ff24121ce8c66af902639cd96244a55f Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 8 Jun 2012 09:17:07 +0000 Subject: * Added OpenCL kernel for bokeh blur * Uncomment COM_OPENCL_ENABLED from COM_defines.h to test --- release/datafiles/clkernelstoh.py | 70 +++++++++++++ source/blender/compositor/COM_defines.h | 17 +++- .../compositor/intern/COM_ExecutionGroup.cpp | 59 ++--------- .../blender/compositor/intern/COM_ExecutionGroup.h | 24 +++-- .../compositor/intern/COM_ExecutionSystem.cpp | 40 +++++--- .../compositor/intern/COM_ExecutionSystem.h | 7 ++ source/blender/compositor/intern/COM_Node.cpp | 9 +- source/blender/compositor/intern/COM_Node.h | 4 +- .../compositor/intern/COM_NodeOperation.cpp | 108 +++++++++++++++++++++ .../blender/compositor/intern/COM_NodeOperation.h | 15 ++- .../blender/compositor/intern/COM_OpenCLDevice.cpp | 8 +- .../compositor/intern/COM_WorkScheduler.cpp | 4 +- source/blender/compositor/nodes/COM_BlurNode.cpp | 6 +- .../blender/compositor/nodes/COM_BokehBlurNode.cpp | 4 +- .../compositor/nodes/COM_BokehImageNode.cpp | 2 +- .../compositor/nodes/COM_ChannelMatteNode.cpp | 2 +- .../compositor/nodes/COM_ChromaMatteNode.cpp | 2 +- .../compositor/nodes/COM_ColorCurveNode.cpp | 40 +++++--- .../compositor/nodes/COM_ColorMatteNode.cpp | 2 +- .../compositor/nodes/COM_CompositorNode.cpp | 2 +- .../compositor/nodes/COM_DifferenceMatteNode.cpp | 2 +- .../compositor/nodes/COM_DistanceMatteNode.cpp | 2 +- source/blender/compositor/nodes/COM_FilterNode.cpp | 2 +- source/blender/compositor/nodes/COM_ImageNode.cpp | 4 +- .../compositor/nodes/COM_LuminanceMatteNode.cpp | 2 +- source/blender/compositor/nodes/COM_MixNode.cpp | 2 +- .../blender/compositor/nodes/COM_MovieClipNode.cpp | 4 +- .../compositor/nodes/COM_OutputFileNode.cpp | 4 +- .../compositor/nodes/COM_RenderLayersNode.cpp | 4 +- .../compositor/nodes/COM_SplitViewerNode.cpp | 2 +- .../blender/compositor/nodes/COM_TextureNode.cpp | 2 +- source/blender/compositor/nodes/COM_ViewerNode.cpp | 2 +- .../operations/COM_BokehBlurOperation.cpp | 37 +++++-- .../compositor/operations/COM_BokehBlurOperation.h | 2 + .../operations/COM_ColorCurveOperation.cpp | 69 ++++++++++++- .../operations/COM_ColorCurveOperation.h | 33 +++++++ .../operations/COM_CompositorOperation.h | 2 +- .../compositor/operations/COM_OpenCLKernels.cl | 52 +++++++++- .../compositor/operations/COM_OpenCLKernels.cl.cpp | 15 --- .../compositor/operations/COM_OpenCLKernels.cl.h | 55 +++++++++++ .../operations/COM_OutputFileOperation.h | 4 +- .../compositor/operations/COM_PreviewOperation.cpp | 5 +- .../compositor/operations/COM_PreviewOperation.h | 4 +- .../operations/COM_ViewerBaseOperation.cpp | 6 +- .../operations/COM_ViewerBaseOperation.h | 2 +- .../operations/COM_WriteBufferOperation.cpp | 18 ++-- .../operations/COM_WriteBufferOperation.h | 2 +- source/blender/editors/space_node/drawnode.c | 2 +- source/blender/makesdna/DNA_node_types.h | 8 ++ source/blender/makesrna/intern/rna_nodetree.c | 35 ++++++- .../blender/makesrna/intern/rna_nodetree_types.h | 1 + .../composite/nodes/node_composite_bokehblur.c | 10 +- 52 files changed, 631 insertions(+), 188 deletions(-) create mode 100755 release/datafiles/clkernelstoh.py delete mode 100644 source/blender/compositor/operations/COM_OpenCLKernels.cl.cpp create mode 100644 source/blender/compositor/operations/COM_OpenCLKernels.cl.h diff --git a/release/datafiles/clkernelstoh.py b/release/datafiles/clkernelstoh.py new file mode 100755 index 00000000000..8fb5d4e6bae --- /dev/null +++ b/release/datafiles/clkernelstoh.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012 Blender Foundation. +# All rights reserved. +# +# Contributor(s): Jeroen Bakker +# +# ***** END GPL LICENCE BLOCK ***** + +# + +import sys +import os + +if len(sys.argv) < 2: + sys.stdout.write("Usage: clkernelstoh \n") + sys.exit(1) + +filename = sys.argv[1] + +try: + fpin = open(filename, "r") +except: + sys.stdout.write("Unable to open input %s\n" % sys.argv[1]) + sys.exit(1) + +if filename[0:2] == "." + os.sep: + filename = filename[2:] + +cname = filename + ".h" +sys.stdout.write("Making H file <%s>\n" % cname) + +filename = filename.split("/")[-1].split("\\")[-1] +filename = filename.replace(".", "_") + +try: + fpout = open(cname, "w") +except: + sys.stdout.write("Unable to open output %s\n" % cname) + sys.exit(1) + +fpout.write("/* clkernelstoh output of file <%s> */\n\n" % filename) +fpout.write("const char * clkernelstoh_%s = " % filename) + +lines = fpin.readlines() +for line in lines: + fpout.write("\"") + fpout.write(line.rstrip()) + fpout.write("\\n\" \\\n") +fpout.write("\"\\0\";\n") + +fpin.close() +fpout.close() diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index df807091cb8..f87265c50f5 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -52,12 +52,25 @@ typedef enum CompositorQuality { COM_QUALITY_LOW = 2 } CompositorQuality; +/** + * @brief Possible priority settings + * @ingroup Execution + */ +typedef enum CompositorPriority { + /** @brief High quality setting */ + COM_PRIORITY_HIGH = 2 , + /** @brief Medium quality setting */ + COM_PRIORITY_MEDIUM = 1, + /** @brief Low quality setting */ + COM_PRIORITY_LOW = 0 +} CompositorPriority; + // configurable items // chunk size determination #define COM_PREVIEW_SIZE 140.0f -#define COM_OPENCL_ENABLED -#define COM_PREVIEW_ENABLED +//#define COM_OPENCL_ENABLED + // workscheduler threading models /** * COM_TM_QUEUE is a multithreaded model, which uses the BLI_thread_queue pattern. This is the default option. diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 0ebf9af207b..44b3c8dafbb 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -57,7 +57,7 @@ ExecutionGroup::ExecutionGroup() this->chunksFinished = 0; } -int ExecutionGroup::getRenderPriotrity() +CompositorPriority ExecutionGroup::getRenderPriotrity() { return this->getOutputNodeOperation()->getRenderPriority(); } @@ -401,47 +401,11 @@ MemoryBuffer** ExecutionGroup::getInputBuffersOpenCL(int chunkNumber) return memoryBuffers; } -// @todo: for opencl the memory buffers size needs to be same as the needed size -// currently this method is not called, but will be when opencl nodes are created MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *rect) { - // find all chunks inside the rect - // determine minxchunk, minychunk, maxxchunk, maxychunk where x and y are chunknumbers - float chunkSizef = this->chunkSize; - - int indexx, indexy; - - const int minxchunk = floor(rect->xmin/chunkSizef); - const int maxxchunk = ceil((rect->xmax-1)/chunkSizef); - const int minychunk = floor(rect->ymin/chunkSizef); - const int maxychunk = ceil((rect->ymax-1)/chunkSizef); - - if (maxxchunk== minxchunk+1 && maxychunk == minychunk+1) { - MemoryBuffer *result =memoryProxy->getBuffer(); - return result; - } - - rcti chunkRect; - chunkRect.xmin = minxchunk*this->chunkSize; - chunkRect.xmax = maxxchunk*this->chunkSize; - chunkRect.ymin = minychunk*this->chunkSize; - chunkRect.ymax = maxychunk*this->chunkSize; - - CLAMP(chunkRect.xmin, 0, (int)this->width); - CLAMP(chunkRect.xmax, 0, (int)this->width); - CLAMP(chunkRect.ymin, 0, (int)this->height); - CLAMP(chunkRect.ymax, 0, (int)this->height); - - MemoryBuffer *result = new MemoryBuffer(memoryProxy, &chunkRect); - - for (indexx = max(minxchunk, 0); indexxnumberOfXChunks, maxxchunk) ; indexx++) { - for (indexy = max(minychunk, 0); indexynumberOfYChunks, maxychunk) ; indexy++) { - /* int chunkNumber = indexx+indexy*this->numberOfXChunks; */ /* UNUSED */ - MemoryBuffer *chunkBuffer = memoryProxy->getBuffer(); - result->copyContentFrom(chunkBuffer); - } - } - + MemoryBuffer* imageBuffer = memoryProxy->getBuffer(); + MemoryBuffer* result = new MemoryBuffer(memoryProxy, rect); + result->copyContentFrom(imageBuffer); return result; } @@ -487,14 +451,14 @@ void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumb MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect) { - MemoryBuffer *outputBuffer = NULL; - // output allocation is only valid when our outputoperation is a memorywriter + // we asume that this method is only called from complex execution groups. NodeOperation * operation = this->getOutputNodeOperation(); if (operation->isWriteBufferOperation()) { -/* WriteBufferOperation *writeOperation = (WriteBufferOperation*)operation; */ /* UNUSED */ -// @todo outputBuffer = MemoryManager::allocateMemoryBuffer(writeOperation->getMemoryProxy(), chunkNumber, rect); + WriteBufferOperation *writeOperation = (WriteBufferOperation*)operation; + MemoryBuffer *buffer = new MemoryBuffer(writeOperation->getMemoryProxy(), rect); + return buffer; } - return outputBuffer; + return NULL; } @@ -600,11 +564,6 @@ void ExecutionGroup::determineDependingMemoryProxies(vector *memor } } -bool ExecutionGroup::operator ==(const ExecutionGroup & executionGroup) const -{ - return this->getOutputNodeOperation() == executionGroup.getOutputNodeOperation(); -} - bool ExecutionGroup::isOpenCL() { return this->openCL; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index cbdc9bb1787..416a78eb8b8 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -167,13 +167,7 @@ private: * @param operation the operation to be added */ bool canContainOperation(NodeOperation *operation); - - /** - * @brief get the Render priority of this ExecutionGroup - * @see ExecutionSystem.execute - */ - int getRenderPriotrity(); - + /** * @brief calculate the actual chunk size of this execution group. * @note A chunk size is an unsigned int that is both the height and width of a chunk. @@ -396,17 +390,21 @@ public: * @see determineChunkSize() */ void determineChunkRect(rcti *rect, const unsigned int chunkNumber) const; - - - bool operator ==(const ExecutionGroup &executionGroup) const; - - /** + + /** * @brief can this ExecutionGroup be scheduled on an OpenCLDevice * @see WorkScheduler.schedule */ bool isOpenCL(); - + void setChunksize(int chunksize) {this->chunkSize = chunksize;} + + /** + * @brief get the Render priority of this ExecutionGroup + * @see ExecutionSystem.execute + */ + CompositorPriority getRenderPriotrity(); + }; #endif diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 96d2a6f4434..8c0b37a0685 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -127,20 +127,9 @@ void ExecutionSystem::execute() WorkScheduler::start(this->context); - - vector executionGroups; - this->findOutputExecutionGroup(&executionGroups); - - /* start execution of the ExecutionGroups based on priority of their output node */ - for (int priority = 9 ; priority>=0 ; priority--) { - for (index = 0 ; index < executionGroups.size(); index ++) { - ExecutionGroup *group = executionGroups[index]; - NodeOperation *output = group->getOutputNodeOperation(); - if (output->getRenderPriority() == priority) { - group->execute(this); - } - } - } + executeGroups(COM_PRIORITY_HIGH); + executeGroups(COM_PRIORITY_MEDIUM); + executeGroups(COM_PRIORITY_LOW); WorkScheduler::finish(); WorkScheduler::stop(); @@ -155,6 +144,18 @@ void ExecutionSystem::execute() } } +void ExecutionSystem::executeGroups(CompositorPriority priority) +{ + int index; + vector executionGroups; + this->findOutputExecutionGroup(&executionGroups, priority); + + for (index = 0 ; index < executionGroups.size(); index ++) { + ExecutionGroup *group = executionGroups[index]; + group->execute(this); + } +} + void ExecutionSystem::addOperation(NodeOperation *operation) { ExecutionSystemHelper::addOperation(this->operations, operation); @@ -304,6 +305,17 @@ void ExecutionSystem::determineActualSocketDataTypes(vector &nodes) } } +void ExecutionSystem::findOutputExecutionGroup(vector *result, CompositorPriority priority) const +{ + unsigned int index; + for (index = 0 ; index < this->groups.size() ; index ++) { + ExecutionGroup *group = this->groups[index]; + if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) { + result->push_back(group); + } + } +} + void ExecutionSystem::findOutputExecutionGroup(vector *result) const { unsigned int index; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index 85fec8b6145..510e58ba1bb 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -138,6 +138,11 @@ private: //methods void addReadWriteBufferOperations(NodeOperation *operation); + /** + * find all execution group with output nodes + */ + void findOutputExecutionGroup(vector *result, CompositorPriority priority) const; + /** * find all execution group with output nodes */ @@ -224,6 +229,8 @@ private: * @param nodes list of nodes or operations to do the data type determination */ void determineActualSocketDataTypes(vector &nodes); + + void executeGroups(CompositorPriority priority); }; #endif diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index ba5e21d53ae..264725b4b2c 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -83,23 +83,20 @@ void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket graph->addOperation(operation); } -void Node::addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket, int priority) +void Node::addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket) { -#ifdef COM_PREVIEW_ENABLED PreviewOperation *operation = new PreviewOperation(); system->addOperation(operation); operation->setbNode(this->getbNode()); operation->setbNodeTree(system->getContext().getbNodeTree()); - operation->setPriority(priority); this->addLink(system, outputSocket, operation->getInputSocket(0)); -#endif } -void Node::addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket, int priority) +void Node::addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket) { if (inputSocket->isConnected()) { OutputSocket *outputsocket = inputSocket->getConnection()->getFromSocket(); - this->addPreviewOperation(system, outputsocket, priority); + this->addPreviewOperation(system, outputsocket); } } diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index 2666d0a6980..23744adf642 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -120,8 +120,8 @@ protected: Node(); - void addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket, int priority); - void addPreviewOperation(ExecutionSystem *system, OutputSocket *inputSocket, int priority); + void addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket); + void addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket); bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex); bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex); diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp index fae652e39d7..650e4af5ae0 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.cpp +++ b/source/blender/compositor/intern/COM_NodeOperation.cpp @@ -124,3 +124,111 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti * input, ReadBufferOpe return false; } } + +cl_mem NodeOperation::COM_clAttachMemoryBufferToKernelParameter(cl_context context, cl_kernel kernel, int parameterIndex, int offsetIndex, list *cleanup, MemoryBuffer **inputMemoryBuffers, SocketReader* reader) +{ + cl_int error; + MemoryBuffer* result = (MemoryBuffer*)reader->initializeTileData(NULL, inputMemoryBuffers); + + const cl_image_format imageFormat = { + CL_RGBA, + CL_FLOAT + }; + + cl_mem clBuffer = clCreateImage2D(context, CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR, &imageFormat, result->getWidth(), + result->getHeight(), 0, result->getBuffer(), &error); + + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + if (error == CL_SUCCESS) cleanup->push_back(clBuffer); + + error = clSetKernelArg(kernel, parameterIndex, sizeof(cl_mem), &clBuffer); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + + COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, offsetIndex, result); + return clBuffer; +} + +void NodeOperation::COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel, int offsetIndex, MemoryBuffer *memoryBuffer) +{ + if (offsetIndex != -1) { + cl_int error; + rcti* rect = memoryBuffer->getRect(); + cl_int2 offset = {rect->xmin, rect->ymin}; + + error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + } +} + +void NodeOperation::COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offsetIndex) +{ + if (offsetIndex != -1) { + cl_int error; + cl_int2 offset = {this->getWidth(), this->getHeight()}; + + error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + } +} + +void NodeOperation::COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, cl_mem clOutputMemoryBuffer) +{ + cl_int error; + error = clSetKernelArg(kernel, parameterIndex, sizeof(cl_mem), &clOutputMemoryBuffer); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } +} + +void NodeOperation::COM_clEnqueueRange(cl_command_queue queue, cl_kernel kernel, MemoryBuffer *outputMemoryBuffer) { + cl_int error; + const size_t size[] = {outputMemoryBuffer->getWidth(),outputMemoryBuffer->getHeight()}; + + error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, size, 0, 0, 0, NULL); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } +} + +void NodeOperation::COM_clEnqueueRange(cl_command_queue queue, cl_kernel kernel, MemoryBuffer *outputMemoryBuffer, int offsetIndex) { + cl_int error; + const int width = outputMemoryBuffer->getWidth(); + const int height = outputMemoryBuffer->getHeight(); + int offsetx; + int offsety; + const int localSize = 32; + size_t size[2]; + cl_int2 offset; + + for (offsety = 0 ; offsety < height; offsety+=localSize) { + offset[1] = offsety; + if (offsety+localSize < height) { + size[1] = localSize; + } else { + size[1] = height - offsety; + } + for (offsetx = 0 ; offsetx < width ; offsetx+=localSize) { + if (offsetx+localSize < width) { + size[0] = localSize; + } else { + size[0] = width - offsetx; + } + offset[0] = offsetx; + + error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, size, 0, 0, 0, NULL); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + clFlush(queue); + } + } +} + +cl_kernel NodeOperation::COM_clCreateKernel(cl_program program, const char *kernelname, list *clKernelsToCleanUp) +{ + cl_int error; + cl_kernel kernel = clCreateKernel(program, kernelname, &error) ; + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + } + else { + if (clKernelsToCleanUp) clKernelsToCleanUp->push_back(kernel); + } + return kernel; + +} diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 73ba5b472d7..2219907b0c8 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -139,8 +139,10 @@ public: * @param rect the rectangle of the chunk (location and size) * @param chunkNumber the chunkNumber to be calculated * @param memoryBuffers all input MemoryBuffer's needed + * @param outputBuffer the outputbuffer to write to */ - virtual void executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** memoryBuffers) {} + virtual void executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, + unsigned int chunkNumber, MemoryBuffer** memoryBuffers, MemoryBuffer* outputBuffer) {} /** * @brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice @@ -207,9 +209,9 @@ public: /** * @brief get the render priority of this node. * @note only applicable for output operations like ViewerOperation - * @return [0:9] 9 is highest priority + * @return CompositorPriority */ - virtual const int getRenderPriority() const {return 0;} + virtual const CompositorPriority getRenderPriority() const {return COM_PRIORITY_LOW;} /** * @brief can this NodeOperation be scheduled on an OpenCLDevice @@ -242,6 +244,13 @@ protected: */ void setOpenCL(bool openCL) {this->openCL = openCL;} + static cl_mem COM_clAttachMemoryBufferToKernelParameter(cl_context context, cl_kernel kernel, int parameterIndex, int offsetIndex, list *cleanup, MemoryBuffer **inputMemoryBuffers, SocketReader* reader); + static void COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel kernel, int offsetIndex, MemoryBuffer *memoryBuffers); + static void COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, cl_mem clOutputMemoryBuffer); + void COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offsetIndex); + static void COM_clEnqueueRange(cl_command_queue queue, cl_kernel kernel, MemoryBuffer* outputMemoryBuffer); + static void COM_clEnqueueRange(cl_command_queue queue, cl_kernel kernel, MemoryBuffer *outputMemoryBuffer, int offsetIndex); + cl_kernel COM_clCreateKernel(cl_program program, const char* kernelname, list *clKernelsToCleanUp); }; diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index 692b96f40b3..e6d3789b06d 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -56,10 +56,10 @@ void OpenCLDevice::execute(WorkPackage *work) MemoryBuffer ** inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber); MemoryBuffer * outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect); - executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this->context, this->program, this->queue, &rect, chunkNumber, inputBuffers); + executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this->context, this->program, this->queue, &rect, + chunkNumber, inputBuffers, outputBuffer); + + delete outputBuffer; executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers); - if (outputBuffer != NULL) { - outputBuffer->setCreatedState(); - } } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 80b91b2364c..172107f720b 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -28,7 +28,7 @@ #include "COM_OpenCLDevice.h" #include "OCL_opencl.h" #include "stdio.h" -#include "COM_OpenCLKernels.cl.cpp" +#include "COM_OpenCLKernels.cl.h" #include "BKE_global.h" #if COM_CURRENT_THREADING_MODEL == COM_TM_NOTHREAD @@ -260,7 +260,7 @@ void WorkScheduler::initialize() if (totalNumberOfDevices > 0) { context = clCreateContext(NULL, totalNumberOfDevices, cldevices, clContextError, NULL, &error); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - program = clCreateProgramWithSource(context, 1, &sourcecode, 0, &error); + program = clCreateProgramWithSource(context, 1, &clkernelstoh_COM_OpenCLKernels_cl, 0, &error); error = clBuildProgram(program, totalNumberOfDevices, cldevices, 0, 0, 0); if (error != CL_SUCCESS) { cl_int error2; diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index b209e36dd48..d9cf2c2fef0 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -55,7 +55,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph); this->getOutputSocket(0)->relinkConnections(operationfgb->getOutputSocket(0)); graph->addOperation(operationfgb); - addPreviewOperation(graph, operationfgb->getOutputSocket(), 5); + addPreviewOperation(graph, operationfgb->getOutputSocket()); } else if (!data->bokeh) { GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); @@ -71,7 +71,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); - addPreviewOperation(graph, operationy->getOutputSocket(), 5); + addPreviewOperation(graph, operationy->getOutputSocket()); if (!connectedSizeSocket) { operationx->setSize(size); @@ -86,7 +86,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c operation->setQuality(quality); graph->addOperation(operation); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, operation->getOutputSocket(), 5); + addPreviewOperation(graph, operation->getOutputSocket()); if (!connectedSizeSocket) { operation->setSize(size); diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp index d6f4f58fe70..abae1b88890 100644 --- a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp @@ -41,9 +41,9 @@ void BokehBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContex if (this->getInputSocket(2)->isConnected()) { VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation(); ConvertDepthToRadiusOperation *converter = new ConvertDepthToRadiusOperation(); - converter->setfStop(4.0f); + converter->setfStop(this->getbNode()->custom3); converter->setCameraObject(camob); - operation->setMaxBlur(16); + operation->setMaxBlur((int)this->getbNode()->custom4); operation->setQuality(context->getQuality()); this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.cpp b/source/blender/compositor/nodes/COM_BokehImageNode.cpp index 35511d213f5..f498fa11e30 100644 --- a/source/blender/compositor/nodes/COM_BokehImageNode.cpp +++ b/source/blender/compositor/nodes/COM_BokehImageNode.cpp @@ -35,5 +35,5 @@ void BokehImageNode::convertToOperations(ExecutionSystem *graph, CompositorConte this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(operation); operation->setData((NodeBokehImage*)this->getbNode()->storage); - addPreviewOperation(graph, operation->getOutputSocket(0), 9); + addPreviewOperation(graph, operation->getOutputSocket(0)); } diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp index dbe5b9936dc..f1d5b8d39cc 100644 --- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp @@ -82,7 +82,7 @@ void ChannelMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCon graph->addOperation(operationAlpha); addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); - addPreviewOperation(graph, operationAlpha->getOutputSocket(), 9); + addPreviewOperation(graph, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp index dd3b3855e3f..82059ed8493 100644 --- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp @@ -63,7 +63,7 @@ void ChromaMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCont addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); graph->addOperation(operationAlpha); - addPreviewOperation(graph, operationAlpha->getOutputSocket(), 9); + addPreviewOperation(graph, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp index d7cde21a984..0d331ed9b05 100644 --- a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp @@ -31,16 +31,32 @@ ColorCurveNode::ColorCurveNode(bNode *editorNode): Node(editorNode) void ColorCurveNode::convertToOperations(ExecutionSystem *graph, CompositorContext * context) { - ColorCurveOperation *operation = new ColorCurveOperation(); - - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); - this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); - this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph); - this->getInputSocket(3)->relinkConnections(operation->getInputSocket(3), 3, graph); - - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - - operation->setCurveMapping((CurveMapping*)this->getbNode()->storage); - - graph->addOperation(operation); + if (this->getInputSocket(2)->isConnected() || this->getInputSocket(3)->isConnected()) { + ColorCurveOperation *operation = new ColorCurveOperation(); + + this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); + this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph); + this->getInputSocket(3)->relinkConnections(operation->getInputSocket(3), 3, graph); + + this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); + + operation->setCurveMapping((CurveMapping*)this->getbNode()->storage); + + graph->addOperation(operation); + } else { + ConstantLevelColorCurveOperation *operation = new ConstantLevelColorCurveOperation(); + + this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); + bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA*)this->getInputSocket(2)->getbNodeSocket()->default_value; + operation->setBlackLevel(val->value); + val = (bNodeSocketValueRGBA*)this->getInputSocket(3)->getbNodeSocket()->default_value; + operation->setWhiteLevel(val->value); + this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); + + operation->setCurveMapping((CurveMapping*)this->getbNode()->storage); + + graph->addOperation(operation); + } } diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp index 860d1a01194..ad117e1ca2c 100644 --- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp @@ -60,7 +60,7 @@ void ColorMatteNode::convertToOperations(ExecutionSystem *graph, CompositorConte addLink(graph, operationRGBToHSV_Image->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0)); addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); graph->addOperation(operationAlpha); - addPreviewOperation(graph, operationAlpha->getOutputSocket(), 9); + addPreviewOperation(graph, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp index 57821e7fe27..e2cc34bb6ce 100644 --- a/source/blender/compositor/nodes/COM_CompositorNode.cpp +++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp @@ -39,6 +39,6 @@ void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorConte imageSocket->relinkConnections(colourAlphaProg->getInputSocket(0)); alphaSocket->relinkConnections(colourAlphaProg->getInputSocket(1)); graph->addOperation(colourAlphaProg); - addPreviewOperation(graph, colourAlphaProg->getInputSocket(0), 5); + addPreviewOperation(graph, colourAlphaProg->getInputSocket(0)); } } diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp index c26fb4e5c5d..596fefff77c 100644 --- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp @@ -49,5 +49,5 @@ void DifferenceMatteNode::convertToOperations(ExecutionSystem *graph, Compositor addLink(graph, operationSet->getOutputSocket(), operation->getInputSocket(1)); outputSocketImage->relinkConnections(operation->getOutputSocket()); graph->addOperation(operation); - addPreviewOperation(graph, operation->getOutputSocket(), 5); + addPreviewOperation(graph, operation->getOutputSocket()); } diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp index d7b4e481ec2..20a55ae195c 100644 --- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp @@ -52,7 +52,7 @@ void DistanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCo addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); graph->addOperation(operationAlpha); - addPreviewOperation(graph, operationAlpha->getOutputSocket(), 9); + addPreviewOperation(graph, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp index bdba69dc47d..7700bceb4ab 100644 --- a/source/blender/compositor/nodes/COM_FilterNode.cpp +++ b/source/blender/compositor/nodes/COM_FilterNode.cpp @@ -76,7 +76,7 @@ void FilterNode::convertToOperations(ExecutionSystem *graph, CompositorContext * inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph); inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph); outputSocket->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, operation->getOutputSocket(0), 5); + addPreviewOperation(graph, operation->getOutputSocket(0)); graph->addOperation(operation); } diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 7f14b068136..cfd530173a9 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -105,7 +105,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext * break; } if (index == 0 && operation) { - addPreviewOperation(graph, operation->getOutputSocket(), 9); + addPreviewOperation(graph, operation->getOutputSocket()); } } } @@ -123,7 +123,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext * operation->setImageUser(imageuser); operation->setFramenumber(framenumber); graph->addOperation(operation); - addPreviewOperation(graph, operation->getOutputSocket(), 9); + addPreviewOperation(graph, operation->getOutputSocket()); } if (numberOfOutputs > 1) { diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp index eb78657f3c4..37976216106 100644 --- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp @@ -53,7 +53,7 @@ void LuminanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorC addLink(graph, rgbToYUV->getInputSocket(0)->getConnection()->getFromSocket(), operation->getInputSocket(0)); addLink(graph, operationSet->getOutputSocket(), operation->getInputSocket(1)); graph->addOperation(operation); - addPreviewOperation(graph, operation->getOutputSocket(), 9); + addPreviewOperation(graph, operation->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operation->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp index 86ca5ebc237..42e32a4e55e 100644 --- a/source/blender/compositor/nodes/COM_MixNode.cpp +++ b/source/blender/compositor/nodes/COM_MixNode.cpp @@ -125,7 +125,7 @@ void MixNode::convertToOperations(ExecutionSystem *graph, CompositorContext * co color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph); color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph); outputSocket->relinkConnections(convertProg->getOutputSocket(0)); - addPreviewOperation(graph, convertProg->getOutputSocket(0), 5); + addPreviewOperation(graph, convertProg->getOutputSocket(0)); convertProg->getInputSocket(2)->setResizeMode(color2Socket->getResizeMode()); diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index 75831130936..eac581dc903 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -62,7 +62,7 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex converter->setFromColorProfile(IB_PROFILE_LINEAR_RGB); converter->setToColorProfile(IB_PROFILE_SRGB); addLink(graph, operation->getOutputSocket(), converter->getInputSocket(0)); - addPreviewOperation(graph, converter->getOutputSocket(), 9); + addPreviewOperation(graph, converter->getOutputSocket()); if (outputMovieClip->isConnected()) { outputMovieClip->relinkConnections(converter->getOutputSocket()); } @@ -72,7 +72,7 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex } } else { - addPreviewOperation(graph, operation->getOutputSocket(), 9); + addPreviewOperation(graph, operation->getOutputSocket()); if (outputMovieClip->isConnected()) { outputMovieClip->relinkConnections(operation->getOutputSocket()); } diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index cc060e9f7cd..ca18ea5fbf7 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -59,7 +59,7 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte input->relinkConnections(outputOperation->getInputSocket(i)); } } - if (hasConnections) addPreviewOperation(graph, outputOperation->getInputSocket(0), 5); + if (hasConnections) addPreviewOperation(graph, outputOperation->getInputSocket(0)); graph->addOperation(outputOperation); } @@ -81,7 +81,7 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte input->relinkConnections(outputOperation->getInputSocket(0)); graph->addOperation(outputOperation); if (!previewAdded) { - addPreviewOperation(graph, outputOperation->getInputSocket(0), 5); + addPreviewOperation(graph, outputOperation->getInputSocket(0)); previewAdded = true; } } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp index 4e99db090e1..8216205b925 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp @@ -63,7 +63,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS outputSocket->relinkConnections(operation->getOutputSocket()); system->addOperation(operation); if (outputSocketNumber == 0) { // only do for image socket if connected - addPreviewOperation(system, operation->getOutputSocket(), 9); + addPreviewOperation(system, operation->getOutputSocket()); } } else { @@ -71,7 +71,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS system->addOperation(operation); operation->setScene(scene); operation->setLayerId(layerId); - addPreviewOperation(system, operation->getOutputSocket(), 9); + addPreviewOperation(system, operation->getOutputSocket()); } else { delete operation; diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp index 9f9efbd8fe5..bf434c164c0 100644 --- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp @@ -45,7 +45,7 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont splitViewerOperation->setXSplit(!this->getbNode()->custom2); image1Socket->relinkConnections(splitViewerOperation->getInputSocket(0), 0, graph); image2Socket->relinkConnections(splitViewerOperation->getInputSocket(1), 1, graph); - addPreviewOperation(graph, splitViewerOperation->getInputSocket(0), 0); + addPreviewOperation(graph, splitViewerOperation->getInputSocket(0)); graph->addOperation(splitViewerOperation); } } diff --git a/source/blender/compositor/nodes/COM_TextureNode.cpp b/source/blender/compositor/nodes/COM_TextureNode.cpp index be8bb623f4c..fe8a8e2250e 100644 --- a/source/blender/compositor/nodes/COM_TextureNode.cpp +++ b/source/blender/compositor/nodes/COM_TextureNode.cpp @@ -39,7 +39,7 @@ void TextureNode::convertToOperations(ExecutionSystem *system, CompositorContext operation->setTexture(texture); operation->setScene(context->getScene()); system->addOperation(operation); - addPreviewOperation(system, operation->getOutputSocket(), 9); + addPreviewOperation(system, operation->getOutputSocket()); if (this->getOutputSocket(0)->isConnected()) { TextureAlphaOperation *alphaOperation = new TextureAlphaOperation(); diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index 679589a7ce1..f5dab52d021 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -51,6 +51,6 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * imageSocket->relinkConnections(viewerOperation->getInputSocket(0), 0, graph); alphaSocket->relinkConnections(viewerOperation->getInputSocket(1)); graph->addOperation(viewerOperation); - addPreviewOperation(graph, viewerOperation->getInputSocket(0), 0); + addPreviewOperation(graph, viewerOperation->getInputSocket(0)); } } diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index 1050fc57194..c48f3b0a291 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -34,8 +34,9 @@ BokehBlurOperation::BokehBlurOperation() : NodeOperation() this->addInputSocket(COM_DT_VALUE); this->addOutputSocket(COM_DT_COLOR); this->setComplex(true); + this->setOpenCL(true); - this->size = .01; + this->size = 1.0f; this->inputProgram = NULL; this->inputBokehProgram = NULL; @@ -90,7 +91,7 @@ void BokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer * int bufferwidth = inputBuffer->getWidth(); int bufferstartx = inputBuffer->getRect()->xmin; int bufferstarty = inputBuffer->getRect()->ymin; - int pixelSize = this->size*this->getWidth(); + int pixelSize = this->size*this->getWidth()/100.0f; int miny = y - pixelSize; int maxy = y + pixelSize; @@ -142,10 +143,10 @@ bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe rcti newInput; rcti bokehInput; - newInput.xmax = input->xmax + (size*this->getWidth()); - newInput.xmin = input->xmin - (size*this->getWidth()); - newInput.ymax = input->ymax + (size*this->getWidth()); - newInput.ymin = input->ymin - (size*this->getWidth()); + newInput.xmax = input->xmax + (size*this->getWidth()/100.0f); + newInput.xmin = input->xmin - (size*this->getWidth()/100.0f); + newInput.ymax = input->ymax + (size*this->getWidth()/100.0f); + newInput.ymin = input->ymin - (size*this->getWidth()/100.0f); NodeOperation *operation = getInputOperation(1); bokehInput.xmax = operation->getWidth(); @@ -165,3 +166,27 @@ bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe } return false; } + +static cl_kernel kernel = 0; +void BokehBlurOperation::executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, + list *clKernelsToCleanUp) +{ + if (!kernel) { + kernel = COM_clCreateKernel(program, "bokehBlurKernel", NULL); + } + cl_int radius = this->getWidth()*this->size/100.0f; + cl_int step = this->getStep(); + + COM_clAttachMemoryBufferToKernelParameter(context, kernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->inputBoundingBoxReader); + COM_clAttachMemoryBufferToKernelParameter(context, kernel, 1, 4, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); + COM_clAttachMemoryBufferToKernelParameter(context, kernel, 2, -1, clMemToCleanUp, inputMemoryBuffers, this->inputBokehProgram); + COM_clAttachOutputMemoryBufferToKernelParameter(kernel, 3, clOutputBuffer); + COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, 5, outputMemoryBuffer); + clSetKernelArg(kernel, 6, sizeof(cl_int), &radius); + clSetKernelArg(kernel, 7, sizeof(cl_int), &step); + COM_clAttachSizeToKernelParameter(kernel, 8); + + COM_clEnqueueRange(queue, kernel, outputMemoryBuffer, 9); +} diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h index ce14faa8596..3cdd995b1df 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h @@ -56,5 +56,7 @@ public: bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void setSize(float size) {this->size = size;} + + void executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, list *clKernelsToCleanUp); }; #endif diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp index 8aee54013b1..069bbde5e73 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp @@ -28,6 +28,7 @@ extern "C" { #include "BKE_colortools.h" #ifdef __cplusplus } +#include "MEM_guardedalloc.h" #endif ColorCurveOperation::ColorCurveOperation(): CurveBaseOperation() @@ -59,6 +60,9 @@ void ColorCurveOperation::initExecution() void ColorCurveOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) { + CurveMapping* cumap = this->curveMapping; + CurveMapping* workingCopy = (CurveMapping*)MEM_dupallocN(cumap); + float black[4]; float white[4]; float fac[4]; @@ -67,13 +71,13 @@ void ColorCurveOperation::executePixel(float *color, float x, float y, PixelSamp this->inputBlackProgram->read(black, x, y, sampler, inputBuffers); this->inputWhiteProgram->read(white, x, y, sampler, inputBuffers); - curvemapping_set_black_white(this->curveMapping, black, white); + curvemapping_set_black_white(workingCopy, black, white); this->inputFacProgram->read(fac, x, y, sampler, inputBuffers); this->inputImageProgram->read(image, x, y, sampler, inputBuffers); if (fac[0] >= 1.0) - curvemapping_evaluate_premulRGBF(this->curveMapping, color, image); + curvemapping_evaluate_premulRGBF(workingCopy, color, image); else if (*fac<=0.0) { color[0] = image[0]; color[1] = image[1]; @@ -81,12 +85,13 @@ void ColorCurveOperation::executePixel(float *color, float x, float y, PixelSamp } else { float col[4], mfac = 1.0f-*fac; - curvemapping_evaluate_premulRGBF(this->curveMapping, col, image); + curvemapping_evaluate_premulRGBF(workingCopy, col, image); color[0] = mfac*image[0] + *fac*col[0]; color[1] = mfac*image[1] + *fac*col[1]; color[2] = mfac*image[2] + *fac*col[2]; } color[3] = image[3]; + MEM_freeN(workingCopy); } void ColorCurveOperation::deinitExecution() @@ -97,3 +102,61 @@ void ColorCurveOperation::deinitExecution() this->inputWhiteProgram = NULL; curvemapping_premultiply(this->curveMapping, 1); } + + +// Constant level curve mapping + +ConstantLevelColorCurveOperation::ConstantLevelColorCurveOperation(): CurveBaseOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + + this->inputFacProgram = NULL; + this->inputImageProgram = NULL; + + this->setResolutionInputSocketIndex(1); +} +void ConstantLevelColorCurveOperation::initExecution() +{ + CurveBaseOperation::initExecution(); + this->inputFacProgram = this->getInputSocketReader(0); + this->inputImageProgram = this->getInputSocketReader(1); + + curvemapping_premultiply(this->curveMapping, 0); + + curvemapping_set_black_white(this->curveMapping, this->black, this->white); +} + +void ConstantLevelColorCurveOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) +{ + float fac[4]; + float image[4]; + + + this->inputFacProgram->read(fac, x, y, sampler, inputBuffers); + this->inputImageProgram->read(image, x, y, sampler, inputBuffers); + + if (fac[0] >= 1.0) + curvemapping_evaluate_premulRGBF(this->curveMapping, color, image); + else if (*fac<=0.0) { + color[0] = image[0]; + color[1] = image[1]; + color[2] = image[2]; + } + else { + float col[4], mfac = 1.0f-*fac; + curvemapping_evaluate_premulRGBF(this->curveMapping, col, image); + color[0] = mfac*image[0] + *fac*col[0]; + color[1] = mfac*image[1] + *fac*col[1]; + color[2] = mfac*image[2] + *fac*col[2]; + } + color[3] = image[3]; +} + +void ConstantLevelColorCurveOperation::deinitExecution() +{ + this->inputFacProgram = NULL; + this->inputImageProgram = NULL; + curvemapping_premultiply(this->curveMapping, 1); +} diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.h b/source/blender/compositor/operations/COM_ColorCurveOperation.h index 15f9fd25e81..6ce5befb14a 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.h +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.h @@ -53,4 +53,37 @@ public: */ void deinitExecution(); }; + +class ConstantLevelColorCurveOperation : public CurveBaseOperation { +private: + /** + * Cached reference to the inputProgram + */ + SocketReader * inputFacProgram; + SocketReader * inputImageProgram; + float black[3]; + float white[3]; + +public: + ConstantLevelColorCurveOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setBlackLevel(float black[3]) {this->black[0] =black[0];this->black[1] =black[1];this->black[2] =black[2]; } + void setWhiteLevel(float white[3]) {this->white[0] =white[0];this->white[1] =white[1];this->white[2] =white[2]; } +}; + #endif diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h index 41d43f896bb..13cb4f28324 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.h +++ b/source/blender/compositor/operations/COM_CompositorOperation.h @@ -63,7 +63,7 @@ public: bool isOutputOperation(bool rendering) const {return true;} void initExecution(); void deinitExecution(); - const int getRenderPriority() const {return 7;} + const CompositorPriority getRenderPriority() const {return COM_PRIORITY_MEDIUM;} void determineResolution(unsigned int resolution[], unsigned int preferredResolution[]); }; #endif diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl b/source/blender/compositor/operations/COM_OpenCLKernels.cl index 40932e54bc7..aeccfcab8b5 100644 --- a/source/blender/compositor/operations/COM_OpenCLKernels.cl +++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl @@ -1,10 +1,52 @@ /// This file contains all opencl kernels for node-operation implementations -__kernel void testKernel(__global __write_only image2d_t output) +// Global SAMPLERS +const sampler_t SAMPLER_NEAREST = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST; + +__constant const int2 zero = {0,0}; + +// KERNEL --- BOKEH BLUR --- +__kernel void bokehBlurKernel(__global __read_only image2d_t boundingBox, __global __read_only image2d_t inputImage, + __global __read_only image2d_t bokehImage, __global __write_only image2d_t output, + int2 offsetInput, int2 offsetOutput, int radius, int step, int2 dimension, int2 offset) { - int x = get_global_id(0); - int y = get_global_id(1); - int2 coords = {x, y}; - float4 color = {0.0f, 1.0f, 0.0f, 1.0f}; + int2 coords = {get_global_id(0), get_global_id(1)}; + coords += offset; + float tempBoundingBox; + float4 color = {0.0f,0.0f,0.0f,0.0f}; + float4 multiplyer = {0.0f,0.0f,0.0f,0.0f}; + float4 bokeh; + const float radius2 = radius*2.0f; + const int2 realCoordinate = coords + offsetOutput; + + tempBoundingBox = read_imagef(boundingBox, SAMPLER_NEAREST, coords).s0; + + if (tempBoundingBox > 0.0f) { + const int2 bokehImageDim = get_image_dim(bokehImage); + const int2 bokehImageCenter = bokehImageDim/2; + const int2 minXY = max(realCoordinate - radius, zero); + const int2 maxXY = min(realCoordinate + radius, dimension); + int nx, ny; + + float2 uv; + int2 inputXy; + + for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny +=step, inputXy.y+=step) { + uv.y = ((realCoordinate.y-ny)/radius2)*bokehImageDim.y+bokehImageCenter.y; + + for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx +=step, inputXy.x+=step) { + uv.x = ((realCoordinate.x-nx)/radius2)*bokehImageDim.x+bokehImageCenter.x; + bokeh = read_imagef(bokehImage, SAMPLER_NEAREST, uv); + color += bokeh * read_imagef(inputImage, SAMPLER_NEAREST, inputXy); + multiplyer += bokeh; + } + } + color /= multiplyer; + + } else { + int2 imageCoordinates = realCoordinate - offsetInput; + color = read_imagef(inputImage, SAMPLER_NEAREST, imageCoordinates); + } + write_imagef(output, coords, color); } diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl.cpp b/source/blender/compositor/operations/COM_OpenCLKernels.cl.cpp deleted file mode 100644 index 1024d460044..00000000000 --- a/source/blender/compositor/operations/COM_OpenCLKernels.cl.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/// @todo: this source needs to be generated from COM_OpenCLKernels.cl. -/// not implemented yet. new data to h - -const char *sourcecode = "/// This file contains all opencl kernels for node-operation implementations \n" \ -"\n" \ -"__kernel void testKernel(__global __write_only image2d_t output)\n" \ -"{\n" \ -" int x = get_global_id(0);\n" \ -" int y = get_global_id(1);\n" \ -" int2 coords = {x, y}; \n" \ -" float4 color = {0.0f, 1.0f, 0.0f, 1.0f};\n" \ -" write_imagef(output, coords, color);\n" \ -"}\n" \ -"\0\n"; - diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl.h b/source/blender/compositor/operations/COM_OpenCLKernels.cl.h new file mode 100644 index 00000000000..3cf33c75272 --- /dev/null +++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl.h @@ -0,0 +1,55 @@ +/* clkernelstoh output of file */ + +const char * clkernelstoh_COM_OpenCLKernels_cl = "/// This file contains all opencl kernels for node-operation implementations\n" \ +"\n" \ +"// Global SAMPLERS\n" \ +"const sampler_t SAMPLER_NEAREST = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;\n" \ +"\n" \ +"__constant const int2 zero = {0,0};\n" \ +"\n" \ +"// KERNEL --- BOKEH BLUR ---\n" \ +"__kernel void bokehBlurKernel(__global __read_only image2d_t boundingBox, __global __read_only image2d_t inputImage,\n" \ +" __global __read_only image2d_t bokehImage, __global __write_only image2d_t output,\n" \ +" int2 offsetInput, int2 offsetOutput, int radius, int step, int2 dimension, int2 offset)\n" \ +"{\n" \ +" int2 coords = {get_global_id(0), get_global_id(1)};\n" \ +" coords += offset;\n" \ +" float tempBoundingBox;\n" \ +" float4 color = {0.0f,0.0f,0.0f,0.0f};\n" \ +" float4 multiplyer = {0.0f,0.0f,0.0f,0.0f};\n" \ +" float4 bokeh;\n" \ +" const float radius2 = radius*2.0f;\n" \ +" const int2 realCoordinate = coords + offsetOutput;\n" \ +"\n" \ +" tempBoundingBox = read_imagef(boundingBox, SAMPLER_NEAREST, coords).s0;\n" \ +"\n" \ +" if (tempBoundingBox > 0.0f) {\n" \ +" const int2 bokehImageDim = get_image_dim(bokehImage);\n" \ +" const int2 bokehImageCenter = bokehImageDim/2;\n" \ +" const int2 minXY = max(realCoordinate - radius, zero);;\n" \ +" const int2 maxXY = min(realCoordinate + radius, dimension);;\n" \ +" int nx, ny;\n" \ +"\n" \ +" float2 uv;\n" \ +" int2 inputXy;\n" \ +"\n" \ +" for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny +=step, inputXy.y+=step) {\n" \ +" uv.y = ((realCoordinate.y-ny)/radius2)*bokehImageDim.y+bokehImageCenter.y;\n" \ +"\n" \ +" for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx +=step, inputXy.x+=step) {\n" \ +" uv.x = ((realCoordinate.x-nx)/radius2)*bokehImageDim.x+bokehImageCenter.x;\n" \ +" bokeh = read_imagef(bokehImage, SAMPLER_NEAREST, uv);\n" \ +" color += bokeh * read_imagef(inputImage, SAMPLER_NEAREST, inputXy);\n" \ +" multiplyer += bokeh;\n" \ +" }\n" \ +" }\n" \ +" color /= multiplyer;\n" \ +"\n" \ +" } else {\n" \ +" int2 imageCoordinates = realCoordinate - offsetInput;\n" \ +" color = read_imagef(inputImage, SAMPLER_NEAREST, imageCoordinates);\n" \ +" }\n" \ +"\n" \ +" write_imagef(output, coords, color);\n" \ +"}\n" \ +"\0"; diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index 0e37432ca5b..9b9fb023467 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -49,7 +49,7 @@ public: bool isOutputOperation(bool rendering) const {return true;} void initExecution(); void deinitExecution(); - const int getRenderPriority() const {return 7;} + const CompositorPriority getRenderPriority() const {return COM_PRIORITY_LOW;} }; /* extra info for OpenEXR layers */ @@ -83,7 +83,7 @@ public: bool isOutputOperation(bool rendering) const {return true;} void initExecution(); void deinitExecution(); - const int getRenderPriority() const {return 7;} + const CompositorPriority getRenderPriority() const {return COM_PRIORITY_LOW;} }; #endif diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index a7b6fc93b25..4975f13a285 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -46,7 +46,6 @@ PreviewOperation::PreviewOperation() : NodeOperation() this->input = NULL; this->divider = 1.0f; this->node = NULL; - this->priority = 0; } void PreviewOperation::initExecution() @@ -129,7 +128,7 @@ void PreviewOperation::determineResolution(unsigned int resolution[], unsigned i resolution[1] = height; } -const int PreviewOperation::getRenderPriority() const +const CompositorPriority PreviewOperation::getRenderPriority() const { - return this->priority; + return COM_PRIORITY_LOW; } diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h index 8450b7fc556..3d1cd38a5ea 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.h +++ b/source/blender/compositor/operations/COM_PreviewOperation.h @@ -37,20 +37,18 @@ protected: const bNodeTree *tree; SocketReader *input; float divider; - int priority; public: PreviewOperation(); bool isOutputOperation(bool rendering) const {return true;} void initExecution(); void deinitExecution(); - const int getRenderPriority() const; + const CompositorPriority getRenderPriority() const; void executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer **memoryBuffers); void determineResolution(unsigned int resolution[], unsigned int preferredResolution[]); void setbNode(bNode *node) { this->node = node;} void setbNodeTree(const bNodeTree *tree) { this->tree = tree;} bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void setPriority(int priority) { this->priority = priority; } }; #endif diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 71fc53e8f8e..809c688195f 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -88,12 +88,12 @@ void ViewerBaseOperation::deinitExecution() this->outputBuffer = NULL; } -const int ViewerBaseOperation::getRenderPriority() const +const CompositorPriority ViewerBaseOperation::getRenderPriority() const { if (this->isActiveViewerOutput()) { - return 8; + return COM_PRIORITY_HIGH; } else { - return 0; + return COM_PRIORITY_LOW; } } diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h index f5f30809f65..51fa8cecc0d 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h @@ -56,7 +56,7 @@ public: float getCenterX() { return this->centerX; } float getCenterY() { return this->centerY; } OrderOfChunks getChunkOrder() { return this->chunkOrder; } - const int getRenderPriority() const; + const CompositorPriority getRenderPriority() const; void setColorManagement(bool doColorManagement) {this->doColorManagement = doColorManagement;} void setColorPredivide(bool doColorPredivide) {this->doColorPredivide = doColorPredivide;} bool isViewerOperation() {return true;} diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 498add2fc87..222b879645c 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -111,10 +111,9 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me memoryBuffer->setCreatedState(); } -void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** inputMemoryBuffers) +void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** inputMemoryBuffers, MemoryBuffer* outputBuffer) { - MemoryBuffer *outputMemoryBuffer = this->getMemoryProxy()->getBuffer();// @todo wrong implementation needs revision - float *outputFloatBuffer = outputMemoryBuffer->getBuffer(); + float *outputFloatBuffer = outputBuffer->getBuffer(); cl_int error; /* * 1. create cl_mem from outputbuffer @@ -125,8 +124,8 @@ void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program pr * note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4 */ // STEP 1 - const unsigned int outputBufferWidth = outputMemoryBuffer->getWidth(); - const unsigned int outputBufferHeight = outputMemoryBuffer->getHeight(); + const unsigned int outputBufferWidth = outputBuffer->getWidth(); + const unsigned int outputBufferHeight = outputBuffer->getHeight(); const cl_image_format imageFormat = { CL_RGBA, @@ -141,19 +140,26 @@ void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program pr clMemToCleanUp->push_back(clOutputBuffer); list *clKernelsToCleanUp = new list(); - this->input->executeOpenCL(context, program, queue, outputMemoryBuffer, clOutputBuffer, inputMemoryBuffers, clMemToCleanUp, clKernelsToCleanUp); + this->input->executeOpenCL(context, program, queue, outputBuffer, clOutputBuffer, inputMemoryBuffers, clMemToCleanUp, clKernelsToCleanUp); // STEP 3 size_t origin[3] = {0,0,0}; size_t region[3] = {outputBufferWidth,outputBufferHeight,1}; +// clFlush(queue); +// clFinish(queue); + error = clEnqueueBarrier(queue); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } error = clEnqueueReadImage(queue, clOutputBuffer, CL_TRUE, origin, region, 0, 0, outputFloatBuffer, 0, NULL, NULL); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + + this->getMemoryProxy()->getBuffer()->copyContentFrom(outputBuffer); + // STEP 4 + while (clMemToCleanUp->size()>0) { cl_mem mem = clMemToCleanUp->front(); error = clReleaseMemObject(mem); diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h index b17122d68f0..6f2c49c49bd 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.h +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h @@ -46,7 +46,7 @@ public: void initExecution(); void deinitExecution(); void setbNodeTree(const bNodeTree *tree) {this->tree = tree;} - void executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** memoryBuffers); + void executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer** memoryBuffers, MemoryBuffer* outputBuffer); }; #endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 1e8541214ce..d37a2739fc3 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2294,7 +2294,7 @@ static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) { // node_composit_backdrop_canvas(snode, backdrop, node, x, y); - if (node->custom1 == 0) { /// @todo: why did we need this one? + if (node->custom1 == 0) { const float backdropWidth = backdrop->x; const float backdropHeight = backdrop->y; const float cx = x + snode->zoom * backdropWidth * node->custom3; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 59506f31b60..5be7688d714 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -241,6 +241,14 @@ typedef struct bNodeLink { #define NTREE_QUALITY_MEDIUM 1 #define NTREE_QUALITY_LOW 2 +/* tree->chunksize */ +#define NTREE_CHUNCKSIZE_32 32 +#define NTREE_CHUNCKSIZE_64 64 +#define NTREE_CHUNCKSIZE_128 128 +#define NTREE_CHUNCKSIZE_256 256 +#define NTREE_CHUNCKSIZE_512 512 +#define NTREE_CHUNCKSIZE_1024 1024 + /* the basis for a Node tree, all links and nodes reside internal here */ /* only re-usable node trees are in the library though, materials and textures allocate own tree struct */ typedef struct bNodeTree { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 562684799b4..65d572c6c11 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -71,6 +71,16 @@ EnumPropertyItem node_quality_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem node_chunksize_items[] = { + {NTREE_CHUNCKSIZE_32, "32", 0, "32x32", "Chunksize of 32x32"}, + {NTREE_CHUNCKSIZE_64, "64", 0, "64x64", "Chunksize of 64x64"}, + {NTREE_CHUNCKSIZE_128, "128", 0, "128x128", "Chunksize of 128x128"}, + {NTREE_CHUNCKSIZE_256, "256", 0, "256x256", "Chunksize of 256x256"}, + {NTREE_CHUNCKSIZE_512, "512", 0, "512x512", "Chunksize of 512x512"}, + {NTREE_CHUNCKSIZE_1024, "1024", 0, "1024x1024", "Chunksize of 1024x1024"}, + {0, NULL, 0, NULL, NULL} +}; + EnumPropertyItem node_socket_type_items[] = { {SOCK_FLOAT, "VALUE", 0, "Value", ""}, {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, @@ -3184,6 +3194,25 @@ static void def_cmp_ellipsemask(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_bokehblur(StructRNA *srna) +{ + PropertyRNA *prop; + prop = RNA_def_property(srna, "f_stop", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "custom3"); + RNA_def_property_range(prop, 0.0f, 128.0f); + RNA_def_property_ui_text(prop, "fStop", + "Amount of focal blur, 128=infinity=perfect focus, half the value doubles " + "the blur radius"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "blur_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "custom4"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Max Blur", "Blur limit, maximum CoC radius"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + +} + static void def_cmp_bokehimage(StructRNA *srna) { PropertyRNA *prop; @@ -4029,11 +4058,11 @@ static void rna_def_composite_nodetree(BlenderRNA *brna) RNA_def_property_enum_items(prop, node_quality_items); RNA_def_property_ui_text(prop, "Edit Quality", "Quality when editing"); - prop = RNA_def_property(srna, "chunk_size", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "chunksize"); + prop = RNA_def_property(srna, "chunk_size", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "chunksize"); + RNA_def_property_enum_items(prop, node_chunksize_items); RNA_def_property_ui_text(prop, "Chunksize", "Max size of a tile (smaller values gives better distribution " "of multiple threads, but more overhead)"); - RNA_def_property_range(prop, 32, 1024); prop = RNA_def_property(srna, "use_opencl", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_COM_OPENCL); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index d5b33f0d01b..2b8050adca7 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -163,6 +163,7 @@ DefNode( CompositorNode, CMP_NODE_MOVIEDISTORTION,def_cmp_moviedistortion,"MOVIE DefNode( CompositorNode, CMP_NODE_MASK_BOX, def_cmp_boxmask, "BOXMASK" ,BoxMask, "Box mask", "" ) DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIPSEMASK" ,EllipseMask, "Ellipse mask", "" ) DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE" ,BokehImage, "Bokeh image", "" ) +DefNode( CompositorNode, CMP_NODE_BOKEHBLUR, def_cmp_bokehblur, "BOKEHBLUR" ,BokehBlur, "Bokeh Blur", "" ) DefNode( CompositorNode, CMP_NODE_SWITCH, def_cmp_switch, "SWITCH" ,Switch, "Switch", "" ) DefNode( CompositorNode, CMP_NODE_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "ColorCorrection", "" ) DefNode( CompositorNode, CMP_NODE_MASK, def_cmp_mask, "MASK", Mask, "Mask", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c index ab679b9242f..06b6e79444a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c @@ -39,7 +39,7 @@ static bNodeSocketTemplate cmp_node_bokehblur_in[]= { { SOCK_RGBA, 1, N_("Image"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Bokeh"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Size"), 0.01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f}, + { SOCK_FLOAT, 1, N_("Size"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, { SOCK_FLOAT, 1, N_("Bounding box"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; @@ -49,6 +49,12 @@ static bNodeSocketTemplate cmp_node_bokehblur_out[]= { { -1, 0, "" } }; +static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + node->custom3 = 4.0f; + node->custom4 = 16.0f; +} + void register_node_type_cmp_bokehblur(bNodeTreeType *ttype) { static bNodeType ntype; @@ -56,5 +62,7 @@ void register_node_type_cmp_bokehblur(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_bokehblur_in, cmp_node_bokehblur_out); node_type_size(&ntype, 120, 80, 200); + node_type_init(&ntype, node_composit_init_bokehblur); + nodeRegisterType(ttype, &ntype); } -- cgit v1.2.3 From ae3062b741f3951048df8b26e09ce61354c5248d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 09:27:40 +0000 Subject: fix for own bug - evaluating past the last frame of a mask didnt work at all. --- source/blender/blenkernel/intern/mask.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 66f10aca652..1f1dc6a0cc8 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1779,10 +1779,17 @@ int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const int frame, } } - *r_masklay_shape_a = NULL; - *r_masklay_shape_b = NULL; + if ((masklay_shape = masklay->splines_shapes.last)) { + *r_masklay_shape_a = masklay_shape; + *r_masklay_shape_b = NULL; + return 1; + } + else { + *r_masklay_shape_a = NULL; + *r_masklay_shape_b = NULL; - return 0; + return 0; + } } MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, const int frame) -- cgit v1.2.3 From 4413903370265d08b55049648e3f58d3ee87a830 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 09:35:51 +0000 Subject: support for subframe animation evaluation for masks. --- source/blender/blenkernel/BKE_mask.h | 4 ++-- source/blender/blenkernel/intern/mask.c | 6 +++--- source/blender/blenkernel/intern/sequencer.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 32f86bd3ebe..a6f2f73720a 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -120,7 +120,7 @@ void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *u void BKE_mask_update_display(struct Mask *mask, float ctime); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe); -void BKE_mask_evaluate(struct Mask *mask, float ctime, const int do_newframe); +void BKE_mask_evaluate(struct Mask *mask, const float ctime, const int do_newframe); void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe); void BKE_mask_parent_init(struct MaskParent *parent); void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); @@ -145,7 +145,7 @@ void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape_b, const float fac); struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, const int frame); -int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const int frame, +int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const float frame, struct MaskLayerShape **r_masklay_shape_a, struct MaskLayerShape **r_masklay_shape_b); struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 1f1dc6a0cc8..02c1169892c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1463,7 +1463,7 @@ void BKE_mask_spline_ensure_deform(MaskSpline *spline) } } -void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) +void BKE_mask_evaluate(Mask *mask, const float ctime, const int do_newframe) { MaskLayer *masklay; @@ -1475,7 +1475,7 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe) MaskLayerShape *masklay_shape_b; int found; - if ((found = BKE_mask_layer_shape_find_frame_range(masklay, (int)ctime, + if ((found = BKE_mask_layer_shape_find_frame_range(masklay, ctime, &masklay_shape_a, &masklay_shape_b))) { if (found == 1) { @@ -1750,7 +1750,7 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int fr } /* when returning 2 - the frame isnt found but before/after frames are */ -int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const int frame, +int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const float frame, MaskLayerShape **r_masklay_shape_a, MaskLayerShape **r_masklay_shape_b) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 4f47a7f6f44..af5b7716bbc 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2067,7 +2067,7 @@ static ImBuf *seq_render_mask_strip( return NULL; } - BKE_mask_evaluate(seq->mask, (int)(seq->mask->sfra + nr), TRUE); + BKE_mask_evaluate(seq->mask, seq->mask->sfra + nr, TRUE); maskbuf = MEM_callocN(sizeof(float) * context.rectx * context.recty, __func__); -- cgit v1.2.3 From 477d12d1fc106fcbb91f0eb4071e2bb1ca47b196 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 09:57:23 +0000 Subject: fix for bug in point slide using freed memory when auto-keying. --- source/blender/editors/mask/mask_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 599f3371cac..67fd57ed50b 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -751,8 +751,6 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_RELEASE) { Scene *scene = CTX_data_scene(C); - free_slide_point_data(op->customdata); - /* dont key sliding feather uw's */ if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) { if (IS_AUTOKEY_ON(scene)) { @@ -760,6 +758,8 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) } } + free_slide_point_data(op->customdata); + WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); -- cgit v1.2.3 From 68c365e2f040cb61266d6ef1309fb22d064ab0d0 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Fri, 8 Jun 2012 13:06:06 +0000 Subject: Index: source/blender/gpu/intern/gpu_draw.c =================================================================== --- source/blender/gpu/intern/gpu_draw.c (revision 47568) +++ source/blender/gpu/intern/gpu_draw.c (working copy) @@ -230,11 +230,12 @@ Image *ima, *curima; int domipmap, linearmipmap; + int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */ int alphablend; float anisotropic; MTFace *lasttface; -} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, 1.f, NULL}; +} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.f, NULL}; /* Mipmap settings */ @@ -256,7 +257,7 @@ static int gpu_get_mipmap(void) { - return GTS.domipmap; + return GTS.domipmap && !GTS.texpaint; } static GLenum gpu_get_mipmap_filter(int mag) @@ -730,6 +731,8 @@ if (!GTS.domipmap) return; + GTS.texpaint = !mipmap; + if (mipmap) { for (ima=G.main->image.first; ima; ima=ima->id.next) { if (ima->bindcode) { --- source/blender/gpu/intern/gpu_draw.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7ae4aa550f9..3e53f2f3836 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -230,11 +230,12 @@ static struct GPUTextureState { Image *ima, *curima; int domipmap, linearmipmap; + int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */ int alphablend; float anisotropic; MTFace *lasttface; -} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, 1.f, NULL}; +} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.f, NULL}; /* Mipmap settings */ @@ -256,7 +257,7 @@ void GPU_set_linear_mipmap(int linear) static int gpu_get_mipmap(void) { - return GTS.domipmap; + return GTS.domipmap && !GTS.texpaint; } static GLenum gpu_get_mipmap_filter(int mag) @@ -730,6 +731,8 @@ void GPU_paint_set_mipmap(int mipmap) if (!GTS.domipmap) return; + GTS.texpaint = !mipmap; + if (mipmap) { for (ima=G.main->image.first; ima; ima=ima->id.next) { if (ima->bindcode) { -- cgit v1.2.3 From b33c5168f4070e30f5ef66dcca76d1ad3c4aaa38 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 14:31:38 +0000 Subject: mask animation keys now editable in the dope sheet (duplicate, transform, delete, select- etc). --- source/blender/blenkernel/BKE_mask.h | 1 + source/blender/blenkernel/intern/mask.c | 13 ++ .../editors/animation/anim_channels_defines.c | 170 ++++++++++++++ .../blender/editors/animation/anim_channels_edit.c | 59 +++++ source/blender/editors/animation/anim_filter.c | 118 +++++++++- source/blender/editors/animation/keyframes_draw.c | 19 +- source/blender/editors/include/ED_anim_api.h | 16 +- source/blender/editors/include/ED_gpencil.h | 3 +- source/blender/editors/include/ED_keyframes_draw.h | 2 + source/blender/editors/include/ED_mask.h | 24 +- source/blender/editors/mask/CMakeLists.txt | 1 + source/blender/editors/mask/mask_editaction.c | 253 +++++++++++++++++++++ source/blender/editors/space_action/action_draw.c | 15 ++ source/blender/editors/space_action/action_edit.c | 72 ++++-- .../blender/editors/space_action/action_select.c | 52 ++++- source/blender/editors/transform/transform.h | 2 +- .../editors/transform/transform_conversions.c | 185 ++++++++++++++- .../blender/editors/transform/transform_generics.c | 4 +- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/makesdna/DNA_mask_types.h | 25 +- source/blender/makesrna/intern/rna_space.c | 1 + 21 files changed, 991 insertions(+), 48 deletions(-) create mode 100644 source/blender/editors/mask/mask_editaction.c diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index a6f2f73720a..ec2eb82a9eb 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -151,6 +151,7 @@ int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const float struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame); void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape); struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, const int frame); +struct MaskLayerShape *BKE_mask_layer_shape_duplicate(struct MaskLayerShape *masklay_shape); void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape); void BKE_mask_layer_shape_sort(struct MaskLayer *masklay); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 02c1169892c..bb2940091e4 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1820,6 +1820,19 @@ MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, const int return masklay_shape; } +MaskLayerShape *BKE_mask_layer_shape_duplicate(MaskLayerShape *masklay_shape) +{ + MaskLayerShape *masklay_shape_copy; + + masklay_shape_copy = MEM_dupallocN(masklay_shape); + + if (LIKELY(masklay_shape_copy->data)) { + masklay_shape_copy->data = MEM_dupallocN(masklay_shape_copy->data); + } + + return masklay_shape_copy; +} + void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape) { BLI_remlink(&masklay->splines_shapes, masklay_shape); diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 7f7d269a7c3..f6b301c4594 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -54,6 +54,7 @@ #include "DNA_world_types.h" #include "DNA_gpencil_types.h" #include "DNA_speaker_types.h" +#include "DNA_mask_types.h" #include "RNA_access.h" @@ -2516,6 +2517,172 @@ static bAnimChannelType ACF_GPL = acf_gpl_setting_ptr /* pointer for setting */ }; + +/* Mask Datablock ------------------------------------------- */ + +/* get backdrop color for mask datablock widget */ +static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3]) +{ + /* these are ID-blocks, but not exactly standalone... */ + UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color); +} + +// TODO: just get this from RNA? +static int acf_mask_icon(bAnimListElem *UNUSED(ale)) +{ + return ICON_GREASEPENCIL; // MASK_TODO - need real icon +} + +/* check if some setting exists for this channel */ +static short acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) +{ + switch (setting) { + /* only select and expand supported */ + case ACHANNEL_SETTING_SELECT: + case ACHANNEL_SETTING_EXPAND: + return 1; + + default: + return 0; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) +{ + /* clear extra return data first */ + *neg = 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return AGRP_SELECTED; + + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return MASK_ANIMF_EXPAND; + } + + /* this shouldn't happen */ + return 0; +} + +/* get pointer to the setting */ +static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) +{ + Mask *mask = (Mask *)ale->data; + + /* all flags are just in mask->flag for now... */ + return GET_ACF_FLAG_PTR(mask->flag, type); +} + +/* mask datablock type define */ +static bAnimChannelType ACF_MASKDATA = +{ + "Mask Datablock", /* type name */ + + acf_mask_color, /* backdrop color */ + acf_group_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_generic_idfill_nameprop, /* name prop */ + acf_mask_icon, /* icon */ + + acf_mask_setting_valid, /* has setting */ + acf_mask_setting_flag, /* flag for setting */ + acf_mask_setting_ptr /* pointer for setting */ +}; + +/* Mask Layer ------------------------------------------- */ + +/* name for grease pencil layer entries */ +static void acf_masklay_name(bAnimListElem *ale, char *name) +{ + MaskLayer *masklay = (MaskLayer *)ale->data; + + if (masklay && name) + BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE); +} + +/* name property for grease pencil layer entries */ +static short acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop) +{ + if (ale->data) { + RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr); + *prop = RNA_struct_name_property(ptr->type); + + return (*prop != NULL); + } + + return 0; +} + +/* check if some setting exists for this channel */ +static short acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) +{ + switch (setting) { + /* unsupported */ + case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */ + case ACHANNEL_SETTING_VISIBLE: /* graph editor only */ + return 0; + + /* always available */ + default: + return 1; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) +{ + /* clear extra return data first */ + *neg = 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return MASK_LAYERFLAG_SELECT; + +// case ACHANNEL_SETTING_MUTE: /* muted */ +// return GP_LAYER_HIDE; + + case ACHANNEL_SETTING_PROTECT: /* protected */ + // *neg = 1; - if we change this to edtiability + return MASK_LAYERFLAG_LOCKED; + + default: /* unsupported */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) +{ + MaskLayer *masklay = (MaskLayer *)ale->data; + + /* all flags are just in agrp->flag for now... */ + return GET_ACF_FLAG_PTR(masklay->flag, type); +} + +/* grease pencil layer type define */ +static bAnimChannelType ACF_MASKLAYER = +{ + "Mask Layer", /* type name */ + + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_flexible, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_masklay_name, /* name */ + acf_masklay_name_prop, /* name prop */ + NULL, /* icon */ + + acf_masklay_setting_valid, /* has setting */ + acf_masklay_setting_flag, /* flag for setting */ + acf_masklay_setting_ptr /* pointer for setting */ +}; + + /* *********************************************** */ /* Type Registration and General Access */ @@ -2566,6 +2733,9 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */ animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */ + animchannelTypeInfo[type++] = &ACF_MASKDATA; /* Mask Datablock */ + animchannelTypeInfo[type++] = &ACF_MASKLAYER; /* Mask Layer */ + // TODO: these types still need to be implemented!!! // probably need a few extra flags for these special cases... animchannelTypeInfo[type++] = NULL; /* NLA Track */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index dc0886a473e..5c57407d14e 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -43,6 +43,7 @@ #include "DNA_scene_types.h" #include "DNA_key_types.h" #include "DNA_gpencil_types.h" +#include "DNA_mask_types.h" #include "RNA_access.h" #include "RNA_define.h" @@ -51,6 +52,7 @@ #include "BKE_fcurve.h" #include "BKE_gpencil.h" #include "BKE_context.h" +#include "BKE_mask.h" #include "BKE_global.h" #include "UI_view2d.h" @@ -258,6 +260,10 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s if (ale->flag & GP_LAYER_SELECT) sel = ACHANNEL_SETFLAG_CLEAR; break; + case ANIMTYPE_MASKLAYER: + if (ale->flag & MASK_LAYERFLAG_SELECT) + sel = ACHANNEL_SETFLAG_CLEAR; + break; } } } @@ -354,6 +360,14 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT); } break; + + case ANIMTYPE_MASKLAYER: + { + MaskLayer *masklay = (MaskLayer *)ale->data; + + ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT); + } + break; } } @@ -1055,6 +1069,10 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op) /* Grease Pencil channels */ printf("Grease Pencil not supported for moving yet\n"); } + else if (ac.datatype == ANIMCONT_MASK) { + /* Grease Pencil channels */ + printf("Mask does not supported for moving yet\n"); + } else if (ac.datatype == ANIMCONT_ACTION) { /* Directly rearrange action's channels */ rearrange_action_channels(&ac, ac.data, mode); @@ -1205,6 +1223,17 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) BLI_freelinkN(&gpd->layers, gpl); } break; + + case ANIMTYPE_MASKLAYER: + { + /* Grease Pencil layer */ + Mask *mask = (Mask *)ale->id; + MaskLayer *masklay = (MaskLayer *)ale->data; + + /* try to delete the layer's data and the layer itself */ + BKE_mask_layer_remove(mask, masklay); + } + break; } } @@ -2287,6 +2316,36 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in notifierFlags |= (ND_ANIMCHAN | NA_EDITED); } break; + case ANIMTYPE_MASKDATABLOCK: + { + Mask *mask = (Mask *)ale->data; + + /* toggle expand + * - although the triangle widget already allows this, the whole channel can also be used for this purpose + */ + mask->flag ^= MASK_ANIMF_EXPAND; + + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + } + break; + case ANIMTYPE_MASKLAYER: + { + MaskLayer *masklay = (MaskLayer *)ale->data; + + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* invert selection status of this layer only */ + masklay->flag ^= MASK_LAYERFLAG_SELECT; + } + else { + /* select layer by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + masklay->flag |= MASK_LAYERFLAG_SELECT; + } + + notifierFlags |= (ND_ANIMCHAN | NA_EDITED); + } + break; default: if (G.debug & G_DEBUG) printf("Error: Invalid channel type in mouse_anim_channels()\n"); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 160e6957513..752e458ef78 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -56,6 +56,7 @@ #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_key_types.h" +#include "DNA_mask_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" @@ -86,6 +87,7 @@ #include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" +#include "BKE_mask.h" #include "BKE_sequencer.h" #include "BKE_utildefines.h" @@ -173,6 +175,22 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return 1; + case SACTCONT_MASK: /* Grease Pencil */ // XXX review how this mode is handled... + /* update scene-pointer (no need to check for pinning yet, as not implemented) */ +{ + // TODO, other methods to get the mask + // Sequence *seq = BKE_sequencer_active_get(ac->scene); + //MovieClip *clip = ac->scene->clip; +// struct Mask *mask = seq ? seq->mask : NULL; + + saction->ads.source = (ID *)ac->scene;; + + ac->datatype = ANIMCONT_MASK; + ac->data = &saction->ads; + + ac->mode = saction->mode; + return 1; +} case SACTCONT_DOPESHEET: /* DopeSheet */ /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; @@ -807,7 +825,18 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne ale->datatype = ALE_GPFRAME; } break; - + + case ANIMTYPE_MASKLAYER: + { + MaskLayer *masklay = (MaskLayer *)data; + + ale->flag = masklay->flag; + + ale->key_data = NULL; + ale->datatype = ALE_MASKLAY; + } + break; + case ANIMTYPE_NLATRACK: { NlaTrack *nlt = (NlaTrack *)data; @@ -1353,6 +1382,83 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i return items; } +static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode) +{ + MaskLayer *masklay_act = BKE_mask_layer_active(mask); + MaskLayer *masklay; + size_t items = 0; + + /* loop over layers as the conditions are acceptable */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + /* only if selected */ + if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay)) ) { + /* only if editable */ +// if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) { + /* active... */ + if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) { + /* add to list */ + ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask); + + +// if (filter_mode & ANIMFILTER_TMP_PEEK) +// return 1; +// else { +// bAnimListElem *ale = make_new_animlistelem(masklay, channel_type, (ID *)owner_id); +// if (ale) { +// BLI_addtail(anim_data, ale); +// items ++; +// } +// } + + } +// } + } + } + + return items; +} + +static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int filter_mode) +{ + Mask *mask; + size_t items = 0; + + /* for now, grab grease pencil datablocks directly from main */ + // XXX: this is not good... + for (mask = G.main->mask.first; mask; mask = mask->id.next) { + ListBase tmp_data = {NULL, NULL}; + size_t tmp_items = 0; + + /* only show if gpd is used by something... */ + if (ID_REAL_USERS(mask) < 1) + continue; + + /* add gpencil animation channels */ + BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask)) + { + tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode); + } + END_ANIMFILTER_SUBCHANNELS; + + /* did we find anything? */ + if (tmp_items) { + /* include data-expand widget first */ + if (filter_mode & ANIMFILTER_LIST_CHANNELS) { + /* add gpd as channel too (if for drawing, and it has layers) */ + ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL); + } + + /* now add the list of collected channels */ + BLI_movelisttolist(anim_data, &tmp_data); + BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL)); + items += tmp_items; + } + } + + /* return the number of items added to the list */ + return items; +} + /* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */ // TODO: how to handle group nodes is still unclear... static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode) @@ -2280,7 +2386,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact); } break; - + case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */ { /* the check for the DopeSheet summary is included here since the summary works here too */ @@ -2294,7 +2400,13 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo items = animdata_filter_gpencil(anim_data, data, filter_mode); } break; - + + case ANIMCONT_MASK: + { + items = animdata_filter_mask(anim_data, data, filter_mode); + } + break; + case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */ { /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */ diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index cee8d15a807..e6fc4d5a168 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -209,7 +209,7 @@ static DLRBT_Node *nalloc_ak_masklayshape(void *data) /* store settings based on state of BezTriple */ ak->cfra = masklay_shape->frame; - ak->sel = (masklay_shape->flag & SELECT) ? SELECT : 0; + ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0; /* set 'modified', since this is used to identify long keyframes */ ak->modified = 1; @@ -224,7 +224,7 @@ static void nupdate_ak_masklayshape(void *node, void *data) MaskLayerShape *masklay_shape = (MaskLayerShape *)data; /* set selection status and 'touched' status */ - if (masklay_shape->flag & SELECT) ak->sel = SELECT; + if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT; ak->modified += 1; } @@ -818,6 +818,21 @@ void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos) BLI_dlrbTree_free(&keys); } +void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos) +{ + DLRBT_Tree keys; + + BLI_dlrbTree_init(&keys); + + mask_to_keylist(ads, masklay, &keys); + + BLI_dlrbTree_linkedlist_sync(&keys); + + draw_keylist(v2d, &keys, NULL, ypos, (masklay->flag & MASK_LAYERFLAG_LOCKED)); + + BLI_dlrbTree_free(&keys); +} + /* *************************** Keyframe List Conversions *************************** */ void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks) diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index d91b29bb281..24aa88a36bd 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -97,7 +97,8 @@ typedef enum eAnimCont_Types { ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */ ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */ ANIMCONT_NLA = 7, /* nla (bDopesheet) */ - ANIMCONT_CHANNEL = 8 /* animation channel (bAnimListElem) */ + ANIMCONT_CHANNEL = 8, /* animation channel (bAnimListElem) */ + ANIMCONT_MASK = 9 /* mask dopesheet */ } eAnimCont_Types; /* --------------- Channels -------------------- */ @@ -160,6 +161,9 @@ typedef enum eAnim_ChannelType { ANIMTYPE_GPDATABLOCK, ANIMTYPE_GPLAYER, + + ANIMTYPE_MASKDATABLOCK, + ANIMTYPE_MASKLAYER, ANIMTYPE_NLATRACK, ANIMTYPE_NLAACTION, @@ -173,6 +177,7 @@ typedef enum eAnim_KeyType { ALE_NONE = 0, /* no keyframe data */ ALE_FCURVE, /* F-Curve */ ALE_GPFRAME, /* Grease Pencil Frames */ + ALE_MASKLAY, /* Mask */ ALE_NLASTRIP, /* NLA Strips */ ALE_ALL, /* All channels summary */ @@ -279,6 +284,15 @@ typedef enum eAnimFilter_Flags { #define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0) #define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT) +/* Mask Only */ +/* Grease Pencil datablock settings */ +#define EXPANDED_MASK(mask) (mask->flag & MASK_ANIMF_EXPAND) +/* Grease Pencil Layer settings */ +#define EDITABLE_MASK(masklay) ((masklay->flag & MASK_LAYERFLAG_LOCKED) == 0) +#define SEL_MASKLAY(masklay) (masklay->flag & SELECT) + + + /* NLA only */ #define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED) #define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0) diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 2040d4b9c32..ad686588f17 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -83,7 +83,8 @@ void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion void gpencil_panel_standard(const struct bContext *C, struct Panel *pa); /* ----------- Grease-Pencil AnimEdit API ------------------ */ -short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, short (*gpf_cb)(struct bGPDframe *, struct Scene *)); +short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, + short (*gpf_cb)(struct bGPDframe *, struct Scene *)); void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel); short is_gplayer_frame_selected(struct bGPDlayer *gpl); diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index e24c21bc133..8a65699f404 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -123,6 +123,8 @@ void draw_summary_channel(struct View2D *v2d, struct bAnimContext *ac, float ypo /* Grease Pencil Layer */ // XXX not restored void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos); +/* Mask Layer */ +void draw_masklay_channel(struct View2D *v2d, struct bDopeSheet *ads, struct MaskLayer *masklay, float ypos); /* Keydata Generation --------------- */ /* F-Curve */ diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 0c2f6807632..bbfc47c582a 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -33,6 +33,7 @@ struct wmKeyConfig; struct MaskLayer; +struct MaskLayerShape; /* mask_editor.c */ void ED_operatortypes_mask(void); @@ -47,4 +48,25 @@ void ED_mask_layer_shape_auto_key(struct MaskLayer *masklay, const int frame); int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame); int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame); -#endif /* ED_TEXT_H */ +/* ----------- Mask AnimEdit API ------------------ */ +short masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene, + short (*masklay_shape_cb)(struct MaskLayerShape *, struct Scene *)); +void masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, short onlysel); + +short is_masklayer_frame_selected(struct MaskLayer *masklay); +void set_masklayer_frame_selection(struct MaskLayer *masklay, short mode); +void select_mask_frames(struct MaskLayer *masklay, short select_mode); +void select_mask_frame(struct MaskLayer *masklay, int selx, short select_mode); +void borderselect_masklayer_frames(struct MaskLayer *masklay, float min, float max, short select_mode); + +void delete_masklayer_frames(struct MaskLayer *masklay); +void duplicate_masklayer_frames(struct MaskLayer *masklay); + +//void free_gpcopybuf(void); +//void copy_gpdata(void); +//void paste_gpdata(void); + +void snap_masklayer_frames(struct MaskLayer *masklay, short mode); +void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); + +#endif /* __ED_MASK_H__ */ diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index f15e9c27732..57be5a2234a 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC mask_add.c mask_draw.c mask_edit.c + mask_editaction.c mask_ops.c mask_relationships.c mask_select.c diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c new file mode 100644 index 00000000000..c773e13e2eb --- /dev/null +++ b/source/blender/editors/mask/mask_editaction.c @@ -0,0 +1,253 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008, Blender Foundation + * This is a new part of Blender + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mask/mask_editaction.c + * \ingroup edgpencil + */ + +#include +#include +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_mask_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_fcurve.h" +#include "BKE_mask.h" + +#include "ED_anim_api.h" +#include "ED_keyframes_edit.h" + +/* ***************************************** */ +/* NOTE ABOUT THIS FILE: + * This file contains code for editing Grease Pencil data in the Action Editor + * as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings. + * Therefore, this file mostly contains functions for selecting Grease-Pencil frames. + */ +/* ***************************************** */ +/* Generics - Loopers */ + +/* Loops over the gp-frames for a gp-layer, and applies the given callback */ +short masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *)) +{ + MaskLayerShape *masklay_shape; + + /* error checker */ + if (masklay == NULL) + return 0; + + /* do loop */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + /* execute callback */ + if (masklay_shape_cb(masklay_shape, scene)) + return 1; + } + + /* nothing to return */ + return 0; +} + +/* ****************************************** */ +/* Data Conversion Tools */ + +/* make a listing all the gp-frames in a layer as cfraelems */ +void masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel) +{ + MaskLayerShape *masklay_shape; + CfraElem *ce; + + /* error checking */ + if (ELEM(NULL, masklay, elems)) + return; + + /* loop through gp-frames, adding */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) { + ce = MEM_callocN(sizeof(CfraElem), "CfraElem"); + + ce->cfra = (float)masklay_shape->frame; + ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0; + + BLI_addtail(elems, ce); + } + } +} + +/* ***************************************** */ +/* Selection Tools */ + +/* check if one of the frames in this layer is selected */ +short is_masklayer_frame_selected(MaskLayer *masklay) +{ + MaskLayerShape *masklay_shape; + + /* error checking */ + if (masklay == NULL) + return 0; + + /* stop at the first one found */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + if (masklay_shape->flag & MASK_SHAPE_SELECT) + return 1; + } + + /* not found */ + return 0; +} + +/* helper function - select gp-frame based on SELECT_* mode */ +static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode) +{ + if (masklay_shape == NULL) + return; + + switch (select_mode) { + case SELECT_ADD: + masklay_shape->flag |= MASK_SHAPE_SELECT; + break; + case SELECT_SUBTRACT: + masklay_shape->flag &= ~MASK_SHAPE_SELECT; + break; + case SELECT_INVERT: + masklay_shape->flag ^= MASK_SHAPE_SELECT; + break; + } +} + +/* set all/none/invert select (like above, but with SELECT_* modes) */ +void select_mask_frames(MaskLayer *masklay, short select_mode) +{ + MaskLayerShape *masklay_shape; + + /* error checking */ + if (masklay == NULL) + return; + + /* handle according to mode */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + masklayshape_select(masklay_shape, select_mode); + } +} + +/* set all/none/invert select */ +void set_masklayer_frame_selection(MaskLayer *masklay, short mode) +{ + /* error checking */ + if (masklay == NULL) + return; + + /* now call the standard function */ + select_mask_frames(masklay, mode); +} + +/* select the frame in this layer that occurs on this frame (there should only be one at most) */ +void select_mask_frame(MaskLayer *masklay, int selx, short select_mode) +{ + MaskLayerShape *masklay_shape; + + if (masklay == NULL) + return; + + /* search through frames for a match */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + /* there should only be one frame with this frame-number */ + if (masklay_shape->frame == selx) { + masklayshape_select(masklay_shape, select_mode); + break; + } + } +} + +/* select the frames in this layer that occur within the bounds specified */ +void borderselect_masklayer_frames(MaskLayer *masklay, float min, float max, short select_mode) +{ + MaskLayerShape *masklay_shape; + + if (masklay == NULL) + return; + + /* only select those frames which are in bounds */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { + if (IN_RANGE(masklay_shape->frame, min, max)) + masklayshape_select(masklay_shape, select_mode); + } +} + +/* ***************************************** */ +/* Frame Editing Tools */ + +/* Delete selected frames */ +void delete_masklayer_frames(MaskLayer *masklay) +{ + MaskLayerShape *masklay_shape, *masklay_shape_next; + + /* error checking */ + if (masklay == NULL) + return; + + /* check for frames to delete */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) { + masklay_shape_next = masklay_shape->next; + + if (masklay_shape->flag & MASK_SHAPE_SELECT) + BKE_mask_layer_shape_unlink(masklay, masklay_shape); + } +} + +/* Duplicate selected frames from given gp-layer */ +void duplicate_masklayer_frames(MaskLayer *masklay) +{ + MaskLayerShape *masklay_shape, *gpfn; + + /* error checking */ + if (masklay == NULL) + return; + + /* duplicate selected frames */ + for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) { + gpfn = masklay_shape->next; + + /* duplicate this frame */ + if (masklay_shape->flag & MASK_SHAPE_SELECT) { + MaskLayerShape *mask_shape_dupe; + + /* duplicate frame, and deselect self */ + mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape); + masklay_shape->flag &= ~MASK_SHAPE_SELECT; + + // XXX - how to handle duplicate frames? + BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe); + } + } +} diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 84ff038a050..edec57d9e93 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -285,6 +285,18 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) else glColor4ub(col2[0], col2[1], col2[2], 0x22); glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF); + /* frames one and higher get a saturated background */ + if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44); + else glColor4ub(col2[0], col2[1], col2[2], 0x44); + glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF); + } + else if (ac->datatype == ANIMCONT_MASK) { + /* TODO --- this is a copy of gpencil */ + /* frames less than one get less saturated background */ + if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22); + else glColor4ub(col2[0], col2[1], col2[2], 0x22); + glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF); + /* frames one and higher get a saturated background */ if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44); else glColor4ub(col2[0], col2[1], col2[2], 0x44); @@ -340,6 +352,9 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) case ALE_GPFRAME: draw_gpl_channel(v2d, ads, ale->data, y); break; + case ALE_MASKLAY: + draw_masklay_channel(v2d, ads, ale->data, y); + break; } } } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 0c32ebe549d..8b26461cc4f 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -44,6 +44,7 @@ #include "DNA_gpencil_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "RNA_access.h" #include "RNA_define.h" @@ -64,6 +65,7 @@ #include "ED_screen.h" #include "ED_transform.h" #include "ED_markers.h" +#include "ED_mask.h" #include "WM_api.h" #include "WM_types.h" @@ -256,6 +258,19 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const *max = MAX2(*max, gpf->framenum); } } + else if (ale->datatype == ALE_MASKLAY) { + MaskLayer *masklay = ale->data; + MaskLayerShape *masklay_shape; + + /* find mask layer which is less than or equal to cframe */ + for (masklay_shape = masklay->splines_shapes.first; + masklay_shape; + masklay_shape = masklay_shape->next) + { + *min = MIN2(*min, masklay_shape->frame); + *max = MAX2(*max, masklay_shape->frame); + } + } else { FCurve *fcu = (FCurve *)ale->key_data; float tmin, tmax; @@ -476,11 +491,16 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* copy keyframes */ - if (ac.datatype == ANIMCONT_GPENCIL) { + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { // FIXME... BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode"); return OPERATOR_CANCELLED; } + else if (ac.datatype == ANIMCONT_MASK) { + // FIXME... + BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode"); + return OPERATOR_CANCELLED; + } else { if (copy_action_keys(&ac)) { BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); @@ -521,9 +541,9 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op) ac.reports = op->reports; /* paste keyframes */ - if (ac.datatype == ANIMCONT_GPENCIL) { + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { // FIXME... - BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode"); + BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil or Mask mode"); return OPERATOR_CANCELLED; } else { @@ -625,7 +645,7 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_CANCELLED; /* what channels to affect? */ @@ -671,7 +691,7 @@ static void duplicate_action_keys(bAnimContext *ac) int filter; /* filter data */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); @@ -681,8 +701,12 @@ static void duplicate_action_keys(bAnimContext *ac) for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_FCURVE) duplicate_fcurve_keys((FCurve *)ale->key_data); - else + else if (ale->type == ANIMTYPE_GPLAYER) duplicate_gplayer_frames((bGPDlayer *)ale->data); + else if (ale->type == ANIMTYPE_MASKLAYER) + duplicate_masklayer_frames((MaskLayer *)ale->data); + else + BLI_assert(0); } /* free filtered list */ @@ -703,7 +727,7 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) duplicate_action_keys(&ac); /* validate keyframes after editing */ - if (ac.datatype != ANIMCONT_GPENCIL) + if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ @@ -744,7 +768,7 @@ static void delete_action_keys(bAnimContext *ac) int filter; /* filter data */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); @@ -752,7 +776,13 @@ static void delete_action_keys(bAnimContext *ac) /* loop through filtered data and delete selected keys */ for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->type != ANIMTYPE_GPLAYER) { + if (ale->type == ANIMTYPE_GPLAYER) { + delete_gplayer_frames((bGPDlayer *)ale->data); + } + else if (ale->type == ANIMTYPE_MASKLAYER) { + delete_masklayer_frames((MaskLayer *)ale->data); + } + else { FCurve *fcu = (FCurve *)ale->key_data; AnimData *adt = ale->adt; @@ -763,8 +793,6 @@ static void delete_action_keys(bAnimContext *ac) if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) ANIM_fcurve_delete_from_animdata(ac, adt, fcu); } - else - delete_gplayer_frames((bGPDlayer *)ale->data); } /* free filtered list */ @@ -785,7 +813,7 @@ static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op)) delete_action_keys(&ac); /* validate keyframes after editing */ - if (ac.datatype != ANIMCONT_GPENCIL) + if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ @@ -840,7 +868,7 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get cleaning threshold */ @@ -907,7 +935,7 @@ static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op)) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* sample keyframes */ @@ -1014,7 +1042,7 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get handle setting mode */ @@ -1085,7 +1113,7 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get handle setting mode */ @@ -1165,7 +1193,7 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get handle setting mode */ @@ -1236,7 +1264,7 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get handle setting mode */ @@ -1359,7 +1387,7 @@ static void snap_action_keys(bAnimContext *ac, short mode) KeyframeEditFunc edit_cb; /* filter data */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); @@ -1404,7 +1432,7 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; // XXX... - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get snapping mode */ @@ -1482,7 +1510,7 @@ static void mirror_action_keys(bAnimContext *ac, short mode) } /* filter data */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); @@ -1518,7 +1546,7 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; // XXX... - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get mirroring mode */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 0c6b0f5eb3d..bd73e35815b 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -43,6 +43,7 @@ #include "DNA_gpencil_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_mask_types.h" #include "RNA_access.h" #include "RNA_define.h" @@ -55,6 +56,7 @@ #include "ED_anim_api.h" #include "ED_gpencil.h" +#include "ED_mask.h" #include "ED_keyframes_draw.h" #include "ED_keyframes_edit.h" #include "ED_markers.h" @@ -92,7 +94,7 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) KeyframeEditFunc test_cb, sel_cb; /* determine type-based settings */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); @@ -112,6 +114,12 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) break; } } + else if (ale->type == ANIMTYPE_MASKLAYER) { + if (is_masklayer_frame_selected(ale->data)) { + sel = SELECT_SUBTRACT; + break; + } + } else { if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) { sel = SELECT_SUBTRACT; @@ -128,6 +136,8 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) set_gplayer_frame_selection(ale->data, sel); + else if (ale->type == ANIMTYPE_MASKLAYER) + set_masklayer_frame_selection(ale->data, sel); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); } @@ -250,6 +260,8 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s /* loop over data selecting */ if (ale->type == ANIMTYPE_GPLAYER) borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); + else if (ale->type == ANIMTYPE_MASKLAYER) + borderselect_masklayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); else ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); } @@ -400,6 +412,9 @@ static void markers_selectkeys_between(bAnimContext *ac) else if (ale->type == ANIMTYPE_GPLAYER) { borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD); } + else if (ale->type == ANIMTYPE_MASKLAYER) { + borderselect_masklayer_frames(ale->data, min, max, SELECT_ADD); + } else { ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -467,7 +482,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode) /* loop through all of the keys and select additional keyframes * based on the keys found to be selected above */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/); @@ -489,6 +504,8 @@ static void columnselect_action_keys(bAnimContext *ac, short mode) /* select elements with frame number matching cfraelem */ if (ale->type == ANIMTYPE_GPLAYER) select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD); + else if (ale->type == ANIMTYPE_MASKLAYER) + select_mask_frame(ale->data, ce->cfra, SELECT_ADD); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -755,7 +772,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se } /* filter data */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); @@ -772,6 +789,8 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se } else if (ale->type == ANIMTYPE_GPLAYER) borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode); + else if (ale->type == ANIMTYPE_MASKLAYER) + borderselect_masklayer_frames(ale->data, ked.f1, ked.f2, select_mode); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -909,6 +928,8 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s /* select the nominated keyframe on the given frame */ if (ale->type == ANIMTYPE_GPLAYER) select_gpencil_frame(ale->data, selx, select_mode); + else if (ale->type == ANIMTYPE_MASKLAYER) + select_mask_frame(ale->data, selx, select_mode); else ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); } @@ -933,7 +954,7 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se /* loop through all of the keys and select additional keyframes * based on the keys found to be selected above */ - if (ac->datatype == ANIMCONT_GPENCIL) + if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); @@ -951,7 +972,9 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se /* select elements with frame number matching cfra */ if (ale->type == ANIMTYPE_GPLAYER) select_gpencil_frame(ale->key_data, selx, select_mode); - else + else if (ale->type == ANIMTYPE_MASKLAYER) + select_mask_frame(ale->key_data, selx, select_mode); + else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -1051,7 +1074,12 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ bGPDlayer *gpl = (bGPDlayer *)ale->data; gpl_to_keylist(ads, gpl, &anim_keys); } - + else if (ale->type == ANIMTYPE_MASKLAYER) { + // TODO: why don't we just give masklayers key_data too? + MaskLayer *masklay = (MaskLayer *)ale->data; + mask_to_keylist(ads, masklay, &anim_keys); + } + /* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */ for (ak = anim_keys.root; ak; ak = akn) { if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) { @@ -1120,6 +1148,18 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ //gpencil_layer_setactive(gpd, gpl); } } + else if (ac->datatype == ANIMCONT_MASK) { + /* deselect all other channels first */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + + /* Highlight GPencil Layer */ + if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) { + MaskLayer *masklay = ale->data; + + masklay->flag |= MASK_LAYERFLAG_SELECT; + //gpencil_layer_setactive(gpd, gpl); + } + } } /* only select keyframes if we clicked on a valid channel and hit something */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 32a4d4ab1a3..fdc09c1bed0 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -555,7 +555,7 @@ struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf); /*********************** transform_conversions.c ********** */ struct ListBase; -void flushTransGPactionData(TransInfo *t); +void flushTransIntFrameActionData(TransInfo *t); void flushTransGraphData(TransInfo *t); void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data); void flushTransUVs(TransInfo *t); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 1d4257ea3d3..ce65127c896 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2797,6 +2797,99 @@ static void posttrans_gpd_clean (bGPdata *gpd) } } + +/* Called by special_aftertrans_update to make sure selected gp-frames replace + * any other gp-frames which may reside on that frame (that are not selected). + * It also makes sure sorted are still stored in chronological order after + * transform. + */ +static void posttrans_mask_clean(Mask *mask) +{ + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay= masklay->next) { + ListBase sel_buffer = {NULL, NULL}; + MaskLayerShape *masklay_shape, *masklay_shape_new; + MaskLayerShape *masklay_shape_sort, *masklay_shape_sort_new; + + /* loop 1: loop through and isolate selected gp-frames to buffer + * (these need to be sorted as they are isolated) + */ + for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape_new) { + short added= 0; + masklay_shape_new= masklay_shape->next; + + if (masklay_shape->flag & GP_FRAME_SELECT) { + BLI_remlink(&masklay->splines_shapes, masklay_shape); + + /* find place to add them in buffer + * - go backwards as most frames will still be in order, + * so doing it this way will be faster + */ + for (masklay_shape_sort= sel_buffer.last; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort->prev) { + /* if current (masklay_shape) occurs after this one in buffer, add! */ + if (masklay_shape_sort->frame < masklay_shape->frame) { + BLI_insertlinkafter(&sel_buffer, masklay_shape_sort, masklay_shape); + added= 1; + break; + } + } + if (added == 0) + BLI_addhead(&sel_buffer, masklay_shape); + } + } + + /* error checking: it is unlikely, but may be possible to have none selected */ + if (sel_buffer.first == NULL) + continue; + + /* if all were selected (i.e. masklay->splines_shapes is empty), then just transfer sel-buf over */ + if (masklay->splines_shapes.first == NULL) { + masklay->splines_shapes.first= sel_buffer.first; + masklay->splines_shapes.last= sel_buffer.last; + + continue; + } + + /* loop 2: remove duplicates of splines_shapes in buffers */ + for (masklay_shape= masklay->splines_shapes.first; masklay_shape && sel_buffer.first; masklay_shape= masklay_shape_new) { + masklay_shape_new= masklay_shape->next; + + /* loop through sel_buffer, emptying stuff from front of buffer if ok */ + for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort && masklay_shape; masklay_shape_sort= masklay_shape_sort_new) { + masklay_shape_sort_new= masklay_shape_sort->next; + + /* if this buffer frame needs to go before current, add it! */ + if (masklay_shape_sort->frame < masklay_shape->frame) { + /* transfer buffer frame to splines_shapes list (before current) */ + BLI_remlink(&sel_buffer, masklay_shape_sort); + BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort); + } + /* if this buffer frame is on same frame, replace current with it and stop */ + else if (masklay_shape_sort->frame == masklay_shape->frame) { + /* transfer buffer frame to splines_shapes list (before current) */ + BLI_remlink(&sel_buffer, masklay_shape_sort); + BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort); + + /* get rid of current frame */ + BKE_mask_layer_shape_unlink(masklay, masklay_shape); + } + } + } + + /* if anything is still in buffer, append to end */ + for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort_new) { + masklay_shape_sort_new= masklay_shape_sort->next; + + BLI_remlink(&sel_buffer, masklay_shape_sort); + BLI_addtail(&masklay->splines_shapes, masklay_shape_sort); + } + + /* NOTE: this is the only difference to grease pencil code above */ + BKE_mask_layer_shape_sort(masklay); + } +} + /* Called during special_aftertrans_update to make sure selected keyframes replace * any other keyframes which may reside on that frame (that is not selected). */ @@ -2936,6 +3029,27 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) return count; } +/* fully select selected beztriples, but only include if it's on the right side of cfra */ +static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra) +{ + MaskLayerShape *masklayer_shape; + int count = 0; + + if (masklay == NULL) + return count; + + /* only include points that occur on the right side of cfra */ + for (masklayer_shape= masklay->splines_shapes.first; masklayer_shape; masklayer_shape= masklayer_shape->next) { + if (masklayer_shape->flag & MASK_SHAPE_SELECT) { + if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) + count++; + } + } + + return count; +} + + /* This function assigns the information to transdata */ static void TimeToTransData(TransData *td, float *time, AnimData *adt) { @@ -2998,7 +3112,7 @@ typedef struct tGPFtransdata { } tGPFtransdata; /* This function helps flush transdata written to tempdata into the gp-frames */ -void flushTransGPactionData(TransInfo *t) +void flushTransIntFrameActionData(TransInfo *t) { tGPFtransdata *tfd; int i; @@ -3049,6 +3163,35 @@ static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl return count; } +/* refer to comment above #GPLayerToTransData, this is the same but for masks */ +static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra) +{ + MaskLayerShape *masklay_shape; + int count= 0; + + /* check for select frames on right side of current frame */ + for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape->next) { + if (masklay_shape->flag & MASK_SHAPE_SELECT) { + if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) { + /* memory is calloc'ed, so that should zero everything nicely for us */ + td->val= &tfd->val; + td->ival= (float)masklay_shape->frame; + + tfd->val= (float)masklay_shape->frame; + tfd->sdata= &masklay_shape->frame; + + /* advance td now */ + td++; + tfd++; + count++; + } + } + } + + return count; +} + + static void createTransActionData(bContext *C, TransInfo *t) { Scene *scene= t->scene; @@ -3069,7 +3212,7 @@ static void createTransActionData(bContext *C, TransInfo *t) return; /* filter data */ - if (ac.datatype == ANIMCONT_GPENCIL) + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT); else filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/); @@ -3102,8 +3245,12 @@ static void createTransActionData(bContext *C, TransInfo *t) if (ale->type == ANIMTYPE_FCURVE) count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); - else + else if (ale->type == ANIMTYPE_GPLAYER) count += count_gplayer_frames(ale->data, t->frame_side, cfra); + else if (ale->type == ANIMTYPE_MASKLAYER) + count += count_masklayer_frames(ale->data, t->frame_side, cfra); + else + BLI_assert(0); } /* stop if trying to build list if nothing selected */ @@ -3121,7 +3268,7 @@ static void createTransActionData(bContext *C, TransInfo *t) td= t->data; td2d = t->data2d; - if (ac.datatype == ANIMCONT_GPENCIL) { + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { if (t->mode == TFM_TIME_SLIDE) { t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata"); tfd= (tGPFtransdata *)((float *)(t->customData) + 2); @@ -3144,6 +3291,14 @@ static void createTransActionData(bContext *C, TransInfo *t) td += i; tfd += i; } + else if (ale->type == ANIMTYPE_MASKLAYER) { + MaskLayer *masklay = (MaskLayer *)ale->data; + int i; + + i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra); + td += i; + tfd += i; + } else { AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; @@ -5004,6 +5159,26 @@ void special_aftertrans_update(bContext *C, TransInfo *t) } } } + else if (ac.datatype == ANIMCONT_MASK) { + /* remove duplicate frames and also make sure points are in order! */ + /* 3 cases here for curve cleanups: + * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done + * 2) canceled == 0 -> user confirmed the transform, so duplicates should be removed + * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these + */ + if ((saction->flag & SACTION_NOTRANSKEYCULL)==0 && + ((canceled == 0) || (duplicate))) + { + Mask *mask; + + // XXX: BAD! this get gpencil datablocks directly from main db... + // but that's how this currently works :/ + for (mask = G.main->mask.first; mask; mask = mask->id.next) { + if (ID_REAL_USERS(mask)) + posttrans_mask_clean(mask); + } + } + } /* marker transform, not especially nice but we may want to move markers * at the same time as keyframes in the dope sheet. @@ -5027,7 +5202,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) } /* make sure all F-Curves are set correctly */ - if (ac.datatype != ANIMCONT_GPENCIL) + if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) ANIM_editkeyframes_refresh(&ac); /* clear flag that was set for time-slide drawing */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 3195fb0299d..e0920e323aa 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -350,9 +350,9 @@ static void recalcData_actedit(TransInfo *t) ANIM_animdata_context_getdata(&ac); /* perform flush */ - if (ac.datatype == ANIMCONT_GPENCIL) { + if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { /* flush transform values back to actual coordinates */ - flushTransGPactionData(t); + flushTransIntFrameActionData(t); } else { /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index b61916f7bfa..08d5743bb88 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -632,7 +632,9 @@ typedef enum eAnimEdit_Context { /* editing of gpencil data */ SACTCONT_GPENCIL = 2, /* dopesheet (default) */ - SACTCONT_DOPESHEET = 3 + SACTCONT_DOPESHEET = 3, + /* mask */ + SACTCONT_MASK = 4 } eAnimEdit_Context; /* SpaceAction AutoSnap Settings (also used by other Animation Editors) */ diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index e4c27a57d85..20701f9adc0 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -48,6 +48,9 @@ typedef struct Mask { int masklay_tot; /* total number of mask layers */ int sfra, efra; /* frames, used by the sequencer */ + + int flag; /* for anim info */ + int pad; } Mask; typedef struct MaskParent { @@ -96,7 +99,7 @@ typedef struct MaskLayerShape { float *data; /* u coordinate along spline segment and weight of this point */ int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */ int frame; /* different flags of this point */ - char flag; + char flag; /* animation flag */ char pad[7]; } MaskLayerShape; @@ -125,9 +128,8 @@ typedef struct MaskLayer { char blend; char blend_flag; - //char flag; /* not used yet */ + char flag; /* for animation */ char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */ - char pad[1]; } MaskLayer; /* MaskParent->flag */ @@ -169,4 +171,21 @@ enum { MASK_BLENDFLAG_INVERT = (1 << 0) }; +/* masklay->flag */ +enum { + MASK_LAYERFLAG_LOCKED = (1 << 4), + MASK_LAYERFLAG_SELECT = (1 << 5) +}; + +/* masklay_shape->flag */ +enum { + MASK_SHAPE_SELECT = (1 << 0) +}; + + +/* mask->flag */ +enum { + MASK_ANIMF_EXPAND = (1 << 4) +}; + #endif // __DNA_MASK_TYPES_H__ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index bbe9595029a..082c7c406e2 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2229,6 +2229,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) {SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"}, {SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"}, {SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"}, + {SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask Editor"}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3 From 5f2409e5ec94fd180206879f9d3dc030bca8f6b8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 14:46:17 +0000 Subject: add listener in action space for mask changes so dopesheet redraws + other minor changes. --- source/blender/editors/include/ED_gpencil.h | 2 +- source/blender/editors/space_action/space_action.c | 14 +++++++++++++- source/blender/makesrna/intern/rna_mask.c | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index ad686588f17..80f7fb9d1ed 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -94,7 +94,7 @@ void select_gpencil_frame(struct bGPDlayer *gpl, int selx, short select_mode); void borderselect_gplayer_frames(struct bGPDlayer *gpl, float min, float max, short select_mode); void delete_gplayer_frames(struct bGPDlayer *gpl); -void duplicate_gplayer_frames(struct bGPDlayer *gpd); +void duplicate_gplayer_frames(struct bGPDlayer *gpl); void free_gpcopybuf(void); void copy_gpdata(void); diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index ae4020aaaba..c8660179945 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -361,7 +361,7 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) case NC_SCREEN: if (wmn->data == ND_GPENCIL) { /* only handle this event in GPencil mode for performance considerations */ - if (saction->mode == SACTCONT_GPENCIL) + if (saction->mode == SACTCONT_GPENCIL) ED_area_tag_redraw(sa); } break; @@ -405,6 +405,18 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) break; } break; + case NC_MASK: + if (saction->mode == SACTCONT_MASK) { + switch (wmn->data) { + case ND_DATA: + ED_area_tag_refresh(sa); + break; + default: /* just redrawing the view will do */ + ED_area_tag_redraw(sa); + break; + } + } + break; case NC_NODE: if (wmn->action == NA_SELECTED) { /* selection changed, so force refresh to flush (needs flag set to do syncing) */ diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 42c893eca16..64f1663a524 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -582,6 +582,12 @@ static void rna_def_mask_layer(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1); RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); + /* select (for dopesheet)*/ + prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_LAYERFLAG_SELECT); + RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the DopeSheet"); +// RNA_def_property_update(prop, NC_SCREEN | ND_MASK, NULL); + /* render settings */ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "alpha"); -- cgit v1.2.3 From 909752a3da73e3630769fdd886cd69f02f0fe2fc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 15:14:45 +0000 Subject: Fix #31752: Select All By Layer seems not to work when object belongs to several layers Added option which changes match policy from exact match and shared layers when selecting objects by layer. --- source/blender/editors/object/object_select.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index fa86f089387..89f018a1b76 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -708,10 +708,11 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) static int object_select_by_layer_exec(bContext *C, wmOperator *op) { unsigned int layernum; - short extend; + short extend, match; extend = RNA_boolean_get(op->ptr, "extend"); layernum = RNA_int_get(op->ptr, "layers"); + match = RNA_enum_get(op->ptr, "match"); if (extend == 0) { CTX_DATA_BEGIN (C, Base *, base, visible_bases) @@ -723,7 +724,14 @@ static int object_select_by_layer_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (base->lay == (1 << (layernum - 1))) + int ok = 0; + + if (match == 1) /* exact */ + ok = (base->lay == (1 << (layernum - 1))); + else /* shared layers */ + ok = (base->lay & (1 << (layernum - 1))); + + if (ok) ED_base_object_select(base, BA_SELECT); } CTX_DATA_END; @@ -736,6 +744,12 @@ static int object_select_by_layer_exec(bContext *C, wmOperator *op) void OBJECT_OT_select_by_layer(wmOperatorType *ot) { + static EnumPropertyItem match_items[] = { + {1, "EXACT", 0, "Exact Match", ""}, + {2, "SHARED", 0, "Shared Layers", ""}, + {0, NULL, 0, NULL, NULL} + }; + /* identifiers */ ot->name = "Select by Layer"; ot->description = "Select all visible objects on a layer"; @@ -750,6 +764,7 @@ void OBJECT_OT_select_by_layer(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ + RNA_def_enum(ot->srna, "match", match_items, 0, "Match", ""); RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first"); RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20); } -- cgit v1.2.3 From 221a7878223e983372ba830e4ca1a17067abf2ba Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Fri, 8 Jun 2012 15:24:28 +0000 Subject: Don't show physics properties in game engine conext Also rename fluid panels to be more consistent with other simulations --- .../startup/bl_ui/properties_physics_cloth.py | 16 ------------- .../bl_ui/properties_physics_dynamicpaint.py | 27 +++++++++++++++------- .../startup/bl_ui/properties_physics_fluid.py | 15 +++++++----- .../startup/bl_ui/properties_physics_smoke.py | 14 +++++++---- .../startup/bl_ui/properties_physics_softbody.py | 24 ------------------- 5 files changed, 37 insertions(+), 59 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index 0240335c98f..33b977b5f04 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -117,10 +117,6 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel): bl_label = "Cloth Cache" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.cloth - def draw(self, context): md = context.cloth point_cache_ui(self, context, md.point_cache, cloth_panel_enabled(md), 'CLOTH') @@ -130,10 +126,6 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel): bl_label = "Cloth Collision" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.cloth - def draw_header(self, context): cloth = context.cloth.collision_settings @@ -173,10 +165,6 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel): bl_label = "Cloth Stiffness Scaling" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.cloth - def draw_header(self, context): cloth = context.cloth.settings @@ -209,10 +197,6 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel): bl_label = "Cloth Field Weights" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return (context.cloth) - def draw(self, context): cloth = context.cloth.settings effector_weights_ui(self, context, cloth.effector_weights) diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py index 04696c793a6..db0794d8a8a 100644 --- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py +++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py @@ -120,7 +120,8 @@ class PHYSICS_PT_dp_advanced_canvas(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint - return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active + rd = context.scene.render + return md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -194,10 +195,13 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint + rd = context.scene.render if not (md and md.ui_type == 'CANVAS' and md.canvas_settings): return 0 surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active - return surface and not (surface.surface_format == 'VERTEX' and (surface.surface_type in {'DISPLACE', 'WAVE'})) + return (surface and + (not (surface.surface_format == 'VERTEX' and (surface.surface_type in {'DISPLACE', 'WAVE'}))) and + (not rd.use_game_engine)) def draw(self, context): layout = self.layout @@ -284,10 +288,11 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint + rd = context.scene.render if not (md and md.ui_type == 'CANVAS' and md.canvas_settings): return 0 surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active - return (surface and surface.surface_type == 'PAINT') + return (surface and surface.surface_type == 'PAINT') and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -318,10 +323,11 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint + rd = context.scene.render if not (md and md.ui_type == 'CANVAS' and md.canvas_settings): return False surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active - return (surface and surface.surface_type == 'PAINT') + return (surface and surface.surface_type == 'PAINT') and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -366,11 +372,13 @@ class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint + rd = context.scene.render return (md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active and - md.canvas_settings.canvas_surfaces.active.is_cache_user) + md.canvas_settings.canvas_surfaces.active.is_cache_user and + (not rd.use_game_engine)) def draw(self, context): surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active @@ -385,7 +393,8 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint - return md and md.ui_type == 'BRUSH' and md.brush_settings + rd = context.scene.render + return md and md.ui_type == 'BRUSH' and md.brush_settings and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -437,7 +446,8 @@ class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint - return md and md.ui_type == 'BRUSH' and md.brush_settings + rd = context.scene.render + return md and md.ui_type == 'BRUSH' and md.brush_settings and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -472,7 +482,8 @@ class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.dynamic_paint - return md and md.ui_type == 'BRUSH' and md.brush_settings + rd = context.scene.render + return md and md.ui_type == 'BRUSH' and md.brush_settings and (not rd.use_game_engine) def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index beb525bbd07..751f3e18acc 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -192,13 +192,14 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel): class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel): - bl_label = "Domain World" + bl_label = "Fluid World" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): md = context.fluid - return md and md.settings and (md.settings.type == 'DOMAIN') + rd = context.scene.render + return md and md.settings and (md.settings.type == 'DOMAIN') and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -244,13 +245,14 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel): class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel): - bl_label = "Domain Boundary" + bl_label = "Fluid Boundary" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): md = context.fluid - return md and md.settings and (md.settings.type == 'DOMAIN') + rd = context.scene.render + return md and md.settings and (md.settings.type == 'DOMAIN') and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -273,13 +275,14 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel): class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel): - bl_label = "Domain Particles" + bl_label = "Fluid Particles" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): md = context.fluid - return md and md.settings and (md.settings.type == 'DOMAIN') + rd = context.scene.render + return md and md.settings and (md.settings.type == 'DOMAIN') and (not rd.use_game_engine) def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py index 012aefebb6e..1b333f1e505 100644 --- a/release/scripts/startup/bl_ui/properties_physics_smoke.py +++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py @@ -117,7 +117,8 @@ class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.smoke - return md and (md.smoke_type == 'DOMAIN') + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -145,7 +146,8 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.smoke - return md and (md.smoke_type == 'DOMAIN') + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) def draw_header(self, context): md = context.smoke.domain_settings @@ -182,7 +184,8 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): md = context.smoke - return md and (md.smoke_type == 'DOMAIN') + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) def draw(self, context): layout = self.layout @@ -202,8 +205,9 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): - smoke = context.smoke - return (smoke and smoke.smoke_type == 'DOMAIN') + md = context.smoke + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) def draw(self, context): domain = context.smoke.domain_settings diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py index ea4180c891f..b043c1f9b68 100644 --- a/release/scripts/startup/bl_ui/properties_physics_softbody.py +++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py @@ -72,10 +72,6 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel): bl_label = "Soft Body Cache" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.soft_body - def draw(self, context): md = context.soft_body point_cache_ui(self, context, md.point_cache, softbody_panel_enabled(md), 'SOFTBODY') @@ -85,10 +81,6 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel): bl_label = "Soft Body Goal" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.soft_body - def draw_header(self, context): softbody = context.soft_body.settings @@ -128,10 +120,6 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel): bl_label = "Soft Body Edges" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.soft_body - def draw_header(self, context): softbody = context.soft_body.settings @@ -181,10 +169,6 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel): bl_label = "Soft Body Self Collision" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.soft_body - def draw_header(self, context): softbody = context.soft_body.settings @@ -213,10 +197,6 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel): bl_label = "Soft Body Solver" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return context.soft_body - def draw(self, context): layout = self.layout @@ -249,10 +229,6 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel): bl_label = "Soft Body Field Weights" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return (context.soft_body) - def draw(self, context): md = context.soft_body softbody = md.settings -- cgit v1.2.3 From 82d3d9f2ba47bbf2f868b5a970d1fe149eba13e2 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Fri, 8 Jun 2012 16:13:01 +0000 Subject: Update Bullet to version 2.80 (bullet svn revision 2537) Remove Jamfiles and other unused files that stuck around during previous updates. Add patches for local changes to the patches directory. Update readme.txt, it had outdated infromation. --- extern/bullet2/CMakeLists.txt | 87 +- extern/bullet2/patches/ghost_softbody.patch | 42 + extern/bullet2/patches/pvs_warning_fixes.patch | 31 + extern/bullet2/readme.txt | 18 +- .../BroadphaseCollision/btAxisSweep3.h | 8 +- .../BroadphaseCollision/btBroadphaseInterface.h | 6 +- .../BroadphaseCollision/btBroadphaseProxy.h | 8 +- .../BroadphaseCollision/btCollisionAlgorithm.h | 6 +- .../BulletCollision/BroadphaseCollision/btDbvt.h | 3 +- .../BroadphaseCollision/btDispatcher.h | 16 +- .../BroadphaseCollision/btMultiSapBroadphase.cpp | 2 +- .../BroadphaseCollision/btOverlappingPairCache.h | 6 +- .../BroadphaseCollision/btQuantizedBvh.h | 12 +- .../BroadphaseCollision/btSimpleBroadphase.h | 6 +- .../CollisionDispatch/SphereTriangleDetector.h | 6 +- .../btBox2dBox2dCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btBoxBoxCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btBoxBoxDetector.h | 4 +- .../CollisionDispatch/btCollisionConfiguration.h | 1 + .../CollisionDispatch/btCollisionCreateFunc.h | 6 +- .../CollisionDispatch/btCollisionDispatcher.cpp | 15 +- .../CollisionDispatch/btCollisionDispatcher.h | 21 +- .../CollisionDispatch/btCollisionObject.h | 6 +- .../CollisionDispatch/btCollisionWorld.cpp | 387 +-- .../CollisionDispatch/btCollisionWorld.h | 6 +- .../btCompoundCollisionAlgorithm.h | 6 +- .../btConvex2dConvex2dAlgorithm.h | 6 +- .../btConvexConcaveCollisionAlgorithm.cpp | 15 +- .../btConvexConcaveCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btConvexConvexAlgorithm.cpp | 277 +- .../CollisionDispatch/btConvexConvexAlgorithm.h | 6 +- .../btConvexPlaneCollisionAlgorithm.cpp | 32 +- .../btConvexPlaneCollisionAlgorithm.h | 8 +- .../btDefaultCollisionConfiguration.cpp | 11 + .../btDefaultCollisionConfiguration.h | 2 + .../CollisionDispatch/btEmptyCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btInternalEdgeUtility.cpp | 90 +- .../CollisionDispatch/btManifoldResult.cpp | 4 +- .../CollisionDispatch/btManifoldResult.h | 6 +- .../btSimulationIslandManager.cpp | 19 +- .../CollisionDispatch/btSimulationIslandManager.h | 8 +- .../btSphereBoxCollisionAlgorithm.h | 6 +- .../btSphereSphereCollisionAlgorithm.h | 6 +- .../btSphereTriangleCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btUnionFind.cpp | 2 +- .../CollisionDispatch/btUnionFind.h | 6 +- .../BulletCollision/CollisionShapes/btBox2dShape.h | 12 +- .../BulletCollision/CollisionShapes/btBoxShape.cpp | 12 +- .../BulletCollision/CollisionShapes/btBoxShape.h | 16 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 6 +- .../CollisionShapes/btCapsuleShape.cpp | 8 +- .../CollisionShapes/btCollisionMargin.h | 11 +- .../CollisionShapes/btCollisionShape.h | 6 +- .../CollisionShapes/btCompoundShape.h | 6 +- .../CollisionShapes/btConcaveShape.h | 6 +- .../BulletCollision/CollisionShapes/btConeShape.h | 6 +- .../CollisionShapes/btConvexHullShape.cpp | 44 + .../CollisionShapes/btConvexHullShape.h | 8 +- .../CollisionShapes/btConvexInternalShape.h | 22 + .../CollisionShapes/btConvexPolyhedron.cpp | 296 +++ .../CollisionShapes/btConvexPolyhedron.h | 62 + .../CollisionShapes/btConvexShape.cpp | 21 +- .../CollisionShapes/btConvexShape.h | 8 +- .../CollisionShapes/btConvexTriangleMeshShape.h | 6 +- .../CollisionShapes/btCylinderShape.cpp | 2 + .../CollisionShapes/btCylinderShape.h | 6 +- .../BulletCollision/CollisionShapes/btEmptyShape.h | 6 +- .../CollisionShapes/btHeightfieldTerrainShape.cpp | 6 +- .../CollisionShapes/btHeightfieldTerrainShape.h | 20 +- .../BulletCollision/CollisionShapes/btMaterial.h | 6 +- .../CollisionShapes/btMinkowskiSumShape.h | 6 +- .../CollisionShapes/btMultiSphereShape.h | 6 +- .../btMultimaterialTriangleMeshShape.h | 6 +- .../CollisionShapes/btOptimizedBvh.cpp | 4 +- .../CollisionShapes/btOptimizedBvh.h | 6 +- .../CollisionShapes/btPolyhedralConvexShape.cpp | 288 +- .../CollisionShapes/btPolyhedralConvexShape.h | 20 +- .../CollisionShapes/btScaledBvhTriangleMeshShape.h | 6 +- .../BulletCollision/CollisionShapes/btShapeHull.h | 6 +- .../CollisionShapes/btSphereShape.h | 6 +- .../CollisionShapes/btStaticPlaneShape.h | 6 +- .../CollisionShapes/btStridingMeshInterface.cpp | 2 + .../CollisionShapes/btStridingMeshInterface.h | 6 +- .../CollisionShapes/btTetrahedronShape.h | 6 +- .../CollisionShapes/btTriangleCallback.h | 6 +- .../CollisionShapes/btTriangleIndexVertexArray.h | 2 + .../CollisionShapes/btTriangleInfoMap.h | 3 + .../CollisionShapes/btTriangleMesh.h | 6 +- .../CollisionShapes/btTriangleMeshShape.h | 6 +- .../CollisionShapes/btTriangleShape.h | 6 +- .../Gimpact/btContactProcessing.cpp | 2 +- .../Gimpact/btGImpactCollisionAlgorithm.h | 6 +- .../src/BulletCollision/Gimpact/btQuantization.h | 6 +- .../BulletCollision/Gimpact/btTriangleShapeEx.h | 6 +- .../btContinuousConvexCollision.cpp | 135 +- .../btContinuousConvexCollision.h | 15 +- .../NarrowPhaseCollision/btConvexCast.h | 8 +- .../btConvexPenetrationDepthSolver.h | 6 +- .../btDiscreteCollisionDetectorInterface.h | 8 +- .../NarrowPhaseCollision/btGjkConvexCast.h | 6 +- .../NarrowPhaseCollision/btGjkEpa2.cpp | 86 +- .../NarrowPhaseCollision/btGjkEpa2.h | 8 +- .../NarrowPhaseCollision/btGjkPairDetector.h | 6 +- .../NarrowPhaseCollision/btManifoldPoint.h | 8 +- .../btMinkowskiPenetrationDepthSolver.h | 6 +- .../NarrowPhaseCollision/btPersistentManifold.cpp | 52 +- .../NarrowPhaseCollision/btPersistentManifold.h | 14 +- .../NarrowPhaseCollision/btPointCollector.h | 6 +- .../btPolyhedralContactClipping.cpp | 440 ++++ .../btPolyhedralContactClipping.h | 46 + .../NarrowPhaseCollision/btRaycastCallback.h | 6 +- .../btSimplexSolverInterface.h | 6 +- .../NarrowPhaseCollision/btSubSimplexConvexCast.h | 6 +- .../NarrowPhaseCollision/btVoronoiSimplexSolver.h | 7 +- .../Character/btCharacterControllerInterface.h | 7 +- .../Character/btKinematicCharacterController.h | 7 +- .../ConstraintSolver/btConeTwistConstraint.cpp | 7 +- .../ConstraintSolver/btConeTwistConstraint.h | 6 +- .../ConstraintSolver/btConstraintSolver.h | 6 +- .../ConstraintSolver/btContactConstraint.cpp | 50 +- .../ConstraintSolver/btContactConstraint.h | 9 +- .../ConstraintSolver/btContactSolverInfo.h | 6 +- .../ConstraintSolver/btGeneric6DofConstraint.cpp | 10 +- .../ConstraintSolver/btGeneric6DofConstraint.h | 6 +- .../btGeneric6DofSpringConstraint.cpp | 13 + .../btGeneric6DofSpringConstraint.h | 8 +- .../ConstraintSolver/btHinge2Constraint.h | 6 +- .../ConstraintSolver/btHingeConstraint.cpp | 29 +- .../ConstraintSolver/btHingeConstraint.h | 7 +- .../ConstraintSolver/btJacobianEntry.h | 6 +- .../ConstraintSolver/btPoint2PointConstraint.h | 6 +- .../btSequentialImpulseConstraintSolver.cpp | 196 +- .../btSequentialImpulseConstraintSolver.h | 8 +- .../ConstraintSolver/btSliderConstraint.h | 11 +- .../ConstraintSolver/btSolve2LinearConstraint.h | 6 +- .../ConstraintSolver/btSolverConstraint.h | 2 + .../ConstraintSolver/btTypedConstraint.cpp | 10 + .../ConstraintSolver/btTypedConstraint.h | 54 +- .../ConstraintSolver/btUniversalConstraint.cpp | 6 +- .../ConstraintSolver/btUniversalConstraint.h | 8 +- .../Dynamics/btContinuousDynamicsWorld.cpp | 196 -- .../Dynamics/btContinuousDynamicsWorld.h | 46 - .../Dynamics/btDiscreteDynamicsWorld.cpp | 441 ++-- .../Dynamics/btDiscreteDynamicsWorld.h | 5 + .../src/BulletDynamics/Dynamics/btDynamicsWorld.h | 3 +- .../src/BulletDynamics/Dynamics/btRigidBody.cpp | 7 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 6 +- .../Dynamics/btSimpleDynamicsWorld.h | 2 +- .../src/BulletDynamics/Vehicle/btRaycastVehicle.h | 6 +- .../BulletDynamics/Vehicle/btVehicleRaycaster.h | 8 +- .../src/BulletDynamics/Vehicle/btWheelInfo.h | 6 +- .../src/BulletSoftBody/btDefaultSoftBodySolver.cpp | 2 +- .../src/BulletSoftBody/btDefaultSoftBodySolver.h | 2 +- extern/bullet2/src/BulletSoftBody/btSoftBody.cpp | 292 ++- extern/bullet2/src/BulletSoftBody/btSoftBody.h | 24 +- .../btSoftBodyConcaveCollisionAlgorithm.cpp | 2 +- .../btSoftBodyConcaveCollisionAlgorithm.h | 6 +- .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 35 +- .../bullet2/src/BulletSoftBody/btSoftBodyHelpers.h | 6 +- .../src/BulletSoftBody/btSoftBodyInternals.h | 2 +- .../bullet2/src/BulletSoftBody/btSoftBodySolvers.h | 2 +- .../BulletSoftBody/btSoftRigidCollisionAlgorithm.h | 6 +- .../BulletSoftBody/btSoftRigidDynamicsWorld.cpp | 17 +- .../src/BulletSoftBody/btSoftRigidDynamicsWorld.h | 4 + .../BulletSoftBody/btSoftSoftCollisionAlgorithm.h | 6 +- extern/bullet2/src/BulletSoftBody/btSparseSDF.h | 6 +- extern/bullet2/src/LinearMath/btAabbUtil2.h | 6 +- .../bullet2/src/LinearMath/btAlignedAllocator.cpp | 15 +- .../bullet2/src/LinearMath/btAlignedObjectArray.h | 33 +- extern/bullet2/src/LinearMath/btConvexHull.h | 6 +- .../src/LinearMath/btConvexHullComputer.cpp | 2751 ++++++++++++++++++++ .../bullet2/src/LinearMath/btConvexHullComputer.h | 103 + .../bullet2/src/LinearMath/btDefaultMotionState.h | 6 +- .../src/LinearMath/btGrahamScan2dConvexHull.h | 110 + extern/bullet2/src/LinearMath/btHashMap.h | 16 + extern/bullet2/src/LinearMath/btIDebugDraw.h | 7 +- extern/bullet2/src/LinearMath/btList.h | 6 +- extern/bullet2/src/LinearMath/btMinMax.h | 8 +- extern/bullet2/src/LinearMath/btPoint3.h | 24 - extern/bullet2/src/LinearMath/btPoolAllocator.h | 5 + extern/bullet2/src/LinearMath/btQuadWord.h | 6 +- extern/bullet2/src/LinearMath/btQuaternion.h | 53 +- extern/bullet2/src/LinearMath/btQuickprof.cpp | 3 +- extern/bullet2/src/LinearMath/btQuickprof.h | 15 +- extern/bullet2/src/LinearMath/btRandom.h | 6 +- extern/bullet2/src/LinearMath/btScalar.h | 37 +- extern/bullet2/src/LinearMath/btSerializer.cpp | 1145 ++++---- extern/bullet2/src/LinearMath/btSerializer.h | 30 +- extern/bullet2/src/LinearMath/btSimdMinMax.h | 41 - extern/bullet2/src/LinearMath/btTransform.h | 6 +- extern/bullet2/src/LinearMath/btTransformUtil.h | 6 +- extern/bullet2/src/LinearMath/btVector3.h | 6 +- extern/bullet2/src/SConscript | 31 +- extern/bullet2/src/btBulletDynamicsCommon.h | 1 - 194 files changed, 7109 insertions(+), 2144 deletions(-) create mode 100644 extern/bullet2/patches/ghost_softbody.patch create mode 100644 extern/bullet2/patches/pvs_warning_fixes.patch create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h create mode 100644 extern/bullet2/src/LinearMath/btConvexHullComputer.cpp create mode 100644 extern/bullet2/src/LinearMath/btConvexHullComputer.h create mode 100644 extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h delete mode 100644 extern/bullet2/src/LinearMath/btPoint3.h delete mode 100644 extern/bullet2/src/LinearMath/btSimdMinMax.h diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt index ae7d282ca55..4bf26ab3794 100644 --- a/extern/bullet2/CMakeLists.txt +++ b/extern/bullet2/CMakeLists.txt @@ -43,9 +43,9 @@ set(SRC src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp - src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -54,16 +54,21 @@ set(SRC src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btGhostObject.cpp + src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp + src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h src/BulletCollision/CollisionDispatch/btManifoldResult.cpp src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp src/BulletCollision/CollisionDispatch/btUnionFind.cpp + src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp src/BulletCollision/CollisionShapes/btBoxShape.cpp + src/BulletCollision/CollisionShapes/btBox2dShape.cpp src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp src/BulletCollision/CollisionShapes/btCapsuleShape.cpp src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -73,14 +78,16 @@ set(SRC src/BulletCollision/CollisionShapes/btConvexHullShape.cpp src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp + src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp src/BulletCollision/CollisionShapes/btConvexShape.cpp + src/BulletCollision/CollisionShapes/btConvex2dShape.cpp src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp src/BulletCollision/CollisionShapes/btCylinderShape.cpp src/BulletCollision/CollisionShapes/btEmptyShape.cpp src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp - src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp + src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -97,11 +104,11 @@ set(SRC src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp src/BulletCollision/Gimpact/btContactProcessing.cpp + src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp src/BulletCollision/Gimpact/btGImpactBvh.cpp src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp src/BulletCollision/Gimpact/btGImpactShape.cpp - src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp src/BulletCollision/Gimpact/btTriangleShapeEx.cpp src/BulletCollision/Gimpact/gim_box_set.cpp src/BulletCollision/Gimpact/gim_contact.cpp @@ -118,25 +125,28 @@ set(SRC src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp - src/BulletDynamics/Character/btKinematicCharacterController.cpp + src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp + src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp + src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp - src/BulletDynamics/Dynamics/Bullet-C-API.cpp - src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp + src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp src/BulletDynamics/Dynamics/btRigidBody.cpp src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp + src/BulletDynamics/Dynamics/Bullet-C-API.cpp src/BulletDynamics/Vehicle/btRaycastVehicle.cpp src/BulletDynamics/Vehicle/btWheelInfo.cpp - src/BulletSoftBody/btDefaultSoftBodySolver.cpp + src/BulletDynamics/Character/btKinematicCharacterController.cpp + src/BulletSoftBody/btSoftBody.cpp src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -144,21 +154,16 @@ set(SRC src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp + src/BulletSoftBody/btDefaultSoftBodySolver.cpp + src/LinearMath/btAlignedAllocator.cpp src/LinearMath/btConvexHull.cpp + src/LinearMath/btConvexHullComputer.cpp src/LinearMath/btGeometryUtil.cpp src/LinearMath/btQuickprof.cpp src/LinearMath/btSerializer.cpp - # UNUSED - # src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp - # src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp - # src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp - # src/BulletCollision/CollisionShapes/btBox2dShape.cpp - # src/BulletCollision/CollisionShapes/btConvex2dShape.cpp - # src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp - # src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp - - src/Bullet-C-Api.h + + src/BulletCollision/BroadphaseCollision/btAxisSweep3.h src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -171,9 +176,9 @@ set(SRC src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h - src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h + src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -183,6 +188,7 @@ set(SRC src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h + src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -193,7 +199,9 @@ set(SRC src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h src/BulletCollision/CollisionDispatch/btUnionFind.h + src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h src/BulletCollision/CollisionShapes/btBoxShape.h + src/BulletCollision/CollisionShapes/btBox2dShape.h src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h src/BulletCollision/CollisionShapes/btCapsuleShape.h src/BulletCollision/CollisionShapes/btCollisionMargin.h @@ -204,15 +212,17 @@ set(SRC src/BulletCollision/CollisionShapes/btConvexHullShape.h src/BulletCollision/CollisionShapes/btConvexInternalShape.h src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h + src/BulletCollision/CollisionShapes/btConvexPolyhedron.h src/BulletCollision/CollisionShapes/btConvexShape.h + src/BulletCollision/CollisionShapes/btConvex2dShape.h src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h src/BulletCollision/CollisionShapes/btCylinderShape.h src/BulletCollision/CollisionShapes/btEmptyShape.h src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h src/BulletCollision/CollisionShapes/btMaterial.h src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h - src/BulletCollision/CollisionShapes/btMultiSphereShape.h src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h + src/BulletCollision/CollisionShapes/btMultiSphereShape.h src/BulletCollision/CollisionShapes/btOptimizedBvh.h src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -233,13 +243,13 @@ set(SRC src/BulletCollision/Gimpact/btBoxCollision.h src/BulletCollision/Gimpact/btClipPolygon.h src/BulletCollision/Gimpact/btContactProcessing.h + src/BulletCollision/Gimpact/btGenericPoolAllocator.h + src/BulletCollision/Gimpact/btGeometryOperations.h src/BulletCollision/Gimpact/btGImpactBvh.h src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h src/BulletCollision/Gimpact/btGImpactMassUtil.h src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h src/BulletCollision/Gimpact/btGImpactShape.h - src/BulletCollision/Gimpact/btGenericPoolAllocator.h - src/BulletCollision/Gimpact/btGeometryOperations.h src/BulletCollision/Gimpact/btQuantization.h src/BulletCollision/Gimpact/btTriangleShapeEx.h src/BulletCollision/Gimpact/gim_array.h @@ -273,14 +283,15 @@ set(SRC src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h - src/BulletDynamics/Character/btCharacterControllerInterface.h - src/BulletDynamics/Character/btKinematicCharacterController.h + src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h + src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h src/BulletDynamics/ConstraintSolver/btConstraintSolver.h src/BulletDynamics/ConstraintSolver/btContactConstraint.h src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h + src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h src/BulletDynamics/ConstraintSolver/btHingeConstraint.h src/BulletDynamics/ConstraintSolver/btJacobianEntry.h src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -290,41 +301,45 @@ set(SRC src/BulletDynamics/ConstraintSolver/btSolverBody.h src/BulletDynamics/ConstraintSolver/btSolverConstraint.h src/BulletDynamics/ConstraintSolver/btTypedConstraint.h + src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h src/BulletDynamics/Dynamics/btActionInterface.h - src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h src/BulletDynamics/Dynamics/btDynamicsWorld.h - src/BulletDynamics/Dynamics/btRigidBody.h src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h + src/BulletDynamics/Dynamics/btRigidBody.h src/BulletDynamics/Vehicle/btRaycastVehicle.h src/BulletDynamics/Vehicle/btVehicleRaycaster.h src/BulletDynamics/Vehicle/btWheelInfo.h - src/BulletSoftBody/btDefaultSoftBodySolver.h + src/BulletDynamics/Character/btCharacterControllerInterface.h + src/BulletDynamics/Character/btKinematicCharacterController.h + src/BulletSoftBody/btSoftBody.h - src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h src/BulletSoftBody/btSoftBodyData.h + src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h src/BulletSoftBody/btSoftBodyHelpers.h - src/BulletSoftBody/btSoftBodyInternals.h src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h - src/BulletSoftBody/btSoftBodySolverVertexBuffer.h - src/BulletSoftBody/btSoftBodySolvers.h src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h src/BulletSoftBody/btSoftRigidDynamicsWorld.h src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h src/BulletSoftBody/btSparseSDF.h + src/BulletSoftBody/btSoftBodySolvers.h + src/BulletSoftBody/btDefaultSoftBodySolver.h + src/BulletSoftBody/btSoftBodySolverVertexBuffer.h + src/LinearMath/btAabbUtil2.h src/LinearMath/btAlignedAllocator.h src/LinearMath/btAlignedObjectArray.h src/LinearMath/btConvexHull.h + src/LinearMath/btConvexHullComputer.h src/LinearMath/btDefaultMotionState.h src/LinearMath/btGeometryUtil.h + src/LinearMath/btGrahamScan2dConvexHull.h src/LinearMath/btHashMap.h src/LinearMath/btIDebugDraw.h src/LinearMath/btList.h src/LinearMath/btMatrix3x3.h src/LinearMath/btMinMax.h src/LinearMath/btMotionState.h - src/LinearMath/btPoint3.h src/LinearMath/btPoolAllocator.h src/LinearMath/btQuadWord.h src/LinearMath/btQuaternion.h @@ -332,20 +347,14 @@ set(SRC src/LinearMath/btRandom.h src/LinearMath/btScalar.h src/LinearMath/btSerializer.h - src/LinearMath/btSimdMinMax.h src/LinearMath/btStackAlloc.h src/LinearMath/btTransform.h src/LinearMath/btTransformUtil.h src/LinearMath/btVector3.h + + src/btBulletCollisionCommon.h src/btBulletDynamicsCommon.h - # src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h - # src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h - # src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h - # src/BulletCollision/CollisionShapes/btBox2dShape.h - # src/BulletCollision/CollisionShapes/btConvex2dShape.h - # src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h - # src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h ) if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/extern/bullet2/patches/ghost_softbody.patch b/extern/bullet2/patches/ghost_softbody.patch new file mode 100644 index 00000000000..b150d57040d --- /dev/null +++ b/extern/bullet2/patches/ghost_softbody.patch @@ -0,0 +1,42 @@ +Index: extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +=================================================================== +--- extern/bullet2/src/BulletSoftBody/btSoftBody.cpp (Revision 43904) ++++ extern/bullet2/src/BulletSoftBody/btSoftBody.cpp (Revision 43905) +@@ -2780,21 +2780,23 @@ + { + const RContact& c = psb->m_rcontacts[i]; + const sCti& cti = c.m_cti; +- btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj); + +- const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); +- const btVector3 vb = c.m_node->m_x-c.m_node->m_q; +- const btVector3 vr = vb-va; +- const btScalar dn = btDot(vr, cti.m_normal); +- if(dn<=SIMD_EPSILON) +- { +- const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg ); +- const btVector3 fv = vr - (cti.m_normal * dn); +- // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient +- const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst ); +- c.m_node->m_x -= impulse * c.m_c2; +- if (tmpRigid) +- tmpRigid->applyImpulse(impulse,c.m_c1); ++ if (cti.m_colObj->hasContactResponse()) { ++ btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj); ++ const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0); ++ const btVector3 vb = c.m_node->m_x-c.m_node->m_q; ++ const btVector3 vr = vb-va; ++ const btScalar dn = btDot(vr, cti.m_normal); ++ if(dn<=SIMD_EPSILON) ++ { ++ const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg ); ++ const btVector3 fv = vr - (cti.m_normal * dn); ++ // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient ++ const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst ); ++ c.m_node->m_x -= impulse * c.m_c2; ++ if (tmpRigid) ++ tmpRigid->applyImpulse(impulse,c.m_c1); ++ } + } + } + } diff --git a/extern/bullet2/patches/pvs_warning_fixes.patch b/extern/bullet2/patches/pvs_warning_fixes.patch new file mode 100644 index 00000000000..5a3fe140454 --- /dev/null +++ b/extern/bullet2/patches/pvs_warning_fixes.patch @@ -0,0 +1,31 @@ +Index: extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h +=================================================================== +--- extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h (Revision 45907) ++++ extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h (Revision 45908) +@@ -45,7 +45,9 @@ + int getTriangleIndex() const + { + // Get only the lower bits where the triangle index is stored +- return (m_PartIdTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); ++ unsigned int x = 0; ++ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS); ++ return (m_PartIdTriangleIndex&~(y)); + } + int getPartId() const + { +Index: extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h +=================================================================== +--- extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h (Revision 45907) ++++ extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h (Revision 45908) +@@ -78,8 +78,10 @@ + int getTriangleIndex() const + { + btAssert(isLeafNode()); ++ unsigned int x=0; ++ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS); + // Get only the lower bits where the triangle index is stored +- return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); ++ return (m_escapeIndexOrTriangleIndex&~(y)); + } + int getPartId() const + { diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt index e2546b049e3..e537ac26189 100644 --- a/extern/bullet2/readme.txt +++ b/extern/bullet2/readme.txt @@ -1,21 +1,15 @@ -*** -Apply bullet_compound_raycast.patch if not already applied in Bullet source -This patch is needed to return correct raycast results on compound shape. -/ben - - -*** These files in extern/bullet2 are NOT part of the Blender build yet *** - This is the new refactored version of Bullet physics library version 2.x -Soon this will replace the old Bullet version in extern/bullet. -First the integration in Blender Game Engine needs to be updated. -Once that is done all build systems can be updated to use/build extern/bullet2 files. - Questions? mail blender at erwincoumans.com, or check the bf-blender mailing list. Thanks, Erwin +Apply patches/ghost_softbody.patch to prevent softbodies being hit by ghost objects. +Originally committed in blender svn revision: 43905. + +Apply patches/pvs_warning_fixes.patch to fix warnings reported by PVS-Studio. +Originally committed in blender svn revision: 45908. + Apply patches/make_id.patch to prevent duplicated define of MAKE_ID macro in blender side and bullet side. Sergey diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index 70cf3e4ace8..4f4d94b3cc7 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -16,8 +16,8 @@ // // 3. This notice may not be removed or altered from any source distribution. -#ifndef AXIS_SWEEP_3_H -#define AXIS_SWEEP_3_H +#ifndef BT_AXIS_SWEEP_3_H +#define BT_AXIS_SWEEP_3_H #include "LinearMath/btVector3.h" #include "btOverlappingPairCache.h" @@ -1026,7 +1026,7 @@ void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE ed /// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. -/// It uses arrays rather than lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. /// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. class btAxisSweep3 : public btAxisSweep3Internal { @@ -1038,7 +1038,7 @@ public: /// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. /// This comes at the cost of more memory per handle, and a bit slower performance. -/// It uses arrays rather than lists for storage of the 3 axis. +/// It uses arrays rather then lists for storage of the 3 axis. class bt32BitAxisSweep3 : public btAxisSweep3Internal { public: diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index fe414effbfc..f1bf00594d3 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BROADPHASE_INTERFACE_H -#define BROADPHASE_INTERFACE_H +#ifndef BT_BROADPHASE_INTERFACE_H +#define BT_BROADPHASE_INTERFACE_H @@ -79,4 +79,4 @@ public: }; -#endif //BROADPHASE_INTERFACE_H +#endif //BT_BROADPHASE_INTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index 62d349739c3..bb58b828936 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BROADPHASE_PROXY_H -#define BROADPHASE_PROXY_H +#ifndef BT_BROADPHASE_PROXY_H +#define BT_BROADPHASE_PROXY_H #include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE #include "LinearMath/btVector3.h" @@ -246,7 +246,7 @@ class btBroadphasePairSortPredicate { public: - bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) + bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const { const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1; const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1; @@ -266,5 +266,5 @@ SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphaseP } -#endif //BROADPHASE_PROXY_H +#endif //BT_BROADPHASE_PROXY_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h index 0d8bca41c8e..36eec97174f 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COLLISION_ALGORITHM_H -#define COLLISION_ALGORITHM_H +#ifndef BT_COLLISION_ALGORITHM_H +#define BT_COLLISION_ALGORITHM_H #include "LinearMath/btScalar.h" #include "LinearMath/btAlignedObjectArray.h" @@ -77,4 +77,4 @@ public: }; -#endif //COLLISION_ALGORITHM_H +#endif //BT_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h index 2bb8ef5d2a7..409da80ae1b 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h @@ -259,6 +259,7 @@ struct btDbvt btAlignedObjectArray m_stkStack; + mutable btAlignedObjectArray m_rayTestStack; // Methods @@ -955,7 +956,7 @@ inline void btDbvt::rayTestInternal( const btDbvtNode* root, int depth=1; int treshold=DOUBLE_STACKSIZE-2; - btAlignedObjectArray stack; + btAlignedObjectArray& stack = m_rayTestStack; stack.resize(DOUBLE_STACKSIZE); stack[0]=root; btVector3 bounds[2]; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 8ded0006c3b..a79cf9402b1 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -13,9 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _DISPATCHER_H -#define _DISPATCHER_H - +#ifndef BT_DISPATCHER_H +#define BT_DISPATCHER_H #include "LinearMath/btScalar.h" class btCollisionAlgorithm; @@ -27,6 +26,7 @@ class btOverlappingPairCache; class btPersistentManifold; class btStackAlloc; +class btPoolAllocator; struct btDispatcherInfo { @@ -40,7 +40,7 @@ struct btDispatcherInfo m_stepCount(0), m_dispatchFunc(DISPATCH_DISCRETE), m_timeOfImpact(btScalar(1.)), - m_useContinuous(false), + m_useContinuous(true), m_debugDraw(0), m_enableSatConvex(false), m_enableSPU(true), @@ -48,7 +48,6 @@ struct btDispatcherInfo m_allowedCcdPenetration(btScalar(0.04)), m_useConvexConservativeDistanceUtil(false), m_convexConservativeDistanceThreshold(0.0f), - m_convexMaxDistanceUseCPT(false), m_stackAllocator(0) { @@ -65,7 +64,6 @@ struct btDispatcherInfo btScalar m_allowedCcdPenetration; bool m_useConvexConservativeDistanceUtil; btScalar m_convexConservativeDistanceThreshold; - bool m_convexMaxDistanceUseCPT; btStackAlloc* m_stackAllocator; }; @@ -98,6 +96,10 @@ public: virtual btPersistentManifold** getInternalManifoldPointer() = 0; + virtual btPoolAllocator* getInternalManifoldPool() = 0; + + virtual const btPoolAllocator* getInternalManifoldPool() const = 0; + virtual void* allocateCollisionAlgorithm(int size) = 0; virtual void freeCollisionAlgorithm(void* ptr) = 0; @@ -105,4 +107,4 @@ public: }; -#endif //_DISPATCHER_H +#endif //BT_DISPATCHER_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp index 6712f528e97..81369fe9b50 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -341,7 +341,7 @@ class btMultiSapBroadphasePairSortPredicate { public: - bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) + bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const { btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index 3945afb8d70..7a3806c1d28 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef OVERLAPPING_PAIR_CACHE_H -#define OVERLAPPING_PAIR_CACHE_H +#ifndef BT_OVERLAPPING_PAIR_CACHE_H +#define BT_OVERLAPPING_PAIR_CACHE_H #include "btBroadphaseInterface.h" @@ -464,6 +464,6 @@ public: }; -#endif //OVERLAPPING_PAIR_CACHE_H +#endif //BT_OVERLAPPING_PAIR_CACHE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h index 9e247d125f5..78382da79f0 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef QUANTIZED_BVH_H -#define QUANTIZED_BVH_H +#ifndef BT_QUANTIZED_BVH_H +#define BT_QUANTIZED_BVH_H class btSerializer; @@ -109,9 +109,9 @@ ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode //for child nodes int m_subPart; int m_triangleIndex; - int m_padding[5];//bad, due to alignment - +//pad the size to 64 bytes + char m_padding[20]; }; @@ -339,7 +339,7 @@ public: ///***************************************** expert/internal use only ************************* - void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.5)); + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; } ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized void buildInternal(); @@ -578,4 +578,4 @@ SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const -#endif //QUANTIZED_BVH_H +#endif //BT_QUANTIZED_BVH_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index 3e7c7ee3b62..7cb3c40a043 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SIMPLE_BROADPHASE_H -#define SIMPLE_BROADPHASE_H +#ifndef BT_SIMPLE_BROADPHASE_H +#define BT_SIMPLE_BROADPHASE_H #include "btOverlappingPairCache.h" @@ -167,5 +167,5 @@ public: -#endif //SIMPLE_BROADPHASE_H +#endif //BT_SIMPLE_BROADPHASE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h index f656e5c323a..22953af43fd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SPHERE_TRIANGLE_DETECTOR_H -#define SPHERE_TRIANGLE_DETECTOR_H +#ifndef BT_SPHERE_TRIANGLE_DETECTOR_H +#define BT_SPHERE_TRIANGLE_DETECTOR_H #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" @@ -47,5 +47,5 @@ private: btScalar m_contactBreakingThreshold; }; -#endif //SPHERE_TRIANGLE_DETECTOR_H +#endif //BT_SPHERE_TRIANGLE_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h index 21342175238..97c5be77003 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BOX_2D_BOX_2D__COLLISION_ALGORITHM_H -#define BOX_2D_BOX_2D__COLLISION_ALGORITHM_H +#ifndef BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H +#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H #include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -62,5 +62,5 @@ public: }; -#endif //BOX_2D_BOX_2D__COLLISION_ALGORITHM_H +#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h index e7d2cc25c22..f0bbae61e3b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BOX_BOX__COLLISION_ALGORITHM_H -#define BOX_BOX__COLLISION_ALGORITHM_H +#ifndef BT_BOX_BOX__COLLISION_ALGORITHM_H +#define BT_BOX_BOX__COLLISION_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -62,5 +62,5 @@ public: }; -#endif //BOX_BOX__COLLISION_ALGORITHM_H +#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h index 605294d47bd..3c941f7deb2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h @@ -16,8 +16,8 @@ subject to the following restrictions: 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BOX_BOX_DETECTOR_H -#define BOX_BOX_DETECTOR_H +#ifndef BT_BOX_BOX_DETECTOR_H +#define BT_BOX_BOX_DETECTOR_H class btBoxShape; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h index 1db51a36d03..f63e0923b78 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -15,6 +15,7 @@ subject to the following restrictions: #ifndef BT_COLLISION_CONFIGURATION #define BT_COLLISION_CONFIGURATION + struct btCollisionAlgorithmCreateFunc; class btStackAlloc; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h index a6da5f61a3c..1d7e74401dd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COLLISION_CREATE_FUNC -#define COLLISION_CREATE_FUNC +#ifndef BT_COLLISION_CREATE_FUNC +#define BT_COLLISION_CREATE_FUNC #include "LinearMath/btAlignedObjectArray.h" class btCollisionAlgorithm; @@ -41,5 +41,5 @@ struct btCollisionAlgorithmCreateFunc return 0; } }; -#endif //COLLISION_CREATE_FUNC +#endif //BT_COLLISION_CREATE_FUNC diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index 9fed44a19f7..29674f3be46 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -92,8 +92,16 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); } else { - mem = btAlignedAlloc(sizeof(btPersistentManifold),16); - + //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert. + if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0) + { + mem = btAlignedAlloc(sizeof(btPersistentManifold),16); + } else + { + btAssert(0); + //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration + return 0; + } } btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold); manifold->m_index1a = m_manifoldsPtr.size(); @@ -172,8 +180,7 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED)) { //broadphase filtering already deals with this - if ((body0->isStaticObject() || body0->isKinematicObject()) && - (body1->isStaticObject() || body1->isKinematicObject())) + if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject()) { m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED; printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index 3c4f039504a..5accad9a993 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COLLISION__DISPATCHER_H -#define COLLISION__DISPATCHER_H +#ifndef BT_COLLISION__DISPATCHER_H +#define BT_COLLISION__DISPATCHER_H #include "BulletCollision/BroadphaseCollision/btDispatcher.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -67,7 +67,8 @@ public: enum DispatcherFlags { CD_STATIC_STATIC_REPORTED = 1, - CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2 + CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2, + CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4 }; int getDispatcherFlags() const @@ -90,7 +91,7 @@ public: btPersistentManifold** getInternalManifoldPointer() { - return &m_manifoldsPtr[0]; + return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0; } btPersistentManifold* getManifoldByIndexInternal(int index) @@ -155,7 +156,17 @@ public: m_collisionConfiguration = config; } + virtual btPoolAllocator* getInternalManifoldPool() + { + return m_persistentManifoldPoolAllocator; + } + + virtual const btPoolAllocator* getInternalManifoldPool() const + { + return m_persistentManifoldPoolAllocator; + } + }; -#endif //COLLISION__DISPATCHER_H +#endif //BT_COLLISION__DISPATCHER_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index 5de829824ff..3a11c967ac9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COLLISION_OBJECT_H -#define COLLISION_OBJECT_H +#ifndef BT_COLLISION_OBJECT_H +#define BT_COLLISION_OBJECT_H #include "LinearMath/btTransform.h" @@ -521,4 +521,4 @@ SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const -#endif //COLLISION_OBJECT_H +#endif //BT_COLLISION_OBJECT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index bfe8d4f52fb..66b93b88efa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -33,6 +33,7 @@ subject to the following restrictions: #include "LinearMath/btQuickprof.h" #include "LinearMath/btStackAlloc.h" #include "LinearMath/btSerializer.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" //#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION @@ -154,7 +155,7 @@ void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj) minAabb -= contactThreshold; maxAabb += contactThreshold; - if(getDispatchInfo().m_convexMaxDistanceUseCPT) + if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) { btVector3 minAabb2,maxAabb2; colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); @@ -662,68 +663,103 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); } else { - //BT_PROFILE("convexSweepConcave"); - btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); - btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); - btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); - // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation - btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); - - //ConvexCast::CastResult - struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE) { - btCollisionWorld::ConvexResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btConcaveShape* m_triangleMesh; - - BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, - btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld): - btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = resultCallback.m_closestHitFraction; + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape; + btContinuousConvexCollision convexCaster1(castShape,planeShape); + btConvexCast* castPtr = &convexCaster1; + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); + } + } } - - virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + } else + { + //BT_PROFILE("convexSweepConcave"); + btConcaveShape* concaveShape = (btConcaveShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - if (hitFraction <= m_resultCallback->m_closestHitFraction) + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btConcaveShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) { + } - btCollisionWorld::LocalConvexResult convexResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitPointLocal, - hitFraction); - bool normalInWorldSpace = false; + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { - return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); - } - return hitFraction; - } + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); - }; + bool normalInWorldSpace = false; - BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform); - tccb.m_hitFraction = resultCallback.m_closestHitFraction; - tccb.m_allowedPenetration = allowedPenetration; - btVector3 boxMinLocal, boxMaxLocal; - castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; - btVector3 rayAabbMinLocal = convexFromLocal; - rayAabbMinLocal.setMin(convexToLocal); - btVector3 rayAabbMaxLocal = convexFromLocal; - rayAabbMaxLocal.setMax(convexToLocal); - rayAabbMinLocal += boxMinLocal; - rayAabbMaxLocal += boxMaxLocal; - concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + tccb.m_allowedPenetration = allowedPenetration; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + + btVector3 rayAabbMinLocal = convexFromLocal; + rayAabbMinLocal.setMin(convexToLocal); + btVector3 rayAabbMaxLocal = convexFromLocal; + rayAabbMaxLocal.setMax(convexToLocal); + rayAabbMinLocal += boxMinLocal; + rayAabbMaxLocal += boxMaxLocal; + concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); + } } } else { ///@todo : use AABB tree or other BVH acceleration structure! @@ -1162,15 +1198,14 @@ public: wv1 = m_worldTrans*triangle[1]; wv2 = m_worldTrans*triangle[2]; btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.); - - btVector3 normal = (wv1-wv0).cross(wv2-wv0); - normal.normalize(); - btVector3 normalColor(1,1,0); - m_debugDrawer->drawLine(center,center+normal,normalColor); - - - - + + if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals ) + { + btVector3 normal = (wv1-wv0).cross(wv2-wv0); + normal.normalize(); + btVector3 normalColor(1,1,0); + m_debugDrawer->drawLine(center,center+normal,normalColor); + } m_debugDrawer->drawLine(wv0,wv1,m_color); m_debugDrawer->drawLine(wv1,wv2,m_color); m_debugDrawer->drawLine(wv2,wv0,m_color); @@ -1195,126 +1230,162 @@ void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const } else { - switch (shape->getShapeType()) - { - case BOX_SHAPE_PROXYTYPE: - { - const btBoxShape* boxShape = static_cast(shape); - btVector3 halfExtents = boxShape->getHalfExtentsWithMargin(); - getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color); - break; - } + /// for polyhedral shapes + if (shape->isPolyhedral()) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; - case SPHERE_SHAPE_PROXYTYPE: + int i; + if (polyshape->getConvexPolyhedron()) { - const btSphereShape* sphereShape = static_cast(shape); - btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron(); + for (i=0;im_faces.size();i++) + { + btVector3 centroid(0,0,0); + int numVerts = poly->m_faces[i].m_indices.size(); + if (numVerts) + { + int lastV = poly->m_faces[i].m_indices[numVerts-1]; + for (int v=0;vm_faces[i].m_indices.size();v++) + { + int curVert = poly->m_faces[i].m_indices[v]; + centroid+=poly->m_vertices[curVert]; + getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color); + lastV = curVert; + } + } + centroid*= btScalar(1.f)/btScalar(numVerts); + if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals) + { + btVector3 normalColor(1,1,0); + btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]); + getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor); + } + + } - getDebugDrawer()->drawSphere(radius, worldTransform, color); - break; - } - case MULTI_SPHERE_SHAPE_PROXYTYPE: + + } else { - const btMultiSphereShape* multiSphereShape = static_cast(shape); - - btTransform childTransform; - childTransform.setIdentity(); - - for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + for (i=0;igetNumEdges();i++) { - childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); - getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color); + btVector3 a,b; + polyshape->getEdge(i,a,b); + btVector3 wa = worldTransform * a; + btVector3 wb = worldTransform * b; + getDebugDrawer()->drawLine(wa,wb,color); } - - break; } - case CAPSULE_SHAPE_PROXYTYPE: - { - const btCapsuleShape* capsuleShape = static_cast(shape); - btScalar radius = capsuleShape->getRadius(); - btScalar halfHeight = capsuleShape->getHalfHeight(); - int upAxis = capsuleShape->getUpAxis(); - getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color); - break; - } - case CONE_SHAPE_PROXYTYPE: + } + else + { + switch (shape->getShapeType()) { - const btConeShape* coneShape = static_cast(shape); - btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); - btScalar height = coneShape->getHeight();//+coneShape->getMargin(); - int upAxis= coneShape->getConeUpIndex(); - getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color); - break; + case BOX_SHAPE_PROXYTYPE: + { + const btBoxShape* boxShape = static_cast(shape); + btVector3 halfExtents = boxShape->getHalfExtentsWithMargin(); + getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color); + break; + } - } - case CYLINDER_SHAPE_PROXYTYPE: - { - const btCylinderShape* cylinder = static_cast(shape); - int upAxis = cylinder->getUpAxis(); - btScalar radius = cylinder->getRadius(); - btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; - getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color); - break; - } + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin - case STATIC_PLANE_PROXYTYPE: - { - const btStaticPlaneShape* staticPlaneShape = static_cast(shape); - btScalar planeConst = staticPlaneShape->getPlaneConstant(); - const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); - getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color); - break; + getDebugDrawer()->drawSphere(radius, worldTransform, color); + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + const btMultiSphereShape* multiSphereShape = static_cast(shape); - } - default: - { + btTransform childTransform; + childTransform.setIdentity(); - if (shape->isConcave()) - { - btConcaveShape* concaveMesh = (btConcaveShape*) shape; + for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + { + childTransform.setOrigin(multiSphereShape->getSpherePosition(i)); + getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color); + } - ///@todo pass camera, for some culling? no -> we are not a graphics lib - btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); - btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + const btCapsuleShape* capsuleShape = static_cast(shape); - DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); + btScalar radius = capsuleShape->getRadius(); + btScalar halfHeight = capsuleShape->getHalfHeight(); + int upAxis = capsuleShape->getUpAxis(); + getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color); + break; } + case CONE_SHAPE_PROXYTYPE: + { + const btConeShape* coneShape = static_cast(shape); + btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); + btScalar height = coneShape->getHeight();//+coneShape->getMargin(); - if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) + int upAxis= coneShape->getConeUpIndex(); + getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color); + break; + + } + case CYLINDER_SHAPE_PROXYTYPE: { - btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; - //todo: pass camera for some culling - btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); - btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); - //DebugDrawcallback drawCallback; - DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + btScalar radius = cylinder->getRadius(); + btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color); + break; } + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color); + break; - /// for polyhedral shapes - if (shape->isPolyhedral()) + } + default: { - btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; - int i; - for (i=0;igetNumEdges();i++) + if (shape->isConcave()) { - btVector3 a,b; - polyshape->getEdge(i,a,b); - btVector3 wa = worldTransform * a; - btVector3 wb = worldTransform * b; - getDebugDrawer()->drawLine(wa,wb,color); + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + ///@todo pass camera, for some culling? no -> we are not a graphics lib + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); } + if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) + { + btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; + //todo: pass camera for some culling + btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); + btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); + //DebugDrawcallback drawCallback; + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + } + + } } } @@ -1327,7 +1398,7 @@ void btCollisionWorld::debugDrawWorld() if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) { int numManifolds = getDispatcher()->getNumManifolds(); - btVector3 color(0,0,0); + btVector3 color(1,0.65,0); for (int i=0;igetManifoldByIndexInternal(i); @@ -1343,7 +1414,7 @@ void btCollisionWorld::debugDrawWorld() } } - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)) + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))) { int i; @@ -1352,7 +1423,7 @@ void btCollisionWorld::debugDrawWorld() btCollisionObject* colObj = m_collisionObjects[i]; if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0) { - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)) { btVector3 color(btScalar(1.),btScalar(1.),btScalar(1.)); switch(colObj->getActivationState()) @@ -1386,12 +1457,14 @@ void btCollisionWorld::debugDrawWorld() btVector3 minAabb2,maxAabb2; - colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); - minAabb2 -= contactThreshold; - maxAabb2 += contactThreshold; - - minAabb.setMin(minAabb2); - maxAabb.setMax(maxAabb2); + if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject()) + { + colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2); + minAabb2 -= contactThreshold; + maxAabb2 += contactThreshold; + minAabb.setMin(minAabb2); + maxAabb.setMax(maxAabb2); + } m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index b42e2c40b21..0a92d2d6e15 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -62,8 +62,8 @@ subject to the following restrictions: -#ifndef COLLISION_WORLD_H -#define COLLISION_WORLD_H +#ifndef BT_COLLISION_WORLD_H +#define BT_COLLISION_WORLD_H class btStackAlloc; class btCollisionShape; @@ -506,4 +506,4 @@ public: }; -#endif //COLLISION_WORLD_H +#endif //BT_COLLISION_WORLD_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 255e0af668c..404574989ab 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COMPOUND_COLLISION_ALGORITHM_H -#define COMPOUND_COLLISION_ALGORITHM_H +#ifndef BT_COMPOUND_COLLISION_ALGORITHM_H +#define BT_COMPOUND_COLLISION_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" @@ -83,4 +83,4 @@ public: }; -#endif //COMPOUND_COLLISION_ALGORITHM_H +#endif //BT_COMPOUND_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h index 5738401401e..53d13b87151 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONVEX_2D_CONVEX_2D_ALGORITHM_H -#define CONVEX_2D_CONVEX_2D_ALGORITHM_H +#ifndef BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H +#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H #include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" @@ -92,4 +92,4 @@ public: }; -#endif //CONVEX_2D_CONVEX_2D_ALGORITHM_H +#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 268ec4b6c7e..d2b2c221426 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -91,7 +91,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i btCollisionObject* ob = static_cast(m_triBody); - +#if 0 ///debug drawing of the overlapping triangles if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe )) { @@ -100,17 +100,8 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); - - //btVector3 center = triangle[0] + triangle[1]+triangle[2]; - //center *= btScalar(0.333333); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); - } - - - //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); +#endif if (m_convexBody->getCollisionShape()->isConvex()) { @@ -119,7 +110,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i btCollisionShape* tmpShape = ob->getCollisionShape(); ob->internalSetTemporaryCollisionShape( &tm ); - + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); if (m_resultOut->getBody0Internal() == m_triBody) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index 984a4c39e8e..f718d1dec25 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H +#ifndef BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H +#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" @@ -113,4 +113,4 @@ public: }; -#endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H +#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index 94385fed909..dd1f3e2490f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -17,6 +17,7 @@ subject to the following restrictions: ///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums ///with reproduction case //define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1 +//#define ZERO_MARGIN #include "btConvexConvexAlgorithm.h" @@ -26,6 +27,8 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" #include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" @@ -48,7 +51,7 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" - +#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h" /////////// @@ -331,6 +334,8 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl #endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER + + #ifdef USE_SEPDISTANCE_UTIL2 if (dispatchInfo.m_useConvexConservativeDistanceUtil) { @@ -357,13 +362,14 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl } else #endif //USE_SEPDISTANCE_UTIL2 { - if (dispatchInfo.m_convexMaxDistanceUseCPT) - { - input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); - } else - { - input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); - } + //if (dispatchInfo.m_convexMaxDistanceUseCPT) + //{ + // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); + //} else + //{ + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); +// } + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; } @@ -371,7 +377,7 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl input.m_transformA = body0->getWorldTransform(); input.m_transformB = body1->getWorldTransform(); - gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + @@ -389,6 +395,155 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl } #endif //USE_SEPDISTANCE_UTIL2 + if (min0->isPolyhedral() && min1->isPolyhedral()) + { + + + struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result + { + virtual void setShapeIdentifiersA(int partId0,int index0){} + virtual void setShapeIdentifiersB(int partId1,int index1){} + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + } + }; + + btDummyResult dummy; + + + btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0; + btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1; + if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron()) + { + + + + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btScalar minDist = -1e30f; + btVector3 sepNormalWorldSpace; + bool foundSepAxis = true; + + if (dispatchInfo.m_enableSatConvex) + { + foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis( + *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0->getWorldTransform(), + body1->getWorldTransform(), + sepNormalWorldSpace); + } else + { +#ifdef ZERO_MARGIN + gjkPairDetector.setIgnoreMargin(true); + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#else + //gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw); +#endif //ZERO_MARGIN + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance(); + minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin(); + +#ifdef ZERO_MARGIN + foundSepAxis = true;//gjkPairDetector.getCachedSeparatingDistance()<0.f; +#else + foundSepAxis = gjkPairDetector.getCachedSeparatingDistance()<(min0->getMargin()+min1->getMargin()); +#endif + } + } + if (foundSepAxis) + { +// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + + btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0->getWorldTransform(), + body1->getWorldTransform(), minDist-threshold, threshold, *resultOut); + + } + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + return; + + } else + { + //we can also deal with convex versus triangle (without connectivity data) + if (polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE) + { + + btVertexArray vertices; + btTriangleShape* tri = (btTriangleShape*)polyhedronB; + vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[0]); + vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[1]); + vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[2]); + + //tri->initializePolyhedralFeatures(); + + btScalar threshold = m_manifoldPtr->getContactBreakingThreshold(); + + btVector3 sepNormalWorldSpace; + btScalar minDist =-1e30f; + btScalar maxDist = threshold; + + bool foundSepAxis = false; + if (0) + { + polyhedronB->initializePolyhedralFeatures(); + foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis( + *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(), + body0->getWorldTransform(), + body1->getWorldTransform(), + sepNormalWorldSpace); + // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ()); + + } else + { +#ifdef ZERO_MARGIN + gjkPairDetector.setIgnoreMargin(true); + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#else + gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw); +#endif//ZERO_MARGIN + + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); + if (l2>SIMD_EPSILON) + { + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + //minDist = gjkPairDetector.getCachedSeparatingDistance(); + //maxDist = threshold; + minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin(); + foundSepAxis = true; + } + } + + + if (foundSepAxis) + { + btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), + body0->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut); + } + + + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + + return; + } + + } + + + } + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points @@ -398,66 +553,70 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl int i; btVector3 v0,v1; btVector3 sepNormalWorldSpace; + btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2(); - sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized(); - btPlaneSpace1(sepNormalWorldSpace,v0,v1); - - - bool perturbeA = true; - const btScalar angleLimit = 0.125f * SIMD_PI; - btScalar perturbeAngle; - btScalar radiusA = min0->getAngularMotionDisc(); - btScalar radiusB = min1->getAngularMotionDisc(); - if (radiusA < radiusB) - { - perturbeAngle = gContactBreakingThreshold /radiusA; - perturbeA = true; - } else + if (l2>SIMD_EPSILON) { - perturbeAngle = gContactBreakingThreshold / radiusB; - perturbeA = false; - } - if ( perturbeAngle > angleLimit ) - perturbeAngle = angleLimit; + sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2); + + btPlaneSpace1(sepNormalWorldSpace,v0,v1); - btTransform unPerturbedTransform; - if (perturbeA) - { - unPerturbedTransform = input.m_transformA; - } else - { - unPerturbedTransform = input.m_transformB; - } - - for ( i=0;iSIMD_EPSILON) + + bool perturbeA = true; + const btScalar angleLimit = 0.125f * SIMD_PI; + btScalar perturbeAngle; + btScalar radiusA = min0->getAngularMotionDisc(); + btScalar radiusB = min1->getAngularMotionDisc(); + if (radiusA < radiusB) { - btQuaternion perturbeRot(v0,perturbeAngle); - btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); - btQuaternion rotq(sepNormalWorldSpace,iterationAngle); - - + perturbeAngle = gContactBreakingThreshold /radiusA; + perturbeA = true; + } else + { + perturbeAngle = gContactBreakingThreshold / radiusB; + perturbeA = false; + } + if ( perturbeAngle > angleLimit ) + perturbeAngle = angleLimit; + + btTransform unPerturbedTransform; if (perturbeA) { - input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis()); - input.m_transformB = body1->getWorldTransform(); -#ifdef DEBUG_CONTACTS - dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); -#endif //DEBUG_CONTACTS + unPerturbedTransform = input.m_transformA; } else { - input.m_transformA = body0->getWorldTransform(); - input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis()); -#ifdef DEBUG_CONTACTS - dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); -#endif + unPerturbedTransform = input.m_transformB; } - btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); - gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); + for ( i=0;iSIMD_EPSILON) + { + btQuaternion perturbeRot(v0,perturbeAngle); + btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations)); + btQuaternion rotq(sepNormalWorldSpace,iterationAngle); + + + if (perturbeA) + { + input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis()); + input.m_transformB = body1->getWorldTransform(); + #ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0); + #endif //DEBUG_CONTACTS + } else + { + input.m_transformA = body0->getWorldTransform(); + input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis()); + #ifdef DEBUG_CONTACTS + dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0); + #endif + } + + btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw); + gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw); + } } - } } @@ -487,7 +646,7 @@ btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, { (void)resultOut; (void)dispatchInfo; - ///rather than checking ALL pairs, only calculate TOI when motion exceeds threshold + ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold ///col0->m_worldTransform, diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index d38aff6862c..4380b80eb4d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONVEX_CONVEX_ALGORITHM_H -#define CONVEX_CONVEX_ALGORITHM_H +#ifndef BT_CONVEX_CONVEX_ALGORITHM_H +#define BT_CONVEX_CONVEX_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" @@ -106,4 +106,4 @@ public: }; -#endif //CONVEX_CONVEX_ALGORITHM_H +#endif //BT_CONVEX_CONVEX_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp index dda85dc693f..b2e9bfaf593 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp @@ -96,23 +96,41 @@ void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0 if (!m_manifoldPtr) return; - btCollisionObject* convexObj = m_isSwapped? body1 : body0; + btCollisionObject* convexObj = m_isSwapped? body1 : body0; btCollisionObject* planeObj = m_isSwapped? body0: body1; btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); - + bool hasCollision = false; const btVector3& planeNormal = planeShape->getPlaneNormal(); - //const btScalar& planeConstant = planeShape->getPlaneConstant(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + btTransform planeInConvex; + planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; - //first perform a collision query with the non-perturbated collision objects + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) { - btQuaternion rotq(0,0,0,1); - collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut); + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); } - if (resultOut->getPersistentManifold()->getNumContacts()isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()m_numPerturbationIterations = numPerturbationIterations; convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; } + +void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold) +{ + btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF; + cpCF->m_numPerturbationIterations = numPerturbationIterations; + cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; + + btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF; + pcCF->m_numPerturbationIterations = numPerturbationIterations; + pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h index 6aa0d8c270f..81ed424a3db 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -129,6 +129,8 @@ public: ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection. void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); + void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3); + }; #endif //BT_DEFAULT_COLLISION_CONFIGURATION diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h index e54721dec21..f03c9dc3833 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef EMPTY_ALGORITH -#define EMPTY_ALGORITH +#ifndef BT_EMPTY_ALGORITH +#define BT_EMPTY_ALGORITH #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "btCollisionCreateFunc.h" #include "btCollisionDispatcher.h" @@ -51,4 +51,4 @@ public: } ATTRIBUTE_ALIGNED(16); -#endif //EMPTY_ALGORITH +#endif //BT_EMPTY_ALGORITH diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp index 5cceb04dbb4..4353cdac0b1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp @@ -1,6 +1,7 @@ #include "btInternalEdgeUtility.h" #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleShape.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" @@ -9,7 +10,6 @@ //#define DEBUG_INTERNAL_EDGE - #ifdef DEBUG_INTERNAL_EDGE #include #endif //DEBUG_INTERNAL_EDGE @@ -456,8 +456,14 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE) return; - btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape(); - btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap(); + btBvhTriangleMeshShape* trimesh = 0; + + if( colObj0->getRootCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE ) + trimesh = ((btScaledBvhTriangleMeshShape*)colObj0->getRootCollisionShape())->getChildShape(); + else + trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape(); + + btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap(); if (!triangleInfoMapPtr) return; @@ -501,14 +507,63 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB; localContactNormalOnB.normalize();//is this necessary? - - if ((info->m_edgeV0V1Angle)< SIMD_2_PI) + + // Get closest edge + int bestedge=-1; + btScalar disttobestedge=BT_LARGE_FLOAT; + // + // Edge 0 -> 1 + if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v0, v1, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=0; + disttobestedge=len; + } + } + // Edge 1 -> 2 + if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v1, v2, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=1; + disttobestedge=len; + } + } + // Edge 2 -> 0 + if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) + { + btVector3 nearest; + btNearestPointInLineSegment( cp.m_localPointB, v2, v0, nearest ); + btScalar len=(contact-nearest).length(); + // + if( len < disttobestedge ) + { + bestedge=2; + disttobestedge=len; + } + } + +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btVector3 upfix=tri_normal * btVector3(0.1f,0.1f,0.1f); + btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red ); +#endif + if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) { #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); #endif btScalar len = (contact-nearest).length(); if(lenm_edgeDistanceThreshold) + if( bestedge==0 ) { btVector3 edge(v0-v1); isNearEdge = true; @@ -577,7 +632,11 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green); #endif //BT_INTERNAL_EDGE_DEBUG_DRAW - if ((info->m_edgeV1V2Angle)< SIMD_2_PI) +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix , green ); +#endif + + if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) { #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black); @@ -587,6 +646,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btScalar len = (contact-nearest).length(); if(lenm_edgeDistanceThreshold) + if( bestedge==1 ) { isNearEdge = true; #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW @@ -658,8 +718,11 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue); #endif //BT_INTERNAL_EDGE_DEBUG_DRAW +#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW + btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix , blue ); +#endif - if ((info->m_edgeV2V0Angle)< SIMD_2_PI) + if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold) { #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW @@ -668,6 +731,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* btScalar len = (contact-nearest).length(); if(lenm_edgeDistanceThreshold) + if( bestedge==2 ) { isNearEdge = true; #ifdef BT_INTERNAL_EDGE_DEBUG_DRAW @@ -759,11 +823,17 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal; } else { + btVector3 newNormal = tri_normal *frontFacing; + //if the tri_normal is pointing opposite direction as the current local contact normal, skip it + btScalar d = newNormal.dot(localContactNormalOnB) ; + if (d< 0) + { + return; + } //modify the normal to be the triangle normal (or backfacing normal) - cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *(tri_normal *frontFacing); + cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *newNormal; } - - + // Reproject collision point along normal. cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1; cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index fd684c056f7..bf24246ea2f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -64,8 +64,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b btAssert(m_manifoldPtr); //order in manifold needs to match -// if (depth > m_manifoldPtr->getContactBreakingThreshold()) - if (depth > m_manifoldPtr->getContactProcessingThreshold()) + if (depth > m_manifoldPtr->getContactBreakingThreshold()) +// if (depth > m_manifoldPtr->getContactProcessingThreshold()) return; bool isSwapped = m_manifoldPtr->getBody0() != m_body0; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 927e2bc4f76..18199b49752 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ -#ifndef MANIFOLD_RESULT_H -#define MANIFOLD_RESULT_H +#ifndef BT_MANIFOLD_RESULT_H +#define BT_MANIFOLD_RESULT_H class btCollisionObject; #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -125,4 +125,4 @@ public: }; -#endif //MANIFOLD_RESULT_H +#endif //BT_MANIFOLD_RESULT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index bb2a7f23985..871c64415a2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -47,6 +47,8 @@ void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btColl { btOverlappingPairCache* pairCachePtr = colWorld->getPairCache(); const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs(); + if (numOverlappingPairs) + { btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr(); for (int i=0;igetIslandTag()); } } + } } } @@ -190,7 +193,7 @@ class btPersistentManifoldSortPredicate { public: - SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) + SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const { return getIslandId(lhs) < getIslandId(rhs); } @@ -327,11 +330,13 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio //kinematic objects don't merge islands, but wake up all connected objects if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) { - colObj1->activate(); + if (colObj0->hasContactResponse()) + colObj1->activate(); } if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) { - colObj0->activate(); + if (colObj1->hasContactResponse()) + colObj0->activate(); } if(m_splitIslands) { @@ -362,7 +367,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, { btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); int maxNumManifolds = dispatcher->getNumManifolds(); - callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); + callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); } else { @@ -372,8 +377,10 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, int numManifolds = int (m_islandmanifold.size()); - //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) + //tried a radix sort, but quicksort/heapsort seems still faster + //@todo rewrite island management m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); + //m_islandmanifold.heapSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) @@ -427,7 +434,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, if (!islandSleeping) { - callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); + callback->processIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index d059f5d6b0d..e24c6afeca1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SIMULATION_ISLAND_MANAGER_H -#define SIMULATION_ISLAND_MANAGER_H +#ifndef BT_SIMULATION_ISLAND_MANAGER_H +#define BT_SIMULATION_ISLAND_MANAGER_H #include "BulletCollision/CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" @@ -59,7 +59,7 @@ public: { virtual ~IslandCallback() {}; - virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; + virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; }; void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback); @@ -77,5 +77,5 @@ public: }; -#endif //SIMULATION_ISLAND_MANAGER_H +#endif //BT_SIMULATION_ISLAND_MANAGER_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h index 47111d1c4af..60286ae0aa4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H -#define SPHERE_BOX_COLLISION_ALGORITHM_H +#ifndef BT_SPHERE_BOX_COLLISION_ALGORITHM_H +#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -71,5 +71,5 @@ public: }; -#endif //SPHERE_BOX_COLLISION_ALGORITHM_H +#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h index 7d07512ca66..e55acf277e6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H -#define SPHERE_SPHERE_COLLISION_ALGORITHM_H +#ifndef BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H +#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -62,5 +62,5 @@ public: }; -#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H +#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h index 606c3635ae9..7c6c4d8f8d5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H +#ifndef BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H +#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #include "btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -65,5 +65,5 @@ public: }; -#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H +#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp index 4c4f58d44fa..5222933595d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -53,7 +53,7 @@ class btUnionFindElementSortPredicate { public: - bool operator() ( const btElement& lhs, const btElement& rhs ) + bool operator() ( const btElement& lhs, const btElement& rhs ) const { return lhs.m_id < rhs.m_id; } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h index 2cce335145b..ef2a29202f7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef UNION_FIND_H -#define UNION_FIND_H +#ifndef BT_UNION_FIND_H +#define BT_UNION_FIND_H #include "LinearMath/btAlignedObjectArray.h" @@ -126,4 +126,4 @@ class btUnionFind }; -#endif //UNION_FIND_H +#endif //BT_UNION_FIND_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h index fc032069c03..f4a9ca03e5c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef OBB_BOX_2D_SHAPE_H -#define OBB_BOX_2D_SHAPE_H +#ifndef BT_OBB_BOX_2D_SHAPE_H +#define BT_OBB_BOX_2D_SHAPE_H #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" @@ -83,6 +83,7 @@ public: } + ///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero) btBox2dShape( const btVector3& boxHalfExtents) : btPolyhedralConvexShape(), m_centroid(0,0,0) @@ -97,6 +98,11 @@ public: m_normals[2].setValue(0,1,0); m_normals[3].setValue(-1,0,0); + btScalar minDimension = boxHalfExtents.getX(); + if (minDimension>boxHalfExtents.getY()) + minDimension = boxHalfExtents.getY(); + setSafeMargin(minDimension); + m_shapeType = BOX_2D_SHAPE_PROXYTYPE; btVector3 margin(getMargin(),getMargin(),getMargin()); m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; @@ -358,6 +364,6 @@ public: }; -#endif //OBB_BOX_2D_SHAPE_H +#endif //BT_OBB_BOX_2D_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp index c6644efbef3..3859138f18a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -14,8 +14,18 @@ subject to the following restrictions: */ #include "btBoxShape.h" +btBoxShape::btBoxShape( const btVector3& boxHalfExtents) +: btPolyhedralConvexShape() +{ + m_shapeType = BOX_SHAPE_PROXYTYPE; + + setSafeMargin(boxHalfExtents); + + btVector3 margin(getMargin(),getMargin(),getMargin()); + m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; +}; + -//{ void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h index b405efc8e3c..0c5857dae62 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef OBB_BOX_MINKOWSKI_H -#define OBB_BOX_MINKOWSKI_H +#ifndef BT_OBB_BOX_MINKOWSKI_H +#define BT_OBB_BOX_MINKOWSKI_H #include "btPolyhedralConvexShape.h" #include "btCollisionMargin.h" @@ -80,13 +80,7 @@ public: } - btBoxShape( const btVector3& boxHalfExtents) - : btPolyhedralConvexShape() - { - m_shapeType = BOX_SHAPE_PROXYTYPE; - btVector3 margin(getMargin(),getMargin(),getMargin()); - m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin; - }; + btBoxShape( const btVector3& boxHalfExtents); virtual void setMargin(btScalar collisionMargin) { @@ -145,7 +139,7 @@ public: virtual void getVertex(int i,btVector3& vtx) const { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 halfExtents = getHalfExtentsWithMargin(); vtx = btVector3( halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1), @@ -313,6 +307,6 @@ public: }; -#endif //OBB_BOX_MINKOWSKI_H +#endif //BT_OBB_BOX_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index c269ef27bdb..d1c21629873 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BVH_TRIANGLE_MESH_SHAPE_H -#define BVH_TRIANGLE_MESH_SHAPE_H +#ifndef BT_BVH_TRIANGLE_MESH_SHAPE_H +#define BT_BVH_TRIANGLE_MESH_SHAPE_H #include "btTriangleMeshShape.h" #include "btOptimizedBvh.h" @@ -136,4 +136,4 @@ SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() con -#endif //BVH_TRIANGLE_MESH_SHAPE_H +#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index 2faa11d4360..864df26e931 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -55,7 +55,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter btVector3 pos(0,0,0); pos[getUpAxis()] = getHalfHeight(); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + vtx = pos +vec*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -67,7 +67,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter btVector3 pos(0,0,0); pos[getUpAxis()] = -getHalfHeight(); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + vtx = pos +vec*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -96,7 +96,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter { btVector3 pos(0,0,0); pos[getUpAxis()] = getHalfHeight(); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + vtx = pos +vec*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) { @@ -107,7 +107,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter { btVector3 pos(0,0,0); pos[getUpAxis()] = -getHalfHeight(); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + vtx = pos +vec*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) { diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h index 18fd026041f..474bf1fb499 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h @@ -13,14 +13,15 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COLLISION_MARGIN_H -#define COLLISION_MARGIN_H - -//used by Gjk and some other algorithms +#ifndef BT_COLLISION_MARGIN_H +#define BT_COLLISION_MARGIN_H +///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape. +///This collision margin is used by Gjk and some other algorithms +///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API #define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01) -#endif //COLLISION_MARGIN_H +#endif //BT_COLLISION_MARGIN_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h index f32bd736a99..865c1067744 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COLLISION_SHAPE_H -#define COLLISION_SHAPE_H +#ifndef BT_COLLISION_SHAPE_H +#define BT_COLLISION_SHAPE_H #include "LinearMath/btTransform.h" #include "LinearMath/btVector3.h" @@ -146,5 +146,5 @@ SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const -#endif //COLLISION_SHAPE_H +#endif //BT_COLLISION_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index 7f41dd4517b..141034a8e8c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef COMPOUND_SHAPE_H -#define COMPOUND_SHAPE_H +#ifndef BT_COMPOUND_SHAPE_H +#define BT_COMPOUND_SHAPE_H #include "btCollisionShape.h" @@ -209,4 +209,4 @@ SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const -#endif //COMPOUND_SHAPE_H +#endif //BT_COMPOUND_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h index 2a370a47c75..2a03241c9d7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONCAVE_SHAPE_H -#define CONCAVE_SHAPE_H +#ifndef BT_CONCAVE_SHAPE_H +#define BT_CONCAVE_SHAPE_H #include "btCollisionShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -57,4 +57,4 @@ public: }; -#endif //CONCAVE_SHAPE_H +#endif //BT_CONCAVE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h index bd7d1443ac2..b69b5c5b0c8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONE_MINKOWSKI_H -#define CONE_MINKOWSKI_H +#ifndef BT_CONE_MINKOWSKI_H +#define BT_CONE_MINKOWSKI_H #include "btConvexInternalShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -99,5 +99,5 @@ class btConeShapeZ : public btConeShape public: btConeShapeZ(btScalar radius,btScalar height); }; -#endif //CONE_MINKOWSKI_H +#endif //BT_CONE_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp index 69bc67cafab..226245979ab 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp @@ -208,4 +208,48 @@ const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* seriali return "btConvexHullShapeData"; } +void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const +{ +#if 1 + min = FLT_MAX; + max = -FLT_MAX; + btVector3 witnesPtMin; + btVector3 witnesPtMax; + + int numVerts = m_unscaledPoints.size(); + for(int i=0;i max) + { + max = dp; + witnesPtMax=pt; + } + } +#else + btVector3 localAxis = dir*trans.getBasis(); + btVector3 vtx1 = trans(localGetSupportingVertex(localAxis)); + btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis)); + + min = vtx1.dot(dir); + max = vtx2.dot(dir); +#endif + + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } + + +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h index bf960f4df92..95a2af6a3a0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONVEX_HULL_SHAPE_H -#define CONVEX_HULL_SHAPE_H +#ifndef BT_CONVEX_HULL_SHAPE_H +#define BT_CONVEX_HULL_SHAPE_H #include "btPolyhedralConvexShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -73,6 +73,8 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; + //debugging virtual const char* getName()const {return "Convex";} @@ -116,5 +118,5 @@ SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const } -#endif //CONVEX_HULL_SHAPE_H +#endif //BT_CONVEX_HULL_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h index 12527731804..85cd9ef90c7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -21,6 +21,11 @@ subject to the following restrictions: ///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. +///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN. +///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h +///Note that when creating small shapes (derived from btConvexInternalShape), +///you need to make sure to set a smaller collision margin, using the 'setMargin' API +///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape class btConvexInternalShape : public btConvexShape { @@ -62,6 +67,23 @@ public: m_implicitShapeDimensions = dimensions; } + void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f) + { + btScalar safeMargin = defaultMarginMultiplier*minDimension; + if (safeMargin < getMargin()) + { + setMargin(safeMargin); + } + } + void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f) + { + //see http://code.google.com/p/bullet/issues/detail?id=349 + //this margin check could could be added to other collision shapes too, + //or add some assert/warning somewhere + btScalar minDimension=halfExtents[halfExtents.minAxis()]; + setSafeMargin(minDimension, defaultMarginMultiplier); + } + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp new file mode 100644 index 00000000000..1e26be531c2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp @@ -0,0 +1,296 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +///This file was written by Erwin Coumans +///Separating axis rest based on work from Pierre Terdiman, see +///And contact clipping based on work from Simon Hobbs + +#include "btConvexPolyhedron.h" +#include "LinearMath/btHashMap.h" + +btConvexPolyhedron::btConvexPolyhedron() +{ + +} +btConvexPolyhedron::~btConvexPolyhedron() +{ + +} + + +inline bool IsAlmostZero(const btVector3& v) +{ + if(fabsf(v.x())>1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +struct btInternalVertexPair +{ + btInternalVertexPair(short int v0,short int v1) + :m_v0(v0), + m_v1(v1) + { + if (m_v1>m_v0) + btSwap(m_v0,m_v1); + } + short int m_v0; + short int m_v1; + int getHash() const + { + return m_v0+(m_v1<<16); + } + bool equals(const btInternalVertexPair& other) const + { + return m_v0==other.m_v0 && m_v1==other.m_v1; + } +}; + +struct btInternalEdge +{ + btInternalEdge() + :m_face0(-1), + m_face1(-1) + { + } + short int m_face0; + short int m_face1; +}; + +// + +#ifdef TEST_INTERNAL_OBJECTS +bool btConvexPolyhedron::testContainment() const +{ + for(int p=0;p<8;p++) + { + btVector3 LocalPt; + if(p==0) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]); + else if(p==1) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]); + else if(p==2) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]); + else if(p==3) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]); + else if(p==4) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]); + else if(p==5) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]); + else if(p==6) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]); + else if(p==7) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]); + + for(int i=0;i0.0f) + return false; + } + } + return true; +} +#endif + +void btConvexPolyhedron::initialize() +{ + + btHashMap edges; + + btScalar TotalArea = 0.0f; + + m_localCenter.setValue(0, 0, 0); + for(int i=0;im_face0>=0); + btAssert(edptr->m_face1<0); + edptr->m_face1 = i; + } else + { + btInternalEdge ed; + ed.m_face0 = i; + edges.insert(vp,ed); + } + } + } + +#ifdef USE_CONNECTED_FACES + for(int i=0;im_face0>=0); + btAssert(edptr->m_face1>=0); + + int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0; + m_faces[i].m_connectedFaces[j] = connectedFace; + } + } +#endif//USE_CONNECTED_FACES + + for(int i=0;iMaxX) MaxX = pt.x(); + if(pt.y()MaxY) MaxY = pt.y(); + if(pt.z()MaxZ) MaxZ = pt.z(); + } + mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ); + mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ); + + + +// const btScalar r = m_radius / sqrtf(2.0f); + const btScalar r = m_radius / sqrtf(3.0f); + const int LargestExtent = mE.maxAxis(); + const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f; + m_extents[0] = m_extents[1] = m_extents[2] = r; + m_extents[LargestExtent] = mE[LargestExtent]*0.5f; + bool FoundBox = false; + for(int j=0;j<1024;j++) + { + if(testContainment()) + { + FoundBox = true; + break; + } + + m_extents[LargestExtent] -= Step; + } + if(!FoundBox) + { + m_extents[0] = m_extents[1] = m_extents[2] = r; + } + else + { + // Refine the box + const btScalar Step = (m_radius - r)/1024.0f; + const int e0 = (1< max) max = dp; + } + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } +} \ No newline at end of file diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h new file mode 100644 index 00000000000..08db39a33c8 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h @@ -0,0 +1,62 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +///This file was written by Erwin Coumans + + +#ifndef _BT_POLYHEDRAL_FEATURES_H +#define _BT_POLYHEDRAL_FEATURES_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btAlignedObjectArray.h" + +#define TEST_INTERNAL_OBJECTS 1 + + +struct btFace +{ + btAlignedObjectArray m_indices; +// btAlignedObjectArray m_connectedFaces; + btScalar m_plane[4]; +}; + + +class btConvexPolyhedron +{ + public: + btConvexPolyhedron(); + virtual ~btConvexPolyhedron(); + + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_faces; + btAlignedObjectArray m_uniqueEdges; + + btVector3 m_localCenter; + btVector3 m_extents; + btScalar m_radius; + btVector3 mC; + btVector3 mE; + + void initialize(); + bool testContainment() const; + + void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; +}; + + +#endif //_BT_POLYHEDRAL_FEATURES_H + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp index f5f3aa58aa4..8c67d8ebef1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -43,6 +43,23 @@ btConvexShape::~btConvexShape() } +void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const +{ + btVector3 localAxis = dir*trans.getBasis(); + btVector3 vtx1 = trans(localGetSupportingVertex(localAxis)); + btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis)); + + min = vtx1.dot(dir); + max = vtx2.dot(dir); + + if(min>max) + { + btScalar tmp = min; + min = max; + max = tmp; + } +} + static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling) { @@ -227,7 +244,7 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV pos[capsuleUpAxis] = halfHeight; //vtx = pos +vec*(radius); - vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV(); + vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); newDot = vec.dot(vtx); @@ -242,7 +259,7 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV pos[capsuleUpAxis] = -halfHeight; //vtx = pos +vec*(radius); - vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV(); + vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV(); newDot = vec.dot(vtx); if (newDot > maxDot) { diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h index 9c158259c1c..290cd9fd13c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONVEX_SHAPE_INTERFACE1 -#define CONVEX_SHAPE_INTERFACE1 +#ifndef BT_CONVEX_SHAPE_INTERFACE1 +#define BT_CONVEX_SHAPE_INTERFACE1 #include "btCollisionShape.h" @@ -52,6 +52,8 @@ public: btScalar getMarginNonVirtual () const; void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const; + virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const; + //notice that the vectors should be unit length virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; @@ -79,4 +81,4 @@ public: -#endif //CONVEX_SHAPE_INTERFACE1 +#endif //BT_CONVEX_SHAPE_INTERFACE1 diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h index f5167e74b80..af5d00388e8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -12,8 +12,8 @@ subject to the following restrictions: 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONVEX_TRIANGLEMESH_SHAPE_H -#define CONVEX_TRIANGLEMESH_SHAPE_H +#ifndef BT_CONVEX_TRIANGLEMESH_SHAPE_H +#define BT_CONVEX_TRIANGLEMESH_SHAPE_H #include "btPolyhedralConvexShape.h" @@ -69,7 +69,7 @@ public: -#endif //CONVEX_TRIANGLEMESH_SHAPE_H +#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp index c2e534b0b46..6cfe43be4da 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -19,6 +19,8 @@ btCylinderShape::btCylinderShape (const btVector3& halfExtents) :btConvexInternalShape(), m_upAxis(1) { + setSafeMargin(halfExtents); + btVector3 margin(getMargin(),getMargin(),getMargin()); m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin; m_shapeType = CYLINDER_SHAPE_PROXYTYPE; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h index f7899265d31..125bfc78a77 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CYLINDER_MINKOWSKI_H -#define CYLINDER_MINKOWSKI_H +#ifndef BT_CYLINDER_MINKOWSKI_H +#define BT_CYLINDER_MINKOWSKI_H #include "btBoxShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -196,5 +196,5 @@ SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSer -#endif //CYLINDER_MINKOWSKI_H +#endif //BT_CYLINDER_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h index 9f6b4435c29..87b7b66d1e1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef EMPTY_SHAPE_H -#define EMPTY_SHAPE_H +#ifndef BT_EMPTY_SHAPE_H +#define BT_EMPTY_SHAPE_H #include "btConcaveShape.h" @@ -67,4 +67,4 @@ protected: -#endif //EMPTY_SHAPE_H +#endif //BT_EMPTY_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp index 3a1e6f4a2b9..95631c30190 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp @@ -21,7 +21,7 @@ subject to the following restrictions: btHeightfieldTerrainShape::btHeightfieldTerrainShape ( -int heightStickWidth, int heightStickLength, void* heightfieldData, +int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis, PHY_ScalarType hdt, bool flipQuadEdges ) @@ -33,7 +33,7 @@ PHY_ScalarType hdt, bool flipQuadEdges -btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges) +btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,const void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges) { // legacy constructor: support only float or unsigned char, // and min height is zero @@ -53,7 +53,7 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int h void btHeightfieldTerrainShape::initialize ( -int heightStickWidth, int heightStickLength, void* heightfieldData, +int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType hdt, bool flipQuadEdges ) diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h index 4f5d1e35bf3..78e231e08e6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H -#define HEIGHTFIELD_TERRAIN_SHAPE_H +#ifndef BT_HEIGHTFIELD_TERRAIN_SHAPE_H +#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H #include "btConcaveShape.h" @@ -85,10 +85,10 @@ protected: btScalar m_heightScale; union { - unsigned char* m_heightfieldDataUnsignedChar; - short* m_heightfieldDataShort; - btScalar* m_heightfieldDataFloat; - void* m_heightfieldDataUnknown; + const unsigned char* m_heightfieldDataUnsignedChar; + const short* m_heightfieldDataShort; + const btScalar* m_heightfieldDataFloat; + const void* m_heightfieldDataUnknown; }; PHY_ScalarType m_heightDataType; @@ -111,7 +111,7 @@ protected: backwards-compatible without a lot of copy/paste. */ void initialize(int heightStickWidth, int heightStickLength, - void* heightfieldData, btScalar heightScale, + const void* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges); @@ -123,7 +123,7 @@ public: heightScale is needed for any integer-based heightfield data types. */ btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength, - void* heightfieldData, btScalar heightScale, + const void* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges); @@ -135,7 +135,7 @@ public: compatibility reasons, heightScale is calculated as maxHeight / 65535 (and is only used when useFloatData = false). */ - btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); + btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,const void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); virtual ~btHeightfieldTerrainShape(); @@ -158,4 +158,4 @@ public: }; -#endif //HEIGHTFIELD_TERRAIN_SHAPE_H +#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h index 030e167da50..866f9b4da4d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h @@ -15,8 +15,8 @@ subject to the following restrictions: /// This file was created by Alex Silverman -#ifndef MATERIAL_H -#define MATERIAL_H +#ifndef BT_MATERIAL_H +#define BT_MATERIAL_H // Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties class btMaterial @@ -31,5 +31,5 @@ public: btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; } }; -#endif // MATERIAL_H +#endif // BT_MATERIAL_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h index d6fd040213b..6c844e8c0af 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MINKOWSKI_SUM_SHAPE_H -#define MINKOWSKI_SUM_SHAPE_H +#ifndef BT_MINKOWSKI_SUM_SHAPE_H +#define BT_MINKOWSKI_SUM_SHAPE_H #include "btConvexInternalShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -57,4 +57,4 @@ public: } }; -#endif //MINKOWSKI_SUM_SHAPE_H +#endif //BT_MINKOWSKI_SUM_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h index 3db7e320889..06c5d16d941 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MULTI_SPHERE_MINKOWSKI_H -#define MULTI_SPHERE_MINKOWSKI_H +#ifndef BT_MULTI_SPHERE_MINKOWSKI_H +#define BT_MULTI_SPHERE_MINKOWSKI_H #include "btConvexInternalShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -96,4 +96,4 @@ SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const -#endif //MULTI_SPHERE_MINKOWSKI_H +#endif //BT_MULTI_SPHERE_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h index 96b2ad95b6d..2b92ab7d1b7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h @@ -15,8 +15,8 @@ subject to the following restrictions: /// This file was created by Alex Silverman -#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H -#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#ifndef BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#define BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H #include "btBvhTriangleMeshShape.h" #include "btMaterial.h" @@ -117,4 +117,4 @@ public: } ; -#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp index 981b8a2652c..6f36775f7c9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -43,7 +43,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized NodeTriangleCallback& operator=(NodeTriangleCallback& other) { - m_triangleNodes = other.m_triangleNodes; + m_triangleNodes.copyFromArray(other.m_triangleNodes); return *this; } @@ -84,7 +84,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) { - m_triangleNodes = other.m_triangleNodes; + m_triangleNodes.copyFromArray(other.m_triangleNodes); m_optimizedTree = other.m_optimizedTree; return *this; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h index 749fe6005dd..715961f5528 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -15,8 +15,8 @@ subject to the following restrictions: ///Contains contributions from Disney Studio's -#ifndef OPTIMIZED_BVH_H -#define OPTIMIZED_BVH_H +#ifndef BT_OPTIMIZED_BVH_H +#define BT_OPTIMIZED_BVH_H #include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" @@ -60,6 +60,6 @@ public: }; -#endif //OPTIMIZED_BVH_H +#endif //BT_OPTIMIZED_BVH_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp index b1ecb3e432c..82def79cf55 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -14,10 +14,289 @@ subject to the following restrictions: */ #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "btConvexPolyhedron.h" +#include "LinearMath/btConvexHullComputer.h" +#include +#include "LinearMath/btGeometryUtil.h" +#include "LinearMath/btGrahamScan2dConvexHull.h" -btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape() + +btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(), +m_polyhedron(0) +{ + +} + +btPolyhedralConvexShape::~btPolyhedralConvexShape() +{ + if (m_polyhedron) + { + btAlignedFree(m_polyhedron); + } +} + + +bool btPolyhedralConvexShape::initializePolyhedralFeatures() { + if (m_polyhedron) + btAlignedFree(m_polyhedron); + + void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16); + m_polyhedron = new (mem) btConvexPolyhedron; + + btAlignedObjectArray orgVertices; + + for (int i=0;i planeEquations; + btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations); + + btAlignedObjectArray shiftedPlaneEquations; + for (int p=0;p tmpVertices; + + btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices); + btConvexHullComputer conv; + conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f); + +#else + btConvexHullComputer conv; + conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f); + +#endif + + + + btAlignedObjectArray faceNormals; + int numFaces = conv.faces.size(); + faceNormals.resize(numFaces); + btConvexHullComputer* convexUtil = &conv; + + + btAlignedObjectArray tmpFaces; + tmpFaces.resize(numFaces); + + int numVertices = convexUtil->vertices.size(); + m_polyhedron->m_vertices.resize(numVertices); + for (int p=0;pm_vertices[p] = convexUtil->vertices[p]; + } + + + for (int i=0;ifaces[i]; + //printf("face=%d\n",face); + const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face]; + const btConvexHullComputer::Edge* edge = firstEdge; + + btVector3 edges[3]; + int numEdges = 0; + //compute face normals + + btScalar maxCross2 = 0.f; + int chosenEdge = -1; + + do + { + + int src = edge->getSourceVertex(); + tmpFaces[i].m_indices.push_back(src); + int targ = edge->getTargetVertex(); + btVector3 wa = convexUtil->vertices[src]; + + btVector3 wb = convexUtil->vertices[targ]; + btVector3 newEdge = wb-wa; + newEdge.normalize(); + if (numEdges<2) + edges[numEdges++] = newEdge; + + edge = edge->getNextEdgeOfFace(); + } while (edge!=firstEdge); + + btScalar planeEq = 1e30f; + + + if (numEdges==2) + { + faceNormals[i] = edges[0].cross(edges[1]); + faceNormals[i].normalize(); + tmpFaces[i].m_plane[0] = faceNormals[i].getX(); + tmpFaces[i].m_plane[1] = faceNormals[i].getY(); + tmpFaces[i].m_plane[2] = faceNormals[i].getZ(); + tmpFaces[i].m_plane[3] = planeEq; + + } + else + { + btAssert(0);//degenerate? + faceNormals[i].setZero(); + } + + for (int v=0;vm_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]); + if (planeEq>eq) + { + planeEq=eq; + } + } + tmpFaces[i].m_plane[3] = -planeEq; + } + + //merge coplanar faces and copy them to m_polyhedron + + btScalar faceWeldThreshold= 0.999f; + btAlignedObjectArray todoFaces; + for (int i=0;i coplanarFaceGroup; + int refFace = todoFaces[todoFaces.size()-1]; + + coplanarFaceGroup.push_back(refFace); + btFace& faceA = tmpFaces[refFace]; + todoFaces.pop_back(); + + btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]); + for (int j=todoFaces.size()-1;j>=0;j--) + { + int i = todoFaces[j]; + btFace& faceB = tmpFaces[i]; + btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]); + if (faceNormalA.dot(faceNormalB)>faceWeldThreshold) + { + coplanarFaceGroup.push_back(i); + todoFaces.remove(i); + } + } + + + bool did_merge = false; + if (coplanarFaceGroup.size()>1) + { + //do the merge: use Graham Scan 2d convex hull + + btAlignedObjectArray orgpoints; + + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + + btFace& face = tmpFaces[coplanarFaceGroup[i]]; + btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]); + btVector3 xyPlaneNormal(0,0,1); + + btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal); + + for (int f=0;fm_vertices[orgIndex]; + btVector3 rotatedPt = quatRotate(rotationArc,pt); + rotatedPt.setZ(0); + bool found = false; + + for (int i=0;i hull; + GrahamScanConvexHull2D(orgpoints,hull); + + for (int i=0;im_faces.push_back(combinedFace); + } + } + if(!did_merge) + { + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + } + + } + + + + } + + m_polyhedron->initialize(); + + return true; } @@ -183,11 +462,14 @@ void btPolyhedralConvexAabbCachingShape::recalcLocalAabb() btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); vec[i] = btScalar(1.); btVector3 tmp = localGetSupportingVertex(vec); - m_localAabbMax[i] = tmp[i]+m_collisionMargin; + m_localAabbMax[i] = tmp[i]; vec[i] = btScalar(-1.); tmp = localGetSupportingVertex(vec); - m_localAabbMin[i] = tmp[i]-m_collisionMargin; + m_localAabbMin[i] = tmp[i]; } #endif } + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h index 2c691b95652..ee2e1e28277 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -13,23 +13,37 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BU_SHAPE -#define BU_SHAPE +#ifndef BT_POLYHEDRAL_CONVEX_SHAPE_H +#define BT_POLYHEDRAL_CONVEX_SHAPE_H #include "LinearMath/btMatrix3x3.h" #include "btConvexInternalShape.h" +class btConvexPolyhedron; ///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes. class btPolyhedralConvexShape : public btConvexInternalShape { + protected: + btConvexPolyhedron* m_polyhedron; + public: btPolyhedralConvexShape(); + virtual ~btPolyhedralConvexShape(); + + ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges) + virtual bool initializePolyhedralFeatures(); + + const btConvexPolyhedron* getConvexPolyhedron() const + { + return m_polyhedron; + } + //brute force implementations virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -95,4 +109,4 @@ public: }; -#endif //BU_SHAPE +#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h index 4ab28555ba8..ff86ef319e9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H -#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#ifndef BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" @@ -90,4 +90,4 @@ SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* data } -#endif //BVH_TRIANGLE_MESH_SHAPE_H +#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h index 07b3500f994..642a2887435 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h @@ -15,8 +15,8 @@ subject to the following restrictions: ///btShapeHull implemented by John McCutchan. -#ifndef _SHAPE_HULL_H -#define _SHAPE_HULL_H +#ifndef BT_SHAPE_HULL_H +#define BT_SHAPE_HULL_H #include "LinearMath/btAlignedObjectArray.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" @@ -56,4 +56,4 @@ public: } }; -#endif //_SHAPE_HULL_H +#endif //BT_SHAPE_HULL_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h index f98372442ba..b192efeeb8d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h @@ -12,8 +12,8 @@ subject to the following restrictions: 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SPHERE_MINKOWSKI_H -#define SPHERE_MINKOWSKI_H +#ifndef BT_SPHERE_MINKOWSKI_H +#define BT_SPHERE_MINKOWSKI_H #include "btConvexInternalShape.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types @@ -70,4 +70,4 @@ public: }; -#endif //SPHERE_MINKOWSKI_H +#endif //BT_SPHERE_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h index beb53ef33a1..b13825e610d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef STATIC_PLANE_SHAPE_H -#define STATIC_PLANE_SHAPE_H +#ifndef BT_STATIC_PLANE_SHAPE_H +#define BT_STATIC_PLANE_SHAPE_H #include "btConcaveShape.h" @@ -97,7 +97,7 @@ SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, bt } -#endif //STATIC_PLANE_SHAPE_H +#endif //BT_STATIC_PLANE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp index bc2f9f21448..dd22fc5635a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -253,9 +253,11 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s memPtr->m_indices16 = 0; memPtr->m_indices32 = 0; memPtr->m_3indices16 = 0; + memPtr->m_3indices8 = 0; memPtr->m_vertices3f = 0; memPtr->m_vertices3d = 0; + switch (gfxindextype) { case PHY_INTEGER: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h index 9e3e2ab0f59..f2b27ade8e8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef STRIDING_MESHINTERFACE_H -#define STRIDING_MESHINTERFACE_H +#ifndef BT_STRIDING_MESHINTERFACE_H +#define BT_STRIDING_MESHINTERFACE_H #include "LinearMath/btVector3.h" #include "btTriangleCallback.h" @@ -159,4 +159,4 @@ SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() co -#endif //STRIDING_MESHINTERFACE_H +#endif //BT_STRIDING_MESHINTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h index 72e9f232876..6b7128efc8e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BU_SIMPLEX_1TO4_SHAPE -#define BU_SIMPLEX_1TO4_SHAPE +#ifndef BT_SIMPLEX_1TO4_SHAPE +#define BT_SIMPLEX_1TO4_SHAPE #include "btPolyhedralConvexShape.h" @@ -71,4 +71,4 @@ public: }; -#endif //BU_SIMPLEX_1TO4_SHAPE +#endif //BT_SIMPLEX_1TO4_SHAPE diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h index 0499702b05b..461c57f8773 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef TRIANGLE_CALLBACK_H -#define TRIANGLE_CALLBACK_H +#ifndef BT_TRIANGLE_CALLBACK_H +#define BT_TRIANGLE_CALLBACK_H #include "LinearMath/btVector3.h" @@ -39,4 +39,4 @@ public: -#endif //TRIANGLE_CALLBACK_H +#endif //BT_TRIANGLE_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h index c64ea6e7043..9e1544e87a4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h @@ -29,9 +29,11 @@ ATTRIBUTE_ALIGNED16( struct) btIndexedMesh int m_numTriangles; const unsigned char * m_triangleIndexBase; + // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed) int m_triangleIndexStride; int m_numVertices; const unsigned char * m_vertexBase; + // Size of a vertex, in bytes int m_vertexStride; // The index type is set when adding an indexed mesh to the diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h index 282a7702e80..1cea7045f20 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h @@ -61,6 +61,7 @@ struct btTriangleInfoMap : public btInternalTriangleInfoMap btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared' btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge" + btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold) @@ -71,6 +72,7 @@ struct btTriangleInfoMap : public btInternalTriangleInfoMap m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001); m_edgeDistanceThreshold = btScalar(0.1); m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001); + m_maxEdgeAngleThreshold = SIMD_2_PI; } virtual ~btTriangleInfoMap() {} @@ -83,6 +85,7 @@ struct btTriangleInfoMap : public btInternalTriangleInfoMap }; +///those fields have to be float and not btScalar for the serialization to work properly struct btTriangleInfoData { int m_flags; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index d2624fe18e1..f623157fac1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef TRIANGLE_MESH_H -#define TRIANGLE_MESH_H +#ifndef BT_TRIANGLE_MESH_H +#define BT_TRIANGLE_MESH_H #include "btTriangleIndexVertexArray.h" #include "LinearMath/btVector3.h" @@ -65,5 +65,5 @@ class btTriangleMesh : public btTriangleIndexVertexArray }; -#endif //TRIANGLE_MESH_H +#endif //BT_TRIANGLE_MESH_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index 2216698d275..c8caf8fe696 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef TRIANGLE_MESH_SHAPE_H -#define TRIANGLE_MESH_SHAPE_H +#ifndef BT_TRIANGLE_MESH_SHAPE_H +#define BT_TRIANGLE_MESH_SHAPE_H #include "btConcaveShape.h" #include "btStridingMeshInterface.h" @@ -86,4 +86,4 @@ public: -#endif //TRIANGLE_MESH_SHAPE_H +#endif //BT_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h index 847147cf6b4..71b0557384e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef OBB_TRIANGLE_MINKOWSKI_H -#define OBB_TRIANGLE_MINKOWSKI_H +#ifndef BT_OBB_TRIANGLE_MINKOWSKI_H +#define BT_OBB_TRIANGLE_MINKOWSKI_H #include "btConvexShape.h" #include "btBoxShape.h" @@ -178,5 +178,5 @@ public: }; -#endif //OBB_TRIANGLE_MINKOWSKI_H +#endif //BT_OBB_TRIANGLE_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp index c3b697bdd1e..eed31d839f8 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp +++ b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp @@ -58,7 +58,7 @@ class CONTACT_KEY_TOKEN_COMP { public: - bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) + bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) const { return ( a < b ); } diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h index ae5d55ab7d9..6b6e07c983d 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h @@ -21,8 +21,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H -#define BVH_CONCAVE_COLLISION_ALGORITHM_H +#ifndef BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H +#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H #include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" @@ -303,4 +303,4 @@ public: -#endif //BVH_CONCAVE_COLLISION_ALGORITHM_H +#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h b/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h index e0487c22766..bd2633cfc59 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h @@ -1,5 +1,5 @@ -#ifndef BT_QUANTIZATION_H_INCLUDED -#define BT_QUANTIZATION_H_INCLUDED +#ifndef BT_GIMPACT_QUANTIZATION_H_INCLUDED +#define BT_GIMPACT_QUANTIZATION_H_INCLUDED /*! \file btQuantization.h *\author Francisco Leon Najera @@ -85,4 +85,4 @@ SIMD_FORCE_INLINE btVector3 bt_unquantize( -#endif // GIM_VECTOR_H_INCLUDED +#endif // BT_GIMPACT_QUANTIZATION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h index fcc981dfb69..973c2ed1277 100644 --- a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h +++ b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h @@ -22,8 +22,8 @@ subject to the following restrictions: */ -#ifndef TRIANGLE_SHAPE_EX_H -#define TRIANGLE_SHAPE_EX_H +#ifndef GIMPACT_TRIANGLE_SHAPE_EX_H +#define GIMPACT_TRIANGLE_SHAPE_EX_H #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionShapes/btTriangleShape.h" @@ -177,4 +177,4 @@ public: }; -#endif //TRIANGLE_MESH_SHAPE_H +#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp index 9ee83e7d561..91fcea57a3c 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -22,20 +22,72 @@ subject to the following restrictions: #include "btGjkPairDetector.h" #include "btPointCollector.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_simplexSolver(simplexSolver), m_penetrationDepthSolver(penetrationDepthSolver), -m_convexA(convexA),m_convexB(convexB) +m_convexA(convexA),m_convexB1(convexB),m_planeShape(0) { } + +btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape* convexA,const btStaticPlaneShape* plane) +:m_simplexSolver(0), +m_penetrationDepthSolver(0), +m_convexA(convexA),m_convexB1(0),m_planeShape(plane) +{ +} + + /// This maximum should not be necessary. It allows for untested/degenerate cases in production code. /// You don't want your game ever to lock-up. #define MAX_ITERATIONS 64 +void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector) +{ + if (m_convexB1) + { + m_simplexSolver->reset(); + btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = transA; + input.m_transformB = transB; + gjk.getClosestPoints(input,pointCollector,0); + } else + { + //convex versus plane + const btConvexShape* convexShape = m_convexA; + const btStaticPlaneShape* planeShape = m_planeShape; + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + + btTransform convexWorldTransform = transA; + btTransform convexInPlaneTrans; + convexInPlaneTrans= transB.inverse() * convexWorldTransform; + btTransform planeInConvex; + planeInConvex= convexWorldTransform.inverse() * transB; + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected; + btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal; + + pointCollector.addContactPoint( + normalOnSurfaceB, + vtxInPlaneWorld, + distance); + } +} + bool btContinuousConvexCollision::calcTimeOfImpact( const btTransform& fromA, const btTransform& toA, @@ -44,7 +96,6 @@ bool btContinuousConvexCollision::calcTimeOfImpact( CastResult& result) { - m_simplexSolver->reset(); /// compute linear and angular velocity for this interval, to interpolate btVector3 linVelA,angVelA,linVelB,angVelB; @@ -53,7 +104,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); - btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); + btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f; btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; btVector3 relLinVel = (linVelB-linVelA); @@ -64,7 +115,6 @@ bool btContinuousConvexCollision::calcTimeOfImpact( return false; - btScalar radius = btScalar(0.001); btScalar lambda = btScalar(0.); btVector3 v(1,0,0); @@ -83,28 +133,14 @@ bool btContinuousConvexCollision::calcTimeOfImpact( //first solution, using GJK - btTransform identityTrans; - identityTrans.setIdentity(); - - btSphereShape raySphere(btScalar(0.0)); - raySphere.setMargin(btScalar(0.)); - - + btScalar radius = 0.001f; // result.drawCoordSystem(sphereTr); btPointCollector pointCollector1; { - - btGjkPairDetector gjk(m_convexA,m_convexB,m_convexA->getShapeType(),m_convexB->getShapeType(),m_convexA->getMargin(),m_convexB->getMargin(),m_simplexSolver,m_penetrationDepthSolver); - btGjkPairDetector::ClosestPointInput input; - //we don't use margins during CCD - // gjk.setIgnoreMargin(true); - - input.m_transformA = fromA; - input.m_transformB = fromB; - gjk.getClosestPoints(input,pointCollector1,0); + computeClosestPoints(fromA,fromB,pointCollector1); hasResult = pointCollector1.m_hasResult; c = pointCollector1.m_pointInWorld; @@ -113,11 +149,12 @@ bool btContinuousConvexCollision::calcTimeOfImpact( if (hasResult) { btScalar dist; - dist = pointCollector1.m_distance; + dist = pointCollector1.m_distance + result.m_allowedPenetration; n = pointCollector1.m_normalOnBInWorld; - btScalar projectedLinearVelocity = relLinVel.dot(n); - + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) + return false; + //not close enough while (dist > radius) { @@ -125,19 +162,10 @@ bool btContinuousConvexCollision::calcTimeOfImpact( { result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1)); } - numIter++; - if (numIter > maxIter) - { - return false; //todo: report a failure - } btScalar dLambda = btScalar(0.); projectedLinearVelocity = relLinVel.dot(n); - //calculate safe moving fraction from distance / (linear+rotational velocity) - - //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); - //btScalar clippedDist = dist; //don't report time of impact for motion away from the contact normal (or causes minor penetration) if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) @@ -182,37 +210,27 @@ bool btContinuousConvexCollision::calcTimeOfImpact( result.DebugDraw( lambda ); btPointCollector pointCollector; - btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = interpolatedTransA; - input.m_transformB = interpolatedTransB; - gjk.getClosestPoints(input,pointCollector,0); + computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector); + if (pointCollector.m_hasResult) { - if (pointCollector.m_distance < btScalar(0.)) - { - //degenerate ?! - result.m_fraction = lastLambda; - n = pointCollector.m_normalOnBInWorld; - result.m_normal=n;//.setValue(1,1,1);// = n; - result.m_hitPoint = pointCollector.m_pointInWorld; - return true; - } + dist = pointCollector.m_distance+result.m_allowedPenetration; c = pointCollector.m_pointInWorld; n = pointCollector.m_normalOnBInWorld; - dist = pointCollector.m_distance; } else { - //?? + result.reportFailure(-1, numIter); return false; } - + numIter++; + if (numIter > maxIter) + { + result.reportFailure(-2, numIter); + return false; + } } - if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) - return false; - result.m_fraction = lambda; result.m_normal = n; result.m_hitPoint = c; @@ -221,16 +239,5 @@ bool btContinuousConvexCollision::calcTimeOfImpact( return false; -/* -//todo: - //if movement away from normal, discard result - btVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin(); - if (result.m_fraction < btScalar(1.)) - { - if (move.dot(result.m_normal) <= btScalar(0.)) - { - } - } -*/ - } + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h index 28c2b4d6156..bdc0572f75a 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -14,13 +14,14 @@ subject to the following restrictions: */ -#ifndef CONTINUOUS_COLLISION_CONVEX_CAST_H -#define CONTINUOUS_COLLISION_CONVEX_CAST_H +#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H +#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H #include "btConvexCast.h" #include "btSimplexSolverInterface.h" class btConvexPenetrationDepthSolver; class btConvexShape; +class btStaticPlaneShape; /// btContinuousConvexCollision implements angular and linear time of impact for convex objects. /// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). @@ -31,13 +32,18 @@ class btContinuousConvexCollision : public btConvexCast btSimplexSolverInterface* m_simplexSolver; btConvexPenetrationDepthSolver* m_penetrationDepthSolver; const btConvexShape* m_convexA; - const btConvexShape* m_convexB; + //second object is either a convex or a plane (code sharing) + const btConvexShape* m_convexB1; + const btStaticPlaneShape* m_planeShape; + void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector); public: btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane ); + virtual bool calcTimeOfImpact( const btTransform& fromA, const btTransform& toA, @@ -48,5 +54,6 @@ public: }; -#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H + +#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h index b0bce341e41..bfd79d03beb 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ -#ifndef CONVEX_CAST_H -#define CONVEX_CAST_H +#ifndef BT_CONVEX_CAST_H +#define BT_CONVEX_CAST_H #include "LinearMath/btTransform.h" #include "LinearMath/btVector3.h" @@ -39,7 +39,7 @@ public: virtual void DebugDraw(btScalar fraction) {(void)fraction;} virtual void drawCoordSystem(const btTransform& trans) {(void)trans;} - + virtual void reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;} CastResult() :m_fraction(btScalar(BT_LARGE_FLOAT)), m_debugDrawer(0), @@ -70,4 +70,4 @@ public: CastResult& result) = 0; }; -#endif //CONVEX_CAST_H +#endif //BT_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h index 7e3fde8e291..72eb5aec461 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ -#ifndef __CONVEX_PENETRATION_DEPTH_H -#define __CONVEX_PENETRATION_DEPTH_H +#ifndef BT_CONVEX_PENETRATION_DEPTH_H +#define BT_CONVEX_PENETRATION_DEPTH_H class btStackAlloc; class btVector3; @@ -38,5 +38,5 @@ public: }; -#endif //CONVEX_PENETRATION_DEPTH_H +#endif //BT_CONVEX_PENETRATION_DEPTH_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h index bc711ad495c..f958cc523ef 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -14,8 +14,9 @@ subject to the following restrictions: */ -#ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H +#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H +#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H + #include "LinearMath/btTransform.h" #include "LinearMath/btVector3.h" class btStackAlloc; @@ -86,4 +87,5 @@ struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result } }; -#endif //DISCRETE_COLLISION_DETECTOR_INTERFACE1_H +#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h index a977c9e83f7..6a42ee63b03 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -15,8 +15,8 @@ subject to the following restrictions: -#ifndef GJK_CONVEX_CAST_H -#define GJK_CONVEX_CAST_H +#ifndef BT_GJK_CONVEX_CAST_H +#define BT_GJK_CONVEX_CAST_H #include "BulletCollision/CollisionShapes/btCollisionMargin.h" @@ -47,4 +47,4 @@ public: }; -#endif //GJK_CONVEX_CAST_H +#endif //BT_GJK_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp index f74261d4b21..3268f06c2f9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -511,7 +511,6 @@ namespace gjkepa2_impl { btVector3 n; btScalar d; - btScalar p; sSV* c[3]; sFace* f[3]; sFace* l[2]; @@ -657,7 +656,7 @@ namespace gjkepa2_impl remove(m_hull,best); append(m_stock,best); best=findbest(); - if(best->p>=outer.p) outer=*best; + outer=*best; } else { m_status=eStatus::InvalidHull;break; } } else { m_status=eStatus::AccuraryReached;break; } } else { m_status=eStatus::OutOfVertices;break; } @@ -696,6 +695,42 @@ namespace gjkepa2_impl m_result.p[0]=1; return(m_status); } + bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist) + { + const btVector3 ba = b->w - a->w; + const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane + const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required + + if(a_dot_nab < 0) + { + // Outside of edge a->b + + const btScalar ba_l2 = ba.length2(); + const btScalar a_dot_ba = btDot(a->w, ba); + const btScalar b_dot_ba = btDot(b->w, ba); + + if(a_dot_ba > 0) + { + // Pick distance vertex a + dist = a->w.length(); + } + else if(b_dot_ba < 0) + { + // Pick distance vertex b + dist = b->w.length(); + } + else + { + // Pick distance to edge a->b + const btScalar a_dot_b = btDot(a->w, b->w); + dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0)); + } + + return true; + } + + return false; + } sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) { if(m_stock.root) @@ -710,41 +745,48 @@ namespace gjkepa2_impl face->n = btCross(b->w-a->w,c->w-a->w); const btScalar l=face->n.length(); const bool v=l>EPA_ACCURACY; - face->p = btMin(btMin( - btDot(a->w,btCross(face->n,a->w-b->w)), - btDot(b->w,btCross(face->n,b->w-c->w))), - btDot(c->w,btCross(face->n,c->w-a->w))) / - (v?l:1); - face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; + if(v) { - face->d = btDot(a->w,face->n)/l; - face->n /= l; - if(forced||(face->d>=-EPA_PLANE_EPS)) + if(!(getedgedist(face, a, b, face->d) || + getedgedist(face, b, c, face->d) || + getedgedist(face, c, a, face->d))) + { + // Origin projects to the interior of the triangle + // Use distance to triangle plane + face->d = btDot(a->w, face->n) / l; + } + + face->n /= l; + if(forced || (face->d >= -EPA_PLANE_EPS)) { - return(face); - } else m_status=eStatus::NonConvex; - } else m_status=eStatus::Degenerated; - remove(m_hull,face); - append(m_stock,face); - return(0); + return face; + } + else + m_status=eStatus::NonConvex; + } + else + m_status=eStatus::Degenerated; + + remove(m_hull, face); + append(m_stock, face); + return 0; + } - m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; - return(0); + m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces; + return 0; } sFace* findbest() { sFace* minf=m_hull.root; btScalar mind=minf->d*minf->d; - btScalar maxp=minf->p; for(sFace* f=minf->l[1];f;f=f->l[1]) { const btScalar sqd=f->d*f->d; - if((f->p>=maxp)&&(sqdp; } } return(minf); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h index 2296527d7db..ac501d5ecfe 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h @@ -22,8 +22,9 @@ misrepresented as being the original software. /* GJK-EPA collision solver by Nathanael Presson, 2008 */ -#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ -#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ +#ifndef BT_GJK_EPA2_H +#define BT_GJK_EPA2_H + #include "BulletCollision/CollisionShapes/btConvexShape.h" ///btGjkEpaSolver contributed under zlib by Nathanael Presson @@ -70,4 +71,5 @@ static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs }; -#endif +#endif //BT_GJK_EPA2_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h index cc6287c86b0..2277a19d981 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h @@ -16,8 +16,8 @@ subject to the following restrictions: -#ifndef GJK_PAIR_DETECTOR_H -#define GJK_PAIR_DETECTOR_H +#ifndef BT_GJK_PAIR_DETECTOR_H +#define BT_GJK_PAIR_DETECTOR_H #include "btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" @@ -100,4 +100,4 @@ public: }; -#endif //GJK_PAIR_DETECTOR_H +#endif //BT_GJK_PAIR_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h index cd310570e06..0ce9dd25926 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -13,14 +13,14 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MANIFOLD_CONTACT_POINT_H -#define MANIFOLD_CONTACT_POINT_H +#ifndef BT_MANIFOLD_CONTACT_POINT_H +#define BT_MANIFOLD_CONTACT_POINT_H #include "LinearMath/btVector3.h" #include "LinearMath/btTransformUtil.h" #ifdef PFX_USE_FREE_VECTORMATH - #include "physics_effects\base_level\solver\pfx_constraint_row.h" + #include "physics_effects/base_level/solver/pfx_constraint_row.h" typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow; #else // Don't change following order of parameters @@ -155,4 +155,4 @@ class btManifoldPoint }; -#endif //MANIFOLD_CONTACT_POINT_H +#endif //BT_MANIFOLD_CONTACT_POINT_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h index 7b6c8a63779..6a8fe52f36f 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H -#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#ifndef BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H #include "btConvexPenetrationDepthSolver.h" @@ -36,5 +36,5 @@ public: ); }; -#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp index 924a8af87d1..954b8395299 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp @@ -21,7 +21,9 @@ subject to the following restrictions: btScalar gContactBreakingThreshold = btScalar(0.02); ContactDestroyedCallback gContactDestroyedCallback = 0; ContactProcessedCallback gContactProcessedCallback = 0; - +///gContactCalcArea3Points will approximate the convex hull area using 3 points +///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower +bool gContactCalcArea3Points = true; btPersistentManifold::btPersistentManifold() @@ -84,10 +86,28 @@ void btPersistentManifold::clearUserCache(btManifoldPoint& pt) } +static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3) +{ + // It calculates possible 3 area constructed from random 4 points and returns the biggest one. + + btVector3 a[3],b[3]; + a[0] = p0 - p1; + a[1] = p0 - p2; + a[2] = p0 - p3; + b[0] = p2 - p3; + b[1] = p1 - p3; + b[2] = p1 - p2; + + //todo: Following 3 cross production can be easily optimized by SIMD. + btVector3 tmp0 = a[0].cross(b[0]); + btVector3 tmp1 = a[1].cross(b[1]); + btVector3 tmp2 = a[2].cross(b[2]); + + return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2()); +} int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) { - //calculate 4 possible cases areas, and take biggest area //also need to keep 'deepest' @@ -106,6 +126,9 @@ int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) #endif //KEEP_DEEPEST_POINT btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.)); + + if (gContactCalcArea3Points) + { if (maxPenetrationIndex != 0) { btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA; @@ -136,10 +159,29 @@ int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) btVector3 cross = a3.cross(b3); res3 = cross.length2(); } + } + else + { + if(maxPenetrationIndex != 0) { + res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA); + } - btVector4 maxvec(res0,res1,res2,res3); - int biggestarea = maxvec.closestAxis4(); - return biggestarea; + if(maxPenetrationIndex != 1) { + res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 2) { + res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA); + } + + if(maxPenetrationIndex != 3) { + res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA); + } + } + btVector4 maxvec(res0,res1,res2,res3); + int biggestarea = maxvec.closestAxis4(); + return biggestarea; + } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index c8aac637307..d877f09944f 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef PERSISTENT_MANIFOLD_H -#define PERSISTENT_MANIFOLD_H +#ifndef BT_PERSISTENT_MANIFOLD_H +#define BT_PERSISTENT_MANIFOLD_H #include "LinearMath/btVector3.h" @@ -197,14 +197,10 @@ public: #endif } + bool validContactDistance(const btManifoldPoint& pt) const { - if (pt.m_lifeTime >1) - { - return pt.m_distance1 <= getContactBreakingThreshold(); - } - return pt.m_distance1 <= getContactProcessingThreshold(); - + return pt.m_distance1 <= getContactBreakingThreshold(); } /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin void refreshContactPoints( const btTransform& trA,const btTransform& trB); @@ -229,4 +225,4 @@ public: -#endif //PERSISTENT_MANIFOLD_H +#endif //BT_PERSISTENT_MANIFOLD_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h index 6ca60548e71..18da171011a 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef POINT_COLLECTOR_H -#define POINT_COLLECTOR_H +#ifndef BT_POINT_COLLECTOR_H +#define BT_POINT_COLLECTOR_H #include "btDiscreteCollisionDetectorInterface.h" @@ -60,5 +60,5 @@ struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result } }; -#endif //POINT_COLLECTOR_H +#endif //BT_POINT_COLLECTOR_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp new file mode 100644 index 00000000000..db1909113b3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp @@ -0,0 +1,440 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +///This file was written by Erwin Coumans +///Separating axis rest based on work from Pierre Terdiman, see +///And contact clipping based on work from Simon Hobbs + + +#include "btPolyhedralContactClipping.h" +#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h" + +#include //for FLT_MAX + +int gExpectedNbTests=0; +int gActualNbTests = 0; +bool gUseInternalObject = true; + +// Clips a face to the back of a plane +void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS) +{ + + int ve; + btScalar ds, de; + int numVerts = pVtxIn.size(); + if (numVerts < 2) + return; + + btVector3 firstVertex=pVtxIn[pVtxIn.size()-1]; + btVector3 endVertex = pVtxIn[0]; + + ds = planeNormalWS.dot(firstVertex)+planeEqWS; + + for (ve = 0; ve < numVerts; ve++) + { + endVertex=pVtxIn[ve]; + + de = planeNormalWS.dot(endVertex)+planeEqWS; + + if (ds<0) + { + if (de<0) + { + // Start < 0, end < 0, so output endVertex + ppVtxOut.push_back(endVertex); + } + else + { + // Start < 0, end >= 0, so output intersection + ppVtxOut.push_back( firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de)))); + } + } + else + { + if (de<0) + { + // Start >= 0, end < 0 so output intersection and end + ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de)))); + ppVtxOut.push_back(endVertex); + } + } + firstVertex = endVertex; + ds = de; + } +} + + +static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth) +{ + btScalar Min0,Max0; + btScalar Min1,Max1; + hullA.project(transA,sep_axis, Min0, Max0); + hullB.project(transB, sep_axis, Min1, Max1); + + if(Max0=0.0f); + btScalar d1 = Max1 - Min0; + assert(d1>=0.0f); + depth = d01e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6) return false; + return true; +} + +#ifdef TEST_INTERNAL_OBJECTS + +inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3]) +{ + // This version is ~11.000 cycles (4%) faster overall in one of the tests. +// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK); +// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK); +// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK); + p[0] = sv[0] < 0.0f ? -extents[0] : extents[0]; + p[1] = sv[1] < 0.0f ? -extents[1] : extents[1]; + p[2] = sv[2] < 0.0f ? -extents[2] : extents[2]; +} + +void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr) +{ + const btMatrix3x3& rot = tr.getBasis(); + const btVector3& r0 = rot[0]; + const btVector3& r1 = rot[1]; + const btVector3& r2 = rot[2]; + + const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z(); + const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z(); + const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z(); + + out.setValue(x, y, z); +} + + bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin) +{ + const btScalar dp = delta_c.dot(axis); + + btVector3 localAxis0; + InverseTransformPoint3x3(localAxis0, axis,trans0); + btVector3 localAxis1; + InverseTransformPoint3x3(localAxis1, axis,trans1); + + btScalar p0[3]; + BoxSupport(convex0.m_extents, localAxis0, p0); + btScalar p1[3]; + BoxSupport(convex1.m_extents, localAxis1, p1); + + const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z(); + const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z(); + + const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius; + const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius; + + const btScalar MinMaxRadius = MaxRadius + MinRadius; + const btScalar d0 = MinMaxRadius + dp; + const btScalar d1 = MinMaxRadius - dp; + + const btScalar depth = d0dmin) + return false; + return true; +} +#endif //TEST_INTERNAL_OBJECTS + + +bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep) +{ + gActualSATPairTests++; + +//#ifdef TEST_INTERNAL_OBJECTS + const btVector3 c0 = transA * hullA.m_localCenter; + const btVector3 c1 = transB * hullB.m_localCenter; + const btVector3 DeltaC2 = c0 - c1; +//#endif + + btScalar dmin = FLT_MAX; + int curPlaneTests=0; + + int numFacesA = hullA.m_faces.size(); + // Test normals from hullA + for(int i=0;i0.0f) + sep = -sep; + + return true; +} + +void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut) +{ + btVertexArray worldVertsB2; + btVertexArray* pVtxIn = &worldVertsB1; + btVertexArray* pVtxOut = &worldVertsB2; + pVtxOut->reserve(pVtxIn->size()); + + int closestFaceA=-1; + { + btScalar dmin = FLT_MAX; + for(int face=0;facesize(); + int numVerticesA = polyA.m_indices.size(); + for(int e0=0;e0resize(0); + } + + + +//#define ONLY_REPORT_DEEPEST_POINT + + btVector3 point; + + + // only keep points that are behind the witness face + { + btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]); + btScalar localPlaneEq = polyA.m_plane[3]; + btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal; + btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin()); + for (int i=0;isize();i++) + { + + btScalar depth = planeNormalWS.dot(pVtxIn->at(i))+planeEqWS; + if (depth <=minDist) + { +// printf("clamped: depth=%f to minDist=%f\n",depth,minDist); + depth = minDist; + } + + if (depth <=maxDist) + { + btVector3 point = pVtxIn->at(i); +#ifdef ONLY_REPORT_DEEPEST_POINT + curMaxDist = depth; +#else +#if 0 + if (depth<-3) + { + printf("error in btPolyhedralContactClipping depth = %f\n", depth); + printf("likely wrong separatingNormal passed in\n"); + } +#endif + resultOut.addContactPoint(separatingNormal,point,depth); +#endif + } + } + } +#ifdef ONLY_REPORT_DEEPEST_POINT + if (curMaxDist dmax) + { + dmax = d; + closestFaceB = face; + } + } + } + btVertexArray worldVertsB1; + { + const btFace& polyB = hullB.m_faces[closestFaceB]; + const int numVertices = polyB.m_indices.size(); + for(int e0=0;e0=0) + clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut); + +} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h new file mode 100644 index 00000000000..99103df2027 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +///This file was written by Erwin Coumans + + +#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H +#define BT_POLYHEDRAL_CONTACT_CLIPPING_H + + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btTransform.h" +#include "btDiscreteCollisionDetectorInterface.h" + +class btConvexPolyhedron; + +typedef btAlignedObjectArray btVertexArray; + +// Clips a face to the back of a plane +struct btPolyhedralContactClipping +{ + static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut); + static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut); + + static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep); + + ///the clipFace method is used internally + static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS); + +}; + +#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h index bdd1add36d2..f012889a70e 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef RAYCAST_TRI_CALLBACK_H -#define RAYCAST_TRI_CALLBACK_H +#ifndef BT_RAYCAST_TRI_CALLBACK_H +#define BT_RAYCAST_TRI_CALLBACK_H #include "BulletCollision/CollisionShapes/btTriangleCallback.h" #include "LinearMath/btTransform.h" @@ -68,5 +68,5 @@ public: virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0; }; -#endif //RAYCAST_TRI_CALLBACK_H +#endif //BT_RAYCAST_TRI_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h index 823b4e7158b..da8a13914c9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -15,8 +15,8 @@ subject to the following restrictions: -#ifndef SIMPLEX_SOLVER_INTERFACE_H -#define SIMPLEX_SOLVER_INTERFACE_H +#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H +#define BT_SIMPLEX_SOLVER_INTERFACE_H #include "LinearMath/btVector3.h" @@ -59,5 +59,5 @@ class btSimplexSolverInterface }; #endif -#endif //SIMPLEX_SOLVER_INTERFACE_H +#endif //BT_SIMPLEX_SOLVER_INTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h index 05662db5d23..6c8127983eb 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ -#ifndef SUBSIMPLEX_CONVEX_CAST_H -#define SUBSIMPLEX_CONVEX_CAST_H +#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H +#define BT_SUBSIMPLEX_CONVEX_CAST_H #include "btConvexCast.h" #include "btSimplexSolverInterface.h" @@ -47,4 +47,4 @@ public: }; -#endif //SUBSIMPLEX_CONVEX_CAST_H +#endif //BT_SUBSIMPLEX_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h index 9a4f552924c..f1c7613efa1 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h @@ -15,8 +15,8 @@ subject to the following restrictions: -#ifndef btVoronoiSimplexSolver_H -#define btVoronoiSimplexSolver_H +#ifndef BT_VORONOI_SIMPLEX_SOLVER_H +#define BT_VORONOI_SIMPLEX_SOLVER_H #include "btSimplexSolverInterface.h" @@ -175,4 +175,5 @@ public: }; -#endif //VoronoiSimplexSolver +#endif //BT_VORONOI_SIMPLEX_SOLVER_H + diff --git a/extern/bullet2/src/BulletDynamics/Character/btCharacterControllerInterface.h b/extern/bullet2/src/BulletDynamics/Character/btCharacterControllerInterface.h index 19373daa241..c81813c92be 100644 --- a/extern/bullet2/src/BulletDynamics/Character/btCharacterControllerInterface.h +++ b/extern/bullet2/src/BulletDynamics/Character/btCharacterControllerInterface.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CHARACTER_CONTROLLER_INTERFACE_H -#define CHARACTER_CONTROLLER_INTERFACE_H +#ifndef BT_CHARACTER_CONTROLLER_INTERFACE_H +#define BT_CHARACTER_CONTROLLER_INTERFACE_H #include "LinearMath/btVector3.h" #include "BulletDynamics/Dynamics/btActionInterface.h" @@ -42,4 +42,5 @@ public: virtual bool onGround () const = 0; }; -#endif +#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H + diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h index 704355c0ae1..ef01f8a3e60 100644 --- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h +++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ -#ifndef KINEMATIC_CHARACTER_CONTROLLER_H -#define KINEMATIC_CHARACTER_CONTROLLER_H +#ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H +#define BT_KINEMATIC_CHARACTER_CONTROLLER_H #include "LinearMath/btVector3.h" @@ -25,6 +25,7 @@ subject to the following restrictions: class btCollisionShape; +class btConvexShape; class btRigidBody; class btCollisionWorld; class btCollisionDispatcher; @@ -159,4 +160,4 @@ public: bool onGround () const; }; -#endif // KINEMATIC_CHARACTER_CONTROLLER_H +#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index bc371e4062d..755544f0dee 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -638,6 +638,11 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr btTransform trDeltaAB = trB * trPose * trA.inverse(); btQuaternion qDeltaAB = trDeltaAB.getRotation(); btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z()); + float swingAxisLen2 = swingAxis.length2(); + if(btFuzzyZero(swingAxisLen2)) + { + return; + } m_swingAxis = swingAxis; m_swingAxis.normalize(); m_swingCorrection = qDeltaAB.getAngle(); @@ -918,7 +923,7 @@ void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. { - qMinTwist = operator-(qTwist); + qMinTwist = -(qTwist); twistAngle = qMinTwist.getAngle(); } if (twistAngle < 0) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index c1c5aa851b6..868e62f063e 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -33,8 +33,8 @@ and swing 1 and 2 are along the z and y axes respectively. -#ifndef CONETWISTCONSTRAINT_H -#define CONETWISTCONSTRAINT_H +#ifndef BT_CONETWISTCONSTRAINT_H +#define BT_CONETWISTCONSTRAINT_H #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" @@ -343,4 +343,4 @@ SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, } -#endif //CONETWISTCONSTRAINT_H +#endif //BT_CONETWISTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h index 7a8e9c1953d..6f673102be2 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONSTRAINT_SOLVER_H -#define CONSTRAINT_SOLVER_H +#ifndef BT_CONSTRAINT_SOLVER_H +#define BT_CONSTRAINT_SOLVER_H #include "LinearMath/btScalar.h" @@ -49,4 +49,4 @@ public: -#endif //CONSTRAINT_SOLVER_H +#endif //BT_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index d97096d9f26..88859182925 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -68,9 +68,53 @@ void btContactConstraint::buildJacobian() #include "LinearMath/btMinMax.h" #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" -#define ASSERT2 btAssert -#define USE_INTERNAL_APPLY_IMPULSE 1 + +//response between two dynamic objects without friction, assuming 0 penetration depth +btScalar resolveSingleCollision( + btRigidBody* body1, + btCollisionObject* colObj2, + const btVector3& contactPositionWorld, + const btVector3& contactNormalOnB, + const btContactSolverInfo& solverInfo, + btScalar distance) +{ + btRigidBody* body2 = btRigidBody::upcast(colObj2); + + + const btVector3& normal = contactNormalOnB; + + btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin(); + btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin(); + + btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btScalar combinedRestitution = body1->getRestitution() * colObj2->getRestitution(); + btScalar restitution = combinedRestitution* -rel_vel; + + btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ; + btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping; + btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal); + btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f; + btScalar relaxation = 1.f; + btScalar jacDiagABInv = relaxation/(denom0+denom1); + + btScalar penetrationImpulse = positionalError * jacDiagABInv; + btScalar velocityImpulse = velocityError * jacDiagABInv; + + btScalar normalImpulse = penetrationImpulse+velocityImpulse; + normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse; + + body1->applyImpulse(normal*(normalImpulse), rel_pos1); + if (body2) + body2->applyImpulse(-normal*(normalImpulse), rel_pos2); + + return normalImpulse; +} //bilateral constraint between two dynamic objects @@ -83,7 +127,7 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, btScalar normalLenSqr = normal.length2(); - ASSERT2(btFabs(normalLenSqr) < btScalar(1.1)); + btAssert(btFabs(normalLenSqr) < btScalar(1.1)); if (normalLenSqr > btScalar(1.1)) { impulse = btScalar(0.); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index 63c1a417bc1..477c79d1756 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONTACT_CONSTRAINT_H -#define CONTACT_CONSTRAINT_H +#ifndef BT_CONTACT_CONSTRAINT_H +#define BT_CONTACT_CONSTRAINT_H #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" @@ -57,6 +57,9 @@ public: }; +///very basic collision resolution without friction +btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance); + ///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, @@ -65,4 +68,4 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, -#endif //CONTACT_CONSTRAINT_H +#endif //BT_CONTACT_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index db5bb5e4c51..6204cb3d16c 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef CONTACT_SOLVER_INFO -#define CONTACT_SOLVER_INFO +#ifndef BT_CONTACT_SOLVER_INFO +#define BT_CONTACT_SOLVER_INFO enum btSolverMode { @@ -84,4 +84,4 @@ struct btContactSolverInfo : public btContactSolverInfoData } }; -#endif //CONTACT_SOLVER_INFO +#endif //BT_CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index 7c5e4f6e7b2..8ff9940bba3 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -130,12 +130,20 @@ int btRotationalLimitMotor::testLimitValue(btScalar test_value) { m_currentLimit = 1;//low limit violation m_currentLimitError = test_value - m_loLimit; + if(m_currentLimitError>SIMD_PI) + m_currentLimitError-=SIMD_2_PI; + else if(m_currentLimitError<-SIMD_PI) + m_currentLimitError+=SIMD_2_PI; return 1; } else if (test_value> m_hiLimit) { m_currentLimit = 2;//High limit violation m_currentLimitError = test_value - m_hiLimit; + if(m_currentLimitError>SIMD_PI) + m_currentLimitError-=SIMD_2_PI; + else if(m_currentLimitError<-SIMD_PI) + m_currentLimitError+=SIMD_2_PI; return 2; }; @@ -1067,4 +1075,4 @@ void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& ax m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; calculateTransforms(); -} \ No newline at end of file +} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index ab745ca5ad6..a8e7bc22902 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -24,8 +24,8 @@ http://gimpact.sf.net */ -#ifndef GENERIC_6DOF_CONSTRAINT_H -#define GENERIC_6DOF_CONSTRAINT_H +#ifndef BT_GENERIC_6DOF_CONSTRAINT_H +#define BT_GENERIC_6DOF_CONSTRAINT_H #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" @@ -611,4 +611,4 @@ SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffe -#endif //GENERIC_6DOF_CONSTRAINT_H +#endif //BT_GENERIC_6DOF_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp index d3503456625..2b38714987b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp @@ -20,6 +20,19 @@ subject to the following restrictions: btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA) +{ + init(); +} + + +btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) + : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB) +{ + init(); +} + + +void btGeneric6DofSpringConstraint::init() { m_objectType = D6_SPRING_CONSTRAINT_TYPE; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h index 16ff973e427..31e0cd531ae 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef GENERIC_6DOF_SPRING_CONSTRAINT_H -#define GENERIC_6DOF_SPRING_CONSTRAINT_H +#ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H +#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H #include "LinearMath/btVector3.h" @@ -39,9 +39,11 @@ protected: btScalar m_equilibriumPoint[6]; btScalar m_springStiffness[6]; btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping) + void init(); void internalUpdateSprings(btConstraintInfo2* info); public: btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); void enableSpring(int index, bool onOff); void setStiffness(int index, btScalar stiffness); void setDamping(int index, btScalar damping); @@ -93,5 +95,5 @@ SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dat return "btGeneric6DofConstraintData"; } -#endif // GENERIC_6DOF_SPRING_CONSTRAINT_H +#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h index 15fd4a014cc..a76452ddb64 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef HINGE2_CONSTRAINT_H -#define HINGE2_CONSTRAINT_H +#ifndef BT_HINGE2_CONSTRAINT_H +#define BT_HINGE2_CONSTRAINT_H @@ -54,5 +54,5 @@ public: -#endif // HINGE2_CONSTRAINT_H +#endif // BT_HINGE2_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index 144beef1cd6..9e3a2baeed9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -37,15 +37,15 @@ subject to the following restrictions: btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA) :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), +#ifdef _BT_USE_CENTER_LIMIT_ + m_limit(), +#endif m_angularOnly(false), m_enableAngularMotor(false), m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), m_useReferenceFrameA(useReferenceFrameA), m_flags(0) -#ifdef _BT_USE_CENTER_LIMIT_ - ,m_limit() -#endif { m_rbAFrame.getOrigin() = pivotInA; @@ -93,14 +93,15 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const bt btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false), +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif +m_angularOnly(false), m_enableAngularMotor(false), m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), m_useReferenceFrameA(useReferenceFrameA), m_flags(0) -#ifdef _BT_USE_CENTER_LIMIT_ -,m_limit() -#endif { // since no frame is given, assume this to be zero angle and just pick rb transform axis @@ -142,15 +143,15 @@ m_flags(0) btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif m_angularOnly(false), m_enableAngularMotor(false), m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), m_useReferenceFrameA(useReferenceFrameA), m_flags(0) -#ifdef _BT_USE_CENTER_LIMIT_ -,m_limit() -#endif { #ifndef _BT_USE_CENTER_LIMIT_ //start with free @@ -168,15 +169,15 @@ m_flags(0) btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), +#ifdef _BT_USE_CENTER_LIMIT_ +m_limit(), +#endif m_angularOnly(false), m_enableAngularMotor(false), m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), m_useReferenceFrameA(useReferenceFrameA), m_flags(0) -#ifdef _BT_USE_CENTER_LIMIT_ -,m_limit() -#endif { ///not providing rigidbody B means implicitly using worldspace for body B @@ -663,7 +664,7 @@ void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt) btScalar targetAngle = qHinge.getAngle(); if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate. { - qHinge = operator-(qHinge); + qHinge = -(qHinge); targetAngle = qHinge.getAngle(); } if (qHinge.getZ() < 0) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 50e3f73cb6d..cb2973e1d1d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -15,8 +15,9 @@ subject to the following restrictions: /* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ -#ifndef HINGECONSTRAINT_H -#define HINGECONSTRAINT_H +#ifndef BT_HINGECONSTRAINT_H +#define BT_HINGECONSTRAINT_H + #define _BT_USE_CENTER_LIMIT_ 1 @@ -377,4 +378,4 @@ SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btS return btHingeConstraintDataName; } -#endif //HINGECONSTRAINT_H +#endif //BT_HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h index 22a8af66b8e..f1994a2dfd8 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef JACOBIAN_ENTRY_H -#define JACOBIAN_ENTRY_H +#ifndef BT_JACOBIAN_ENTRY_H +#define BT_JACOBIAN_ENTRY_H #include "LinearMath/btVector3.h" #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -153,4 +153,4 @@ public: }; -#endif //JACOBIAN_ENTRY_H +#endif //BT_JACOBIAN_ENTRY_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index b589ee68254..b3bda03eec1 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef POINT2POINTCONSTRAINT_H -#define POINT2POINTCONSTRAINT_H +#ifndef BT_POINT2POINTCONSTRAINT_H +#define BT_POINT2POINTCONSTRAINT_H #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" @@ -158,4 +158,4 @@ SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffe return btPoint2PointConstraintDataName; } -#endif //POINT2POINTCONSTRAINT_H +#endif //BT_POINT2POINTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 0fc93cd3756..ab074224028 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -225,7 +225,7 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); - c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); + c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128); __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128); __m128 impulseMagnitude = deltaImpulse; @@ -740,13 +740,13 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m } } - btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { BT_PROFILE("solveGroupCacheFriendlySetup"); (void)stackAlloc; (void)debugDrawer; + m_maxOverrideNumSolverIterations = 0; if (!(numConstraints + numManifolds)) { @@ -788,6 +788,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol { btTypedConstraint* constraint = constraints[j]; constraint->buildJacobian(); + constraint->internalSetAppliedImpulse(0.0f); } } //btRigidBody* rb0=0,*rb1=0; @@ -804,7 +805,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol for (i=0;igetInfo1(&info1); + if (constraints[i]->isEnabled()) + { + constraints[i]->getInfo1(&info1); + } else + { + info1.m_numConstraintRows = 0; + info1.nub = 0; + } totalNumRows += info1.m_numConstraintRows; } m_tmpSolverNonContactConstraintPool.resize(totalNumRows); @@ -823,23 +831,26 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow]; btTypedConstraint* constraint = constraints[i]; + btRigidBody& rbA = constraint->getRigidBodyA(); + btRigidBody& rbB = constraint->getRigidBodyB(); + int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations; + if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations) + m_maxOverrideNumSolverIterations = overrideNumSolverIterations; - btRigidBody& rbA = constraint->getRigidBodyA(); - btRigidBody& rbB = constraint->getRigidBodyB(); - int j; for ( j=0;j=constraints[i]->getBreakingImpulseThreshold()) + { + solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold(); + } + + if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold()) + { + solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold(); + } + solverConstraint.m_originalContactPoint = constraint; { @@ -939,15 +961,20 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol btContactSolverInfo info = infoGlobal; - + int numNonContactPool = m_tmpSolverNonContactConstraintPool.size(); int numConstraintPool = m_tmpSolverContactConstraintPool.size(); int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size(); ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints + m_orderNonContactConstraintPool.resize(numNonContactPool); m_orderTmpConstraintPool.resize(numConstraintPool); m_orderFrictionConstraintPool.resize(numFrictionPool); { int i; + for (i=0;isolveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); - } - - ///solve all contact constraints using SIMD, if available - int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - for (j=0;jsolveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + } - } - ///solve all friction constraints, using SIMD, if available - int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); - for (j=0;jbtScalar(0)) + } + + ///solve all friction constraints, using SIMD, if available + int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); + for (j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - resolveSingleConstraintRowGenericSIMD(*solveManifold.m_solverBodyA, *solveManifold.m_solverBodyB,solveManifold); + resolveSingleConstraintRowGenericSIMD(*solveManifold.m_solverBodyA, *solveManifold.m_solverBodyB,solveManifold); + } } } } else @@ -1032,34 +1076,38 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration ///solve all joint constraints for (j=0;jsolveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); - } - ///solve all contact constraints - int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - for (j=0;jbtScalar(0)) + for (j=0;jsolveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + } + ///solve all contact constraints + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + for (j=0;jbtScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + + resolveSingleConstraintRowGeneric(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold); + } } } } @@ -1111,16 +1159,18 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations( { BT_PROFILE("solveGroupCacheFriendlyIterations"); - - //should traverse the contacts random order... - int iteration; { - for ( iteration = 0;iteration infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations; + + for ( int iteration = 0 ; iteration< maxIterations ; iteration++) + //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--) { solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc); } - solveGroupCacheFriendlySplitImpulseIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc); } return 0.f; } @@ -1151,9 +1201,11 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCo { const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j]; btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint; - btScalar sum = constr->internalGetAppliedImpulse(); - sum += solverConstr.m_appliedImpulse; - constr->internalSetAppliedImpulse(sum); + constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse); + if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold()) + { + constr->setEnabled(false); + } } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index f268ec9ae74..bb377db8db9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H -#define SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H +#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H +#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H #include "btConstraintSolver.h" class btIDebugDraw; @@ -33,8 +33,10 @@ protected: btConstraintArray m_tmpSolverNonContactConstraintPool; btConstraintArray m_tmpSolverContactFrictionConstraintPool; btAlignedObjectArray m_orderTmpConstraintPool; + btAlignedObjectArray m_orderNonContactConstraintPool; btAlignedObjectArray m_orderFrictionConstraintPool; btAlignedObjectArray m_tmpConstraintSizesPool; + int m_maxOverrideNumSolverIterations; void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyIdB, btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, @@ -124,5 +126,5 @@ typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverP #endif -#endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H +#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h index e9723a7bb40..2edc8d2b2e1 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -22,8 +22,8 @@ TODO: - add conversion for ODE constraint solver */ -#ifndef SLIDER_CONSTRAINT_H -#define SLIDER_CONSTRAINT_H +#ifndef BT_SLIDER_CONSTRAINT_H +#define BT_SLIDER_CONSTRAINT_H @@ -236,7 +236,10 @@ public: btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } - btScalar getLinearPos() { return m_linPos; } + + btScalar getLinearPos() const { return m_linPos; } + btScalar getAngularPos() const { return m_angPos; } + // access for ODE solver @@ -326,5 +329,5 @@ SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, bt -#endif //SLIDER_CONSTRAINT_H +#endif //BT_SLIDER_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h index 057d3fac827..e8bfabf864e 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SOLVE_2LINEAR_CONSTRAINT_H -#define SOLVE_2LINEAR_CONSTRAINT_H +#ifndef BT_SOLVE_2LINEAR_CONSTRAINT_H +#define BT_SOLVE_2LINEAR_CONSTRAINT_H #include "LinearMath/btMatrix3x3.h" #include "LinearMath/btVector3.h" @@ -104,4 +104,4 @@ public: }; -#endif //SOLVE_2LINEAR_CONSTRAINT_H +#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h index 79e45a4383b..179e79d7911 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -51,6 +51,8 @@ ATTRIBUTE_ALIGNED64 (struct) btSolverConstraint btScalar m_unusedPadding0; }; + int m_overrideNumSolverIterations; + union { int m_frictionIndex; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp index 8212c36ff4e..06bde5e7eec 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -25,7 +25,10 @@ btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rb :btTypedObject(type), m_userConstraintType(-1), m_userConstraintId(-1), +m_breakingImpulseThreshold(SIMD_INFINITY), +m_isEnabled(true), m_needsFeedback(false), +m_overrideNumSolverIterations(-1), m_rbA(rbA), m_rbB(getFixedBody()), m_appliedImpulse(btScalar(0.)), @@ -38,7 +41,10 @@ btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rb :btTypedObject(type), m_userConstraintType(-1), m_userConstraintId(-1), +m_breakingImpulseThreshold(SIMD_INFINITY), +m_isEnabled(true), m_needsFeedback(false), +m_overrideNumSolverIterations(-1), m_rbA(rbA), m_rbB(rbB), m_appliedImpulse(btScalar(0.)), @@ -114,6 +120,10 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali tcd->m_objectType = m_objectType; tcd->m_needsFeedback = m_needsFeedback; + tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations; + tcd->m_breakingImpulseThreshold = float(m_breakingImpulseThreshold); + tcd->m_isEnabled = m_isEnabled? 1: 0; + tcd->m_userConstraintId =m_userConstraintId; tcd->m_userConstraintType =m_userConstraintType; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index 65e6d558300..a16e869a973 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef TYPED_CONSTRAINT_H -#define TYPED_CONSTRAINT_H +#ifndef BT_TYPED_CONSTRAINT_H +#define BT_TYPED_CONSTRAINT_H class btRigidBody; #include "LinearMath/btScalar.h" @@ -62,7 +62,11 @@ class btTypedConstraint : public btTypedObject void* m_userConstraintPtr; }; - bool m_needsFeedback; + btScalar m_breakingImpulseThreshold; + bool m_isEnabled; + bool m_needsFeedback; + int m_overrideNumSolverIterations; + btTypedConstraint& operator=(btTypedConstraint& other) { @@ -80,7 +84,6 @@ protected: ///internal method used by the constraint solver, don't use them directly btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); - static btRigidBody& getFixedBody(); public: @@ -92,6 +95,8 @@ public: int m_numConstraintRows,nub; }; + static btRigidBody& getFixedBody(); + struct btConstraintInfo2 { // integrator parameters: frames per second (1/stepsize), default error // reduction parameter (0..1). @@ -126,6 +131,18 @@ public: btScalar m_damping; }; + int getOverrideNumSolverIterations() const + { + return m_overrideNumSolverIterations; + } + + ///override the number of constraint solver iterations used to solve this constraint + ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations + void setOverrideNumSolverIterations(int overideNumIterations) + { + m_overrideNumSolverIterations = overideNumIterations; + } + ///internal method used by the constraint solver, don't use them directly virtual void buildJacobian() {}; @@ -155,6 +172,28 @@ public: return m_appliedImpulse; } + + btScalar getBreakingImpulseThreshold() const + { + return m_breakingImpulseThreshold; + } + + void setBreakingImpulseThreshold(btScalar threshold) + { + m_breakingImpulseThreshold = threshold; + } + + bool isEnabled() const + { + return m_isEnabled; + } + + void setEnabled(bool enabled) + { + m_isEnabled=enabled; + } + + ///internal method used by the constraint solver, don't use them directly virtual void solveConstraintObsolete(btRigidBody& /*bodyA*/,btRigidBody& /*bodyB*/,btScalar /*timeStep*/) {}; @@ -302,7 +341,10 @@ struct btTypedConstraintData float m_dbgDrawSize; int m_disableCollisionsBetweenLinkedBodies; - char m_pad4[4]; + int m_overrideNumSolverIterations; + + float m_breakingImpulseThreshold; + int m_isEnabled; }; @@ -407,4 +449,4 @@ public: -#endif //TYPED_CONSTRAINT_H +#endif //BT_TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp index 40c56e77954..b009f41aec8 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp @@ -27,7 +27,7 @@ subject to the following restrictions: // constructor // anchor, axis1 and axis2 are in world coordinate system // axis1 must be orthogonal to axis2 -btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2) +btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2) : btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), m_anchor(anchor), m_axis1(axis1), @@ -42,8 +42,8 @@ btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, // new position of X, allowed limits are (-PI,PI); // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs // Build the frame in world coordinate system first - btVector3 zAxis = axis1.normalize(); - btVector3 yAxis = axis2.normalize(); + btVector3 zAxis = m_axis1.normalize(); + btVector3 yAxis = m_axis2.normalize(); btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system btTransform frameInW; frameInW.setIdentity(); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h index a8d404a591c..a86939164ec 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef UNIVERSAL_CONSTRAINT_H -#define UNIVERSAL_CONSTRAINT_H +#ifndef BT_UNIVERSAL_CONSTRAINT_H +#define BT_UNIVERSAL_CONSTRAINT_H @@ -41,7 +41,7 @@ public: // constructor // anchor, axis1 and axis2 are in world coordinate system // axis1 must be orthogonal to axis2 - btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2); + btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2); // access const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } @@ -58,5 +58,5 @@ public: -#endif // UNIVERSAL_CONSTRAINT_H +#endif // BT_UNIVERSAL_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp deleted file mode 100644 index 23501c4435e..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btContinuousDynamicsWorld.h" -#include "LinearMath/btQuickprof.h" - -//collision detection -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" - -//rigidbody & constraints -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" - - - -#include - -btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) -:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) -{ -} - -btContinuousDynamicsWorld::~btContinuousDynamicsWorld() -{ -} - - -void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) -{ - - startProfiling(timeStep); - - if(0 != m_internalPreTickCallback) { - (*m_internalPreTickCallback)(this, timeStep); - } - - - ///update aabbs information - updateAabbs(); - //static int frame=0; -// printf("frame %d\n",frame++); - - ///apply gravity, predict motion - predictUnconstraintMotion(timeStep); - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_debugDraw = getDebugDrawer(); - - ///perform collision detection - performDiscreteCollisionDetection(); - - calculateSimulationIslands(); - - - getSolverInfo().m_timeStep = timeStep; - - - - ///solve contact and other joint constraints - solveConstraints(getSolverInfo()); - - ///CallbackTriggers(); - calculateTimeOfImpacts(timeStep); - - btScalar toi = dispatchInfo.m_timeOfImpact; -// if (toi < 1.f) -// printf("toi = %f\n",toi); - if (toi < 0.f) - printf("toi = %f\n",toi); - - - ///integrate transforms - integrateTransforms(timeStep * toi); - - ///update vehicle simulation - updateActions(timeStep); - - updateActivationState( timeStep ); - - if(0 != m_internalTickCallback) { - (*m_internalTickCallback)(this, timeStep); - } -} - -void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) -{ - ///these should be 'temporal' aabbs! - updateTemporalAabbs(timeStep); - - ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually. - ///so we handle the case moving versus static properly, and we cheat for moving versus moving - btScalar toi = 1.f; - - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_timeOfImpact = 1.f; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS; - - ///calculate time of impact for overlapping pairs - - - btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - - toi = dispatchInfo.m_timeOfImpact; - - dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; - -} - -void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) -{ - - btVector3 temporalAabbMin,temporalAabbMax; - - for ( int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax); - const btVector3& linvel = body->getLinearVelocity(); - - //make the AABB temporal - btScalar temporalAabbMaxx = temporalAabbMax.getX(); - btScalar temporalAabbMaxy = temporalAabbMax.getY(); - btScalar temporalAabbMaxz = temporalAabbMax.getZ(); - btScalar temporalAabbMinx = temporalAabbMin.getX(); - btScalar temporalAabbMiny = temporalAabbMin.getY(); - btScalar temporalAabbMinz = temporalAabbMin.getZ(); - - // add linear motion - btVector3 linMotion = linvel*timeStep; - - if (linMotion.x() > 0.f) - temporalAabbMaxx += linMotion.x(); - else - temporalAabbMinx += linMotion.x(); - if (linMotion.y() > 0.f) - temporalAabbMaxy += linMotion.y(); - else - temporalAabbMiny += linMotion.y(); - if (linMotion.z() > 0.f) - temporalAabbMaxz += linMotion.z(); - else - temporalAabbMinz += linMotion.z(); - - //add conservative angular motion - btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep; - btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); - temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); - temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); - - temporalAabbMin -= angularMotion3d; - temporalAabbMax += angularMotion3d; - - m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1); - } - } - - //update aabb (of all moved objects) - - m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - - - -} - - - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h deleted file mode 100644 index 61c8dea03eb..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H -#define BT_CONTINUOUS_DYNAMICS_WORLD_H - -#include "btDiscreteDynamicsWorld.h" - -///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld. -///This copes with fast moving objects that otherwise would tunnel/miss collisions. -///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead. -class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld -{ - - void updateTemporalAabbs(btScalar timeStep); - - public: - - btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); - virtual ~btContinuousDynamicsWorld(); - - ///time stepping with calculation of time of impact for selected fast moving objects - virtual void internalSingleStepSimulation( btScalar timeStep); - - virtual void calculateTimeOfImpacts(btScalar timeStep); - - virtual btDynamicsWorldType getWorldType() const - { - return BT_CONTINUOUS_DYNAMICS_WORLD; - } - -}; - -#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index e1eada07c82..954ef241adc 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -35,6 +35,8 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" #include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + #include "LinearMath/btIDebugDraw.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -46,6 +48,167 @@ subject to the following restrictions: #include "LinearMath/btSerializer.h" +#if 0 +btAlignedObjectArray debugContacts; +btAlignedObjectArray debugNormals; +int startHit=2; +int firstHit=startHit; +#endif + +SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) +{ + int islandId; + + const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); + const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); + islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); + return islandId; + +} + + +class btSortConstraintOnIslandPredicate +{ + public: + + bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const + { + int rIslandId0,lIslandId0; + rIslandId0 = btGetConstraintIslandId(rhs); + lIslandId0 = btGetConstraintIslandId(lhs); + return lIslandId0 < rIslandId0; + } +}; + +struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback +{ + btContactSolverInfo* m_solverInfo; + btConstraintSolver* m_solver; + btTypedConstraint** m_sortedConstraints; + int m_numConstraints; + btIDebugDraw* m_debugDrawer; + btStackAlloc* m_stackAlloc; + btDispatcher* m_dispatcher; + + btAlignedObjectArray m_bodies; + btAlignedObjectArray m_manifolds; + btAlignedObjectArray m_constraints; + + + InplaceSolverIslandCallback( + btConstraintSolver* solver, + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) + :m_solverInfo(NULL), + m_solver(solver), + m_sortedConstraints(NULL), + m_numConstraints(0), + m_debugDrawer(NULL), + m_stackAlloc(stackAlloc), + m_dispatcher(dispatcher) + { + + } + + InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other) + { + btAssert(0); + (void)other; + return *this; + } + + SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer) + { + btAssert(solverInfo); + m_solverInfo = solverInfo; + m_sortedConstraints = sortedConstraints; + m_numConstraints = numConstraints; + m_debugDrawer = debugDrawer; + m_bodies.resize (0); + m_manifolds.resize (0); + m_constraints.resize (0); + } + + + virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) + { + if (islandId<0) + { + if (numManifolds + m_numConstraints) + { + ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + } else + { + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;im_minimumSolverBatchSize<=1) + { + ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive + if (numManifolds + numCurConstraints) + { + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + } else + { + + for (i=0;im_solverInfo->m_minimumSolverBatchSize) + { + processConstraints(); + } else + { + //printf("deferred\n"); + } + } + } + } + void processConstraints() + { + if (m_manifolds.size() + m_constraints.size()>0) + { + + btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0; + btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0; + btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0; + + m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + m_bodies.resize(0); + m_manifolds.resize(0); + m_constraints.resize(0); + + } + +}; + btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) @@ -54,7 +217,9 @@ m_constraintSolver(constraintSolver), m_gravity(0,-10,0), m_localTime(0), m_synchronizeAllMotionStates(false), -m_profileTimings(0) +m_profileTimings(0), +m_sortedConstraints (), +m_solverIslandCallback ( NULL ) { if (!m_constraintSolver) { @@ -72,6 +237,11 @@ m_profileTimings(0) } m_ownsIslandManager = true; + + { + void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16); + m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (constraintSolver, m_stackAlloc, dispatcher); + } } @@ -83,6 +253,11 @@ btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() m_islandManager->~btSimulationIslandManager(); btAlignedFree( m_islandManager); } + if (m_solverIslandCallback) + { + m_solverIslandCallback->~InplaceSolverIslandCallback(); + btAlignedFree(m_solverIslandCallback); + } if (m_ownsConstraintSolver) { @@ -138,7 +313,7 @@ void btDiscreteDynamicsWorld::debugDrawWorld() - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)) + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals))) { int i; @@ -314,9 +489,11 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) dispatchInfo.m_stepCount = 0; dispatchInfo.m_debugDraw = getDebugDrawer(); + ///perform collision detection performDiscreteCollisionDetection(); + calculateSimulationIslands(); @@ -524,187 +701,39 @@ void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character) } -SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) -{ - int islandId; - - const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); - const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); - islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); - return islandId; - -} - - -class btSortConstraintOnIslandPredicate -{ - public: - - bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) - { - int rIslandId0,lIslandId0; - rIslandId0 = btGetConstraintIslandId(rhs); - lIslandId0 = btGetConstraintIslandId(lhs); - return lIslandId0 < rIslandId0; - } -}; - void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { BT_PROFILE("solveConstraints"); - struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback - { - - btContactSolverInfo& m_solverInfo; - btConstraintSolver* m_solver; - btTypedConstraint** m_sortedConstraints; - int m_numConstraints; - btIDebugDraw* m_debugDrawer; - btStackAlloc* m_stackAlloc; - btDispatcher* m_dispatcher; - - btAlignedObjectArray m_bodies; - btAlignedObjectArray m_manifolds; - btAlignedObjectArray m_constraints; - - - InplaceSolverIslandCallback( - btContactSolverInfo& solverInfo, - btConstraintSolver* solver, - btTypedConstraint** sortedConstraints, - int numConstraints, - btIDebugDraw* debugDrawer, - btStackAlloc* stackAlloc, - btDispatcher* dispatcher) - :m_solverInfo(solverInfo), - m_solver(solver), - m_sortedConstraints(sortedConstraints), - m_numConstraints(numConstraints), - m_debugDrawer(debugDrawer), - m_stackAlloc(stackAlloc), - m_dispatcher(dispatcher) - { - - } - - - InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other) - { - btAssert(0); - (void)other; - return *this; - } - virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) - { - if (islandId<0) - { - if (numManifolds + m_numConstraints) - { - ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id - m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - } - } else - { - //also add all non-contact constraints/joints for this island - btTypedConstraint** startConstraint = 0; - int numCurConstraints = 0; - int i; - - //find the first constraint for this island - for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - } - } else - { - - for (i=0;im_solverInfo.m_minimumSolverBatchSize) - { - processConstraints(); - } else - { - //printf("deferred\n"); - } - } - } - } - void processConstraints() - { - if (m_manifolds.size() + m_constraints.size()>0) - { - m_solver->solveGroup( &m_bodies[0],m_bodies.size(), &m_manifolds[0], m_manifolds.size(), &m_constraints[0], m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - } - m_bodies.resize(0); - m_manifolds.resize(0); - m_constraints.resize(0); - - } - - }; - - - - //sorted version of all btTypedConstraint, based on islandId - btAlignedObjectArray sortedConstraints; - sortedConstraints.resize( m_constraints.size()); + m_sortedConstraints.resize( m_constraints.size()); int i; for (i=0;isetup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer()); m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island - m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),&solverCallback); + m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback); - solverCallback.processConstraints(); + m_solverIslandCallback->processConstraints(); m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); } - - void btDiscreteDynamicsWorld::calculateSimulationIslands() { BT_PROFILE("calculateSimulationIslands"); @@ -717,18 +746,20 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() for (i=0;i< numConstraints ; i++ ) { btTypedConstraint* constraint = m_constraints[i]; - - const btRigidBody* colObj0 = &constraint->getRigidBodyA(); - const btRigidBody* colObj1 = &constraint->getRigidBodyB(); - - if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && - ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) + if (constraint->isEnabled()) { - if (colObj0->isActive() || colObj1->isActive()) + const btRigidBody* colObj0 = &constraint->getRigidBodyA(); + const btRigidBody* colObj1 = &constraint->getRigidBodyB(); + + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) { + if (colObj0->isActive() || colObj1->isActive()) + { - getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), - (colObj1)->getIslandTag()); + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), + (colObj1)->getIslandTag()); + } } } } @@ -745,12 +776,13 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { +public: + btCollisionObject* m_me; btScalar m_allowedPenetration; btOverlappingPairCache* m_pairCache; btDispatcher* m_dispatcher; - public: btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : btCollisionWorld::ClosestConvexResultCallback(fromA,toA), @@ -797,6 +829,7 @@ public: //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179 if (m_dispatcher->needsResponse(m_me,otherObj)) { +#if 0 ///don't do CCD when there are already contact points (touching contact/penetration) btAlignedObjectArray manifoldArray; btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); @@ -814,8 +847,11 @@ public: } } } +#endif + return true; } - return true; + + return false; } @@ -824,7 +860,6 @@ public: ///internal debugging variable. this value shouldn't be too high int gNumClampedCcdMotions=0; -//#include "stdio.h" void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { BT_PROFILE("integrateTransforms"); @@ -836,34 +871,93 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) if (body->isActive() && (!body->isStaticOrKinematicObject())) { + body->predictIntegratedTransform(timeStep, predictedTrans); + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); - if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + + + if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) { BT_PROFILE("CCD motion clamping"); if (body->getCollisionShape()->isConvex()) { gNumClampedCcdMotions++; - +#ifdef USE_STATIC_ONLY + class StaticOnlyCallback : public btClosestNotMeConvexResultCallback + { + public: + + StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : + btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher) + { + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject; + if (!otherObj->isStaticOrKinematicObject()) + return false; + return btClosestNotMeConvexResultCallback::needsCollision(proxy0); + } + }; + + StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#else btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher()); +#endif //btConvexShape* convexShape = static_cast(body->getCollisionShape()); btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration; sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup; sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask; + btTransform modifiedPredictedTrans = predictedTrans; + modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis()); - convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults); + convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults); if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) { + + //printf("clamped integration to hit fraction = %f\n",fraction); body->setHitFraction(sweepResults.m_closestHitFraction); body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); body->setHitFraction(0.f); -// printf("clamped integration to hit fraction = %f\n",fraction); + body->proceedToTransform( predictedTrans); + +#if 0 + btVector3 linVel = body->getLinearVelocity(); + + btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep; + btScalar maxSpeedSqr = maxSpeed*maxSpeed; + if (linVel.length2()>maxSpeedSqr) + { + linVel.normalize(); + linVel*= maxSpeed; + body->setLinearVelocity(linVel); + btScalar ms2 = body->getLinearVelocity().length2(); + body->predictIntegratedTransform(timeStep, predictedTrans); + + btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + btScalar smt = body->getCcdSquareMotionThreshold(); + printf("sm2=%f\n",sm2); + } +#else + //response between two dynamic objects without friction, assuming 0 penetration depth + btScalar appliedImpulse = 0.f; + btScalar depth = 0.f; + appliedImpulse = resolveSingleCollision(body,sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth); + + +#endif + + continue; } } } + body->proceedToTransform( predictedTrans); } } @@ -873,6 +967,7 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) + void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { BT_PROFILE("predictUnconstraintMotion"); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index df47c29044f..23a38dd2a12 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -27,6 +27,8 @@ class btTypedConstraint; class btActionInterface; class btIDebugDraw; +struct InplaceSolverIslandCallback; + #include "LinearMath/btAlignedObjectArray.h" @@ -35,6 +37,9 @@ class btIDebugDraw; class btDiscreteDynamicsWorld : public btDynamicsWorld { protected: + + btAlignedObjectArray m_sortedConstraints; + InplaceSolverIslandCallback* m_solverIslandCallback; btConstraintSolver* m_constraintSolver; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 105317920ae..6b0093371b8 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -32,7 +32,8 @@ enum btDynamicsWorldType { BT_SIMPLE_DYNAMICS_WORLD=1, BT_DISCRETE_DYNAMICS_WORLD=2, - BT_CONTINUOUS_DYNAMICS_WORLD=3 + BT_CONTINUOUS_DYNAMICS_WORLD=3, + BT_SOFT_RIGID_DYNAMICS_WORLD=4 }; ///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index aefb26a1be2..911b5072394 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -286,7 +286,7 @@ btQuaternion btRigidBody::getOrientation() const void btRigidBody::setCenterOfMassTransform(const btTransform& xform) { - if (isStaticOrKinematicObject()) + if (isKinematicObject()) { m_interpolationWorldTransform = m_worldTransform; } else @@ -309,8 +309,9 @@ bool btRigidBody::checkCollideWithOverride(btCollisionObject* co) for (int i = 0; i < m_constraintRefs.size(); ++i) { btTypedConstraint* c = m_constraintRefs[i]; - if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb) - return false; + if (c->isEnabled()) + if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb) + return false; } return true; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index 5a7ba97ccbc..7c121e6df13 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef RIGIDBODY_H -#define RIGIDBODY_H +#ifndef BT_RIGIDBODY_H +#define BT_RIGIDBODY_H #include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btTransform.h" @@ -687,5 +687,5 @@ struct btRigidBodyDoubleData -#endif +#endif //BT_RIGIDBODY_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h index 07a727e2efe..d48d2e39c4d 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -23,7 +23,7 @@ class btOverlappingPairCache; class btConstraintSolver; ///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. -///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished). +///Please use btDiscreteDynamicsWorld instead class btSimpleDynamicsWorld : public btDynamicsWorld { protected: diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index ac42f1313be..f59555f94d2 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -8,8 +8,8 @@ * of this software for any purpose. * It is provided "as is" without express or implied warranty. */ -#ifndef RAYCASTVEHICLE_H -#define RAYCASTVEHICLE_H +#ifndef BT_RAYCASTVEHICLE_H +#define BT_RAYCASTVEHICLE_H #include "BulletDynamics/Dynamics/btRigidBody.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" @@ -232,5 +232,5 @@ public: }; -#endif //RAYCASTVEHICLE_H +#endif //BT_RAYCASTVEHICLE_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h index 5112ce6d420..3cc909c6530 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, @@ -8,8 +8,8 @@ * of this software for any purpose. * It is provided "as is" without express or implied warranty. */ -#ifndef VEHICLE_RAYCASTER_H -#define VEHICLE_RAYCASTER_H +#ifndef BT_VEHICLE_RAYCASTER_H +#define BT_VEHICLE_RAYCASTER_H #include "LinearMath/btVector3.h" @@ -31,5 +31,5 @@ virtual ~btVehicleRaycaster() }; -#endif //VEHICLE_RAYCASTER_H +#endif //BT_VEHICLE_RAYCASTER_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h index b74f8c80acb..f916053ecac 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -8,8 +8,8 @@ * of this software for any purpose. * It is provided "as is" without express or implied warranty. */ -#ifndef WHEEL_INFO_H -#define WHEEL_INFO_H +#ifndef BT_WHEEL_INFO_H +#define BT_WHEEL_INFO_H #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" @@ -115,5 +115,5 @@ struct btWheelInfo }; -#endif //WHEEL_INFO_H +#endif //BT_WHEEL_INFO_H diff --git a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp index c876ebf1fd6..d1435b65cda 100644 --- a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp +++ b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp @@ -35,7 +35,7 @@ btDefaultSoftBodySolver::~btDefaultSoftBodySolver() } // In this case the data is already in the soft bodies so there is no need for us to do anything -void btDefaultSoftBodySolver::copyBackToSoftBodies() +void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove) { } diff --git a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h index 8e7db3daf98..7d9092ce5b9 100644 --- a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h +++ b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h @@ -46,7 +46,7 @@ public: virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies,bool forceUpdate=false ); - virtual void copyBackToSoftBodies(); + virtual void copyBackToSoftBodies(bool bMove = true); virtual void solveConstraints( float solverdt ); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp index 0d19fd193e7..9c06841801c 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -19,9 +19,10 @@ subject to the following restrictions: #include "btSoftBodyData.h" #include "LinearMath/btSerializer.h" + // btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) -:m_worldInfo(worldInfo),m_softBodySolver(0) +:m_softBodySolver(0),m_worldInfo(worldInfo) { /* Init */ initDefaults(); @@ -357,14 +358,14 @@ void btSoftBody::appendTetra(int node0, // -void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies) +void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence) { btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x; - appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies); + appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence); } // -void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies) +void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence) { if (disableCollisionBetweenLinkedBodies) { @@ -379,6 +380,7 @@ void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& loc a.m_body = body; a.m_local = localPivot; a.m_node->m_battach = 1; + a.m_influence = influence; m_anchors.push_back(a); } @@ -451,6 +453,167 @@ void btSoftBody::addForce(const btVector3& force,int node) } } +void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex) +{ + btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size()); + + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + const btScalar kPR = m_cfg.kPR; + const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_aero = as_lift || as_drag; + const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided); + + Node& n = m_nodes[nodeIndex]; + + if( n.m_im>0 ) + { + btSoftBody::sMedium medium; + + EvaluateMedium(m_worldInfo, n.m_x, medium); + medium.m_velocity = windVelocity; + medium.m_density = m_worldInfo->air_density; + + /* Aerodynamics */ + if(as_vaero) + { + const btVector3 rel_v = n.m_v - medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); + const btScalar rel_v2 = rel_v.length2(); + + if(rel_v2>SIMD_EPSILON) + { + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = n.m_n; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag) + { + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * n.m_area; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + n.m_f += fDrag; + n.m_f += fLift; + } + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided) + { + if (btSoftBody::eAeroModel::V_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn = btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = n.m_area * dvn * rel_v2/2; + const btScalar c1 = c0 * medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized() * (-c1 * kDG); + ApplyClampedForce(n, force, dt); + } + } + } + } + } +} + +void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex) +{ + const btScalar dt = m_sst.sdt; + const btScalar kLF = m_cfg.kLF; + const btScalar kDG = m_cfg.kDG; + const btScalar kPR = m_cfg.kPR; + const btScalar kVC = m_cfg.kVC; + const bool as_lift = kLF>0; + const bool as_drag = kDG>0; + const bool as_aero = as_lift || as_drag; + const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided); + + if(as_faero) + { + btSoftBody::Face& f=m_faces[faceIndex]; + + btSoftBody::sMedium medium; + + const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; + const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; + EvaluateMedium(m_worldInfo,x,medium); + medium.m_velocity = windVelocity; + medium.m_density = m_worldInfo->air_density; + const btVector3 rel_v=v-medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); + const btScalar rel_v2=rel_v.length2(); + + if(rel_v2>SIMD_EPSILON) + { + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = f.m_normal; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag) + { + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * f.m_ra; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + fDrag /= 3; + fLift /= 3; + + for(int j=0;j<3;++j) + { + if (f.m_n[j]->m_im>0) + { + f.m_n[j]->m_f += fDrag; + f.m_n[j]->m_f += fLift; + } + } + } + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided) + { + if (btSoftBody::eAeroModel::F_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn=btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = f.m_ra*dvn*rel_v2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + force /= 3; + for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + } + } + } + } + +} + // void btSoftBody::addVelocity(const btVector3& velocity) { @@ -1820,7 +1983,7 @@ btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayF void btSoftBody::pointersToIndices() { #define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) - btSoftBody::Node* base=&m_nodes[0]; + btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0; int i,ni; for(i=0,ni=m_nodes.size();im_x; + btVector3 v1=tet.m_n[index1]->m_x; + btVector3 v2=tet.m_n[index2]->m_x; + + + const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir, + v0,v1,v2, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Tetra; + index=i; + mint=t; + } + } + } + } return(cnt); } @@ -2660,44 +2855,8 @@ void btSoftBody::applyForces() { if(use_medium) { - EvaluateMedium(m_worldInfo, n.m_x, medium); - medium.m_velocity = m_windVelocity; - medium.m_density = m_worldInfo->air_density; - /* Aerodynamics */ - if(as_vaero) - { - const btVector3 rel_v = n.m_v - medium.m_velocity; - const btScalar rel_v2 = rel_v.length2(); - if(rel_v2>SIMD_EPSILON) - { - btVector3 nrm = n.m_n; - /* Setup normal */ - switch(m_cfg.aeromodel) - { - case btSoftBody::eAeroModel::V_Point: - nrm = NormalizeAny(rel_v); - break; - case btSoftBody::eAeroModel::V_TwoSided: - nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); - break; - default: - { - } - } - const btScalar dvn = btDot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) - { - btVector3 force(0,0,0); - const btScalar c0 = n.m_area * dvn * rel_v2/2; - const btScalar c1 = c0 * medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized() * (-c1 * kDG); - ApplyClampedForce(n, force, dt); - } - } - } + addAeroForceToNode(m_windVelocity, i); } /* Pressure */ if(as_pressure) @@ -2711,43 +2870,14 @@ void btSoftBody::applyForces() } } } + /* Per face forces */ for(i=0,ni=m_faces.size();im_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; - const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; - EvaluateMedium(m_worldInfo,x,medium); - const btVector3 rel_v=v-medium.m_velocity; - const btScalar rel_v2=rel_v.length2(); - if(rel_v2>SIMD_EPSILON) - { - btVector3 nrm=f.m_normal; - /* Setup normal */ - switch(m_cfg.aeromodel) - { - case btSoftBody::eAeroModel::F_TwoSided: - nrm*=(btScalar)(btDot(nrm,rel_v)<0?-1:+1);break; - default: - { - } - } - const btScalar dvn=btDot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) - { - btVector3 force(0,0,0); - const btScalar c0 = f.m_ra*dvn*rel_v2; - const btScalar c1 = c0*medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized()*(-c1*kDG); - force /= 3; - for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); - } - } - } + + /* Aerodynamics */ + addAeroForceToFace(m_windVelocity, i); } } @@ -2765,7 +2895,7 @@ void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti) const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; const btVector3 vb=n.m_x-n.m_q; const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; - const btVector3 impulse=a.m_c0*vr; + const btVector3 impulse=a.m_c0*vr*a.m_influence; n.m_x+=impulse*a.m_c2; a.m_body->applyImpulse(-impulse,a.m_c1); } @@ -3196,7 +3326,7 @@ const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializ sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL; sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL; sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL; - + //pose for shape matching { sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h index ad8678f28b2..ba589486f26 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -80,11 +80,13 @@ public: ///eAeroModel struct eAeroModel { enum _ { - V_Point, ///Vertex normals are oriented toward velocity - V_TwoSided, ///Vertex normals are fliped to match velocity - V_OneSided, ///Vertex normals are taken as it is - F_TwoSided, ///Face normals are fliped to match velocity - F_OneSided, ///Face normals are taken as it is + V_Point, ///Vertex normals are oriented toward velocity + V_TwoSided, ///Vertex normals are flipped to match velocity + V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied + V_OneSided, ///Vertex normals are taken as it is + F_TwoSided, ///Face normals are flipped to match velocity + F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied + F_OneSided, ///Face normals are taken as it is END };}; @@ -117,6 +119,7 @@ public: Node, Link, Face, + Tetra, END };}; @@ -282,6 +285,7 @@ public: Node* m_node; // Node pointer btVector3 m_local; // Anchor position in body space btRigidBody* m_body; // Body + btScalar m_influence; btMatrix3x3 m_c0; // Impulse matrix btVector3 m_c1; // Relative anchor btScalar m_c2; // ima*dt @@ -752,8 +756,8 @@ public: /* Append anchor */ void appendAnchor( int node, - btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false); - void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false); + btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); + void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); /* Append linear joint */ void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); @@ -767,6 +771,12 @@ public: /* Add force (or gravity) to a node of the body */ void addForce( const btVector3& force, int node); + /* Add aero force to a node of the body */ + void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex); + + /* Add aero force to a face of the body */ + void addAeroForceToFace(const btVector3& windVelocity,int faceIndex); + /* Add velocity to the entire body */ void addVelocity( const btVector3& velocity); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp index 04ee7ea77cf..d99be3b8138 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -95,7 +95,7 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, ci.m_dispatcher1 = m_dispatcher; ///debug drawing of the overlapping triangles - if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe) + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe)) { btVector3 color(1,1,0); btTransform& tr = ob->getWorldTransform(); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h index f311419d4a8..8a09fff2a37 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H -#define SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#ifndef BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#define BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h" @@ -152,4 +152,4 @@ public: }; -#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp index 1a271066497..0fb3560e94c 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -19,6 +19,8 @@ subject to the following restrictions: #include #include "btSoftBodyHelpers.h" #include "LinearMath/btConvexHull.h" +#include "LinearMath/btConvexHullComputer.h" + // static void drawVertex( btIDebugDraw* idraw, @@ -183,6 +185,35 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, { vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x; } +#define USE_NEW_CONVEX_HULL_COMPUTER +#ifdef USE_NEW_CONVEX_HULL_COMPUTER + btConvexHullComputer computer; + int stride = sizeof(btVector3); + int count = vertices.size(); + btScalar shrink=0.f; + btScalar shrinkClamp=0.f; + computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp); + for (int i=0;igetNextEdgeOfFace(); + + int v0 = firstEdge->getSourceVertex(); + int v1 = firstEdge->getTargetVertex(); + while (edge!=firstEdge) + { + int v2 = edge->getTargetVertex(); + idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1); + edge = edge->getNextEdgeOfFace(); + v0=v1; + v1=v2; + }; + } +#else + HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); HullResult hres; HullLibrary hlib; @@ -201,6 +232,8 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, color,1); } hlib.ReleaseResult(hres); +#endif + } /* Velocities */ #if 0 @@ -296,7 +329,7 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, { const btScalar scl=(btScalar)0.8; const btScalar alp=(btScalar)1; - const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7); + const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7); for(int i=0;im_tetras.size();++i) { const btSoftBody::Tetra& t=psb->m_tetras[i]; diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h index 49b1f0bbce8..620a52fe394 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SOFT_BODY_HELPERS_H -#define SOFT_BODY_HELPERS_H +#ifndef BT_SOFT_BODY_HELPERS_H +#define BT_SOFT_BODY_HELPERS_H #include "btSoftBody.h" @@ -140,4 +140,4 @@ struct btSoftBodyHelpers }; -#endif //SOFT_BODY_HELPERS_H +#endif //BT_SOFT_BODY_HELPERS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h index 885571069d0..5ef8db19396 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h @@ -70,7 +70,7 @@ public: ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { - /* t should be identity, but better be safe than...fast? */ + /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */ const btVector3 mins=m_body->m_bounds[0]; const btVector3 maxs=m_body->m_bounds[1]; const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h index 440084c5f7b..2fcd8b67616 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h @@ -73,7 +73,7 @@ public: virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false) = 0; /** Copy necessary data back to the original soft body source objects. */ - virtual void copyBackToSoftBodies() = 0; + virtual void copyBackToSoftBodies(bool bMove = true) = 0; /** Predict motion of soft bodies into next timestep */ virtual void predictMotion( float solverdt ) = 0; diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h index adc3844e363..7658e3c2252 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SOFT_RIGID_COLLISION_ALGORITHM_H -#define SOFT_RIGID_COLLISION_ALGORITHM_H +#ifndef BT_SOFT_RIGID_COLLISION_ALGORITHM_H +#define BT_SOFT_RIGID_COLLISION_ALGORITHM_H #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -70,6 +70,6 @@ public: }; -#endif //SOFT_RIGID_COLLISION_ALGORITHM_H +#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp index 1b9b5e392a1..8f4be231c13 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -165,7 +165,7 @@ void btSoftRigidDynamicsWorld::debugDrawWorld() for ( i=0;im_softBodies.size();i++) { btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)) + if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) { btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); @@ -300,12 +300,19 @@ void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,con shapeInfo.m_shapePart = 0; shapeInfo.m_triangleIndex = softResult.index; // get the normal - btVector3 normal = softBody->m_faces[softResult.index].m_normal; btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin(); - if (normal.dot(rayDir) > 0) { - // normal always point toward origin of the ray - normal = -normal; + btVector3 normal=-rayDir; + normal.normalize(); + + if (softResult.feature == btSoftBody::eFeature::Face) + { + normal = softBody->m_faces[softResult.index].m_normal; + if (normal.dot(rayDir) > 0) { + // normal always point toward origin of the ray + normal = -normal; + } } + btCollisionWorld::LocalRayResult rayResult (collisionObject, &shapeInfo, diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h index 7d8d0cb7daa..3e0efafd6c7 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -73,6 +73,10 @@ public: return m_sbi; } + virtual btDynamicsWorldType getWorldType() const + { + return BT_SOFT_RIGID_DYNAMICS_WORLD; + } btSoftBodyArray& getSoftBodyArray() { diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h index 1b34e0af60f..92d683c1dc8 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -13,8 +13,8 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SOFT_SOFT_COLLISION_ALGORITHM_H -#define SOFT_SOFT_COLLISION_ALGORITHM_H +#ifndef BT_SOFT_SOFT_COLLISION_ALGORITHM_H +#define BT_SOFT_SOFT_COLLISION_ALGORITHM_H #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" @@ -64,6 +64,6 @@ public: }; -#endif //SOFT_SOFT_COLLISION_ALGORITHM_H +#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h index cc4266732ae..90a26cdf7e3 100644 --- a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h +++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ ///btSparseSdf implementation by Nathanael Presson -#ifndef _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ -#define _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ +#ifndef BT_SPARSE_SDF_H +#define BT_SPARSE_SDF_H #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" @@ -303,4 +303,4 @@ struct btSparseSdf }; -#endif +#endif //BT_SPARSE_SDF_H diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 532ce1bf633..42b721dea22 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef AABB_UTIL2 -#define AABB_UTIL2 +#ifndef BT_AABB_UTIL2 +#define BT_AABB_UTIL2 #include "btTransform.h" #include "btVector3.h" @@ -231,6 +231,6 @@ SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVec } #endif //USE_BANCHLESS -#endif +#endif //BT_AABB_UTIL2 diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp index 189b759d237..c4c0ceb2ed2 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -58,16 +58,18 @@ static inline void btAlignedFreeDefault(void *ptr) free(ptr); } #else + + + + + static inline void *btAlignedAllocDefault(size_t size, int alignment) { void *ret; char *real; - unsigned long offset; - real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); if (real) { - offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); - ret = (void *)((real + sizeof(void *)) + offset); + ret = btAlignPointer(real + sizeof(void *),alignment); *((void **)(ret)-1) = (void *)(real); } else { ret = (void *)(real); @@ -110,7 +112,6 @@ void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filen { void *ret; char *real; - unsigned long offset; gTotalBytesAlignedAllocs += size; gNumAlignedAllocs++; @@ -118,9 +119,7 @@ void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filen real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); if (real) { - offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & -(alignment-1); - ret = (void *)((real + 2*sizeof(void *)) + offset); + ret = (void*) btAlignPointer((real + 2*sizeof(void *), alignment); *((void **)(ret)-1) = (void *)(real); *((int*)(ret)-2) = size; diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h index 955bb128e83..36090e13c89 100644 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -28,6 +28,7 @@ subject to the following restrictions: #define BT_USE_PLACEMENT_NEW 1 //#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in or or otherwise... +#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful #ifdef BT_USE_MEMCPY #include @@ -53,7 +54,19 @@ class btAlignedObjectArray //PCK: added this line bool m_ownsMemory; - protected: +#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR +public: + SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other) + { + copyFromArray(other); + return *this; + } +#else//BT_ALLOW_ARRAY_COPY_OPERATOR +private: + SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other); +#endif//BT_ALLOW_ARRAY_COPY_OPERATOR + +protected: SIMD_FORCE_INLINE int allocSize(int size) { return (size ? size*2 : 1); @@ -140,21 +153,29 @@ class btAlignedObjectArray SIMD_FORCE_INLINE const T& at(int n) const { + btAssert(n>=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n0); m_size--; m_data[m_size].~T(); } @@ -291,8 +313,9 @@ class btAlignedObjectArray } }; + template - void quickSortInternal(L CompareFunc,int lo, int hi) + void quickSortInternal(const L& CompareFunc,int lo, int hi) { // lo is the lower index, hi is the upper index // of the region of array a that is to be sorted @@ -322,7 +345,7 @@ class btAlignedObjectArray template - void quickSort(L CompareFunc) + void quickSort(const L& CompareFunc) { //don't sort 0 or 1 elements if (size()>1) @@ -334,7 +357,7 @@ class btAlignedObjectArray ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ template - void downHeap(T *pArr, int k, int n,L CompareFunc) + void downHeap(T *pArr, int k, int n, const L& CompareFunc) { /* PRE: a[k+1..N] is a heap */ /* POST: a[k..N] is a heap */ @@ -380,7 +403,7 @@ class btAlignedObjectArray } template - void heapSort(L CompareFunc) + void heapSort(const L& CompareFunc) { /* sort a[0..N-1], N.B. 0 to N-1 */ int k; diff --git a/extern/bullet2/src/LinearMath/btConvexHull.h b/extern/bullet2/src/LinearMath/btConvexHull.h index a23fa4d550f..69c52bc6f83 100644 --- a/extern/bullet2/src/LinearMath/btConvexHull.h +++ b/extern/bullet2/src/LinearMath/btConvexHull.h @@ -16,8 +16,8 @@ subject to the following restrictions: ///includes modifications/improvements by John Ratcliff, see BringOutYourDead below. -#ifndef CD_HULL_H -#define CD_HULL_H +#ifndef BT_CD_HULL_H +#define BT_CD_HULL_H #include "btVector3.h" #include "btAlignedObjectArray.h" @@ -237,5 +237,5 @@ private: }; -#endif +#endif //BT_CD_HULL_H diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp new file mode 100644 index 00000000000..c03c901c051 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp @@ -0,0 +1,2751 @@ +/* +Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include + +#include "btConvexHullComputer.h" +#include "btAlignedObjectArray.h" +#include "btMinMax.h" +#include "btVector3.h" + +#ifdef __GNUC__ + #include +#elif defined(_MSC_VER) + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; +#else + typedef int int32_t; + typedef long long int int64_t; + typedef unsigned int uint32_t; + typedef unsigned long long int uint64_t; +#endif + + +//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines +//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly +// #define USE_X86_64_ASM +//#endif + + +//#define DEBUG_CONVEX_HULL +//#define SHOW_ITERATIONS + +#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS) + #include +#endif + +// Convex hull implementation based on Preparata and Hong +// Ole Kniemeyer, MAXON Computer GmbH +class btConvexHullInternal +{ + public: + + class Point64 + { + public: + int64_t x; + int64_t y; + int64_t z; + + Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z) + { + } + + bool isZero() + { + return (x == 0) && (y == 0) && (z == 0); + } + + int64_t dot(const Point64& b) const + { + return x * b.x + y * b.y + z * b.z; + } + }; + + class Point32 + { + public: + int32_t x; + int32_t y; + int32_t z; + int index; + + Point32() + { + } + + Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1) + { + } + + bool operator==(const Point32& b) const + { + return (x == b.x) && (y == b.y) && (z == b.z); + } + + bool operator!=(const Point32& b) const + { + return (x != b.x) || (y != b.y) || (z != b.z); + } + + bool isZero() + { + return (x == 0) && (y == 0) && (z == 0); + } + + Point64 cross(const Point32& b) const + { + return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + + Point64 cross(const Point64& b) const + { + return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + + int64_t dot(const Point32& b) const + { + return x * b.x + y * b.y + z * b.z; + } + + int64_t dot(const Point64& b) const + { + return x * b.x + y * b.y + z * b.z; + } + + Point32 operator+(const Point32& b) const + { + return Point32(x + b.x, y + b.y, z + b.z); + } + + Point32 operator-(const Point32& b) const + { + return Point32(x - b.x, y - b.y, z - b.z); + } + }; + + class Int128 + { + public: + uint64_t low; + uint64_t high; + + Int128() + { + } + + Int128(uint64_t low, uint64_t high): low(low), high(high) + { + } + + Int128(uint64_t low): low(low), high(0) + { + } + + Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL) + { + } + + static Int128 mul(int64_t a, int64_t b); + + static Int128 mul(uint64_t a, uint64_t b); + + Int128 operator-() const + { + return Int128((uint64_t) -(int64_t)low, ~high + (low == 0)); + } + + Int128 operator+(const Int128& b) const + { +#ifdef USE_X86_64_ASM + Int128 result; + __asm__ ("addq %[bl], %[rl]\n\t" + "adcq %[bh], %[rh]\n\t" + : [rl] "=r" (result.low), [rh] "=r" (result.high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); + return result; +#else + uint64_t lo = low + b.low; + return Int128(lo, high + b.high + (lo < low)); +#endif + } + + Int128 operator-(const Int128& b) const + { +#ifdef USE_X86_64_ASM + Int128 result; + __asm__ ("subq %[bl], %[rl]\n\t" + "sbbq %[bh], %[rh]\n\t" + : [rl] "=r" (result.low), [rh] "=r" (result.high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); + return result; +#else + return *this + -b; +#endif + } + + Int128& operator+=(const Int128& b) + { +#ifdef USE_X86_64_ASM + __asm__ ("addq %[bl], %[rl]\n\t" + "adcq %[bh], %[rh]\n\t" + : [rl] "=r" (low), [rh] "=r" (high) + : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high) + : "cc" ); +#else + uint64_t lo = low + b.low; + if (lo < low) + { + ++high; + } + low = lo; + high += b.high; +#endif + return *this; + } + + Int128& operator++() + { + if (++low == 0) + { + ++high; + } + return *this; + } + + Int128 operator*(int64_t b) const; + + btScalar toScalar() const + { + return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low) + : -(-*this).toScalar(); + } + + int getSign() const + { + return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0; + } + + bool operator<(const Int128& b) const + { + return (high < b.high) || ((high == b.high) && (low < b.low)); + } + + int ucmp(const Int128&b) const + { + if (high < b.high) + { + return -1; + } + if (high > b.high) + { + return 1; + } + if (low < b.low) + { + return -1; + } + if (low > b.low) + { + return 1; + } + return 0; + } + }; + + + class Rational64 + { + private: + uint64_t m_numerator; + uint64_t m_denominator; + int sign; + + public: + Rational64(int64_t numerator, int64_t denominator) + { + if (numerator > 0) + { + sign = 1; + m_numerator = (uint64_t) numerator; + } + else if (numerator < 0) + { + sign = -1; + m_numerator = (uint64_t) -numerator; + } + else + { + sign = 0; + m_numerator = 0; + } + if (denominator > 0) + { + m_denominator = (uint64_t) denominator; + } + else if (denominator < 0) + { + sign = -sign; + m_denominator = (uint64_t) -denominator; + } + else + { + m_denominator = 0; + } + } + + bool isNegativeInfinity() const + { + return (sign < 0) && (m_denominator == 0); + } + + bool isNaN() const + { + return (sign == 0) && (m_denominator == 0); + } + + int compare(const Rational64& b) const; + + btScalar toScalar() const + { + return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator); + } + }; + + + class Rational128 + { + private: + Int128 numerator; + Int128 denominator; + int sign; + bool isInt64; + + public: + Rational128(int64_t value) + { + if (value > 0) + { + sign = 1; + this->numerator = value; + } + else if (value < 0) + { + sign = -1; + this->numerator = -value; + } + else + { + sign = 0; + this->numerator = (uint64_t) 0; + } + this->denominator = (uint64_t) 1; + isInt64 = true; + } + + Rational128(const Int128& numerator, const Int128& denominator) + { + sign = numerator.getSign(); + if (sign >= 0) + { + this->numerator = numerator; + } + else + { + this->numerator = -numerator; + } + int dsign = denominator.getSign(); + if (dsign >= 0) + { + this->denominator = denominator; + } + else + { + sign = -sign; + this->denominator = -denominator; + } + isInt64 = false; + } + + int compare(const Rational128& b) const; + + int compare(int64_t b) const; + + btScalar toScalar() const + { + return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar()); + } + }; + + class PointR128 + { + public: + Int128 x; + Int128 y; + Int128 z; + Int128 denominator; + + PointR128() + { + } + + PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator) + { + } + + btScalar xvalue() const + { + return x.toScalar() / denominator.toScalar(); + } + + btScalar yvalue() const + { + return y.toScalar() / denominator.toScalar(); + } + + btScalar zvalue() const + { + return z.toScalar() / denominator.toScalar(); + } + }; + + + class Edge; + class Face; + + class Vertex + { + public: + Vertex* next; + Vertex* prev; + Edge* edges; + Face* firstNearbyFace; + Face* lastNearbyFace; + PointR128 point128; + Point32 point; + int copy; + + Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1) + { + } + +#ifdef DEBUG_CONVEX_HULL + void print() + { + printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z); + } + + void printGraph(); +#endif + + Point32 operator-(const Vertex& b) const + { + return point - b.point; + } + + Rational128 dot(const Point64& b) const + { + return (point.index >= 0) ? Rational128(point.dot(b)) + : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator); + } + + btScalar xvalue() const + { + return (point.index >= 0) ? btScalar(point.x) : point128.xvalue(); + } + + btScalar yvalue() const + { + return (point.index >= 0) ? btScalar(point.y) : point128.yvalue(); + } + + btScalar zvalue() const + { + return (point.index >= 0) ? btScalar(point.z) : point128.zvalue(); + } + + void receiveNearbyFaces(Vertex* src) + { + if (lastNearbyFace) + { + lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace; + } + else + { + firstNearbyFace = src->firstNearbyFace; + } + if (src->lastNearbyFace) + { + lastNearbyFace = src->lastNearbyFace; + } + for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex) + { + btAssert(f->nearbyVertex == src); + f->nearbyVertex = this; + } + src->firstNearbyFace = NULL; + src->lastNearbyFace = NULL; + } + }; + + + class Edge + { + public: + Edge* next; + Edge* prev; + Edge* reverse; + Vertex* target; + Face* face; + int copy; + + ~Edge() + { + next = NULL; + prev = NULL; + reverse = NULL; + target = NULL; + face = NULL; + } + + void link(Edge* n) + { + btAssert(reverse->target == n->reverse->target); + next = n; + n->prev = this; + } + +#ifdef DEBUG_CONVEX_HULL + void print() + { + printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev, + reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z); + } +#endif + }; + + class Face + { + public: + Face* next; + Vertex* nearbyVertex; + Face* nextWithSameNearbyVertex; + Point32 origin; + Point32 dir0; + Point32 dir1; + + Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL) + { + } + + void init(Vertex* a, Vertex* b, Vertex* c) + { + nearbyVertex = a; + origin = a->point; + dir0 = *b - *a; + dir1 = *c - *a; + if (a->lastNearbyFace) + { + a->lastNearbyFace->nextWithSameNearbyVertex = this; + } + else + { + a->firstNearbyFace = this; + } + a->lastNearbyFace = this; + } + + Point64 getNormal() + { + return dir0.cross(dir1); + } + }; + + template class DMul + { + private: + static uint32_t high(uint64_t value) + { + return (uint32_t) (value >> 32); + } + + static uint32_t low(uint64_t value) + { + return (uint32_t) value; + } + + static uint64_t mul(uint32_t a, uint32_t b) + { + return (uint64_t) a * (uint64_t) b; + } + + static void shlHalf(uint64_t& value) + { + value <<= 32; + } + + static uint64_t high(Int128 value) + { + return value.high; + } + + static uint64_t low(Int128 value) + { + return value.low; + } + + static Int128 mul(uint64_t a, uint64_t b) + { + return Int128::mul(a, b); + } + + static void shlHalf(Int128& value) + { + value.high = value.low; + value.low = 0; + } + + public: + + static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh) + { + UWord p00 = mul(low(a), low(b)); + UWord p01 = mul(low(a), high(b)); + UWord p10 = mul(high(a), low(b)); + UWord p11 = mul(high(a), high(b)); + UWord p0110 = UWord(low(p01)) + UWord(low(p10)); + p11 += high(p01); + p11 += high(p10); + p11 += high(p0110); + shlHalf(p0110); + p00 += p0110; + if (p00 < p0110) + { + ++p11; + } + resLow = p00; + resHigh = p11; + } + }; + + private: + + class IntermediateHull + { + public: + Vertex* minXy; + Vertex* maxXy; + Vertex* minYx; + Vertex* maxYx; + + IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL) + { + } + + void print(); + }; + + enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE}; + + template class PoolArray + { + private: + T* array; + int size; + + public: + PoolArray* next; + + PoolArray(int size): size(size), next(NULL) + { + array = (T*) btAlignedAlloc(sizeof(T) * size, 16); + } + + ~PoolArray() + { + btAlignedFree(array); + } + + T* init() + { + T* o = array; + for (int i = 0; i < size; i++, o++) + { + o->next = (i+1 < size) ? o + 1 : NULL; + } + return array; + } + }; + + template class Pool + { + private: + PoolArray* arrays; + PoolArray* nextArray; + T* freeObjects; + int arraySize; + + public: + Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256) + { + } + + ~Pool() + { + while (arrays) + { + PoolArray* p = arrays; + arrays = p->next; + p->~PoolArray(); + btAlignedFree(p); + } + } + + void reset() + { + nextArray = arrays; + freeObjects = NULL; + } + + void setArraySize(int arraySize) + { + this->arraySize = arraySize; + } + + T* newObject() + { + T* o = freeObjects; + if (!o) + { + PoolArray* p = nextArray; + if (p) + { + nextArray = p->next; + } + else + { + p = new(btAlignedAlloc(sizeof(PoolArray), 16)) PoolArray(arraySize); + p->next = arrays; + arrays = p; + } + o = p->init(); + } + freeObjects = o->next; + return new(o) T(); + }; + + void freeObject(T* object) + { + object->~T(); + object->next = freeObjects; + freeObjects = object; + } + }; + + btVector3 scaling; + btVector3 center; + Pool vertexPool; + Pool edgePool; + Pool facePool; + btAlignedObjectArray originalVertices; + int mergeStamp; + int minAxis; + int medAxis; + int maxAxis; + int usedEdgePairs; + int maxUsedEdgePairs; + + static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t); + Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot); + void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1); + + Edge* newEdgePair(Vertex* from, Vertex* to); + + void removeEdgePair(Edge* edge) + { + Edge* n = edge->next; + Edge* r = edge->reverse; + + btAssert(edge->target && r->target); + + if (n != edge) + { + n->prev = edge->prev; + edge->prev->next = n; + r->target->edges = n; + } + else + { + r->target->edges = NULL; + } + + n = r->next; + + if (n != r) + { + n->prev = r->prev; + r->prev->next = n; + edge->target->edges = n; + } + else + { + edge->target->edges = NULL; + } + + edgePool.freeObject(edge); + edgePool.freeObject(r); + usedEdgePairs--; + } + + void computeInternal(int start, int end, IntermediateHull& result); + + bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1); + + void merge(IntermediateHull& h0, IntermediateHull& h1); + + btVector3 toBtVector(const Point32& v); + + btVector3 getBtNormal(Face* face); + + bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray stack); + + public: + Vertex* vertexList; + + void compute(const void* coords, bool doubleCoords, int stride, int count); + + btVector3 getCoordinates(const Vertex* v); + + btScalar shrink(btScalar amount, btScalar clampAmount); +}; + + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const +{ + bool negative = (int64_t) high < 0; + Int128 a = negative ? -*this : *this; + if (b < 0) + { + negative = !negative; + b = -b; + } + Int128 result = mul(a.low, (uint64_t) b); + result.high += a.high * (uint64_t) b; + return negative ? -result : result; +} + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b) +{ + Int128 result; + +#ifdef USE_X86_64_ASM + __asm__ ("imulq %[b]" + : "=a" (result.low), "=d" (result.high) + : "0"(a), [b] "r"(b) + : "cc" ); + return result; + +#else + bool negative = a < 0; + if (negative) + { + a = -a; + } + if (b < 0) + { + negative = !negative; + b = -b; + } + DMul::mul((uint64_t) a, (uint64_t) b, result.low, result.high); + return negative ? -result : result; +#endif +} + +btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b) +{ + Int128 result; + +#ifdef USE_X86_64_ASM + __asm__ ("mulq %[b]" + : "=a" (result.low), "=d" (result.high) + : "0"(a), [b] "r"(b) + : "cc" ); + +#else + DMul::mul(a, b, result.low, result.high); +#endif + + return result; +} + +int btConvexHullInternal::Rational64::compare(const Rational64& b) const +{ + if (sign != b.sign) + { + return sign - b.sign; + } + else if (sign == 0) + { + return 0; + } + + // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0; + +#ifdef USE_X86_64_ASM + + int result; + int64_t tmp; + int64_t dummy; + __asm__ ("mulq %[bn]\n\t" + "movq %%rax, %[tmp]\n\t" + "movq %%rdx, %%rbx\n\t" + "movq %[tn], %%rax\n\t" + "mulq %[bd]\n\t" + "subq %[tmp], %%rax\n\t" + "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator" + "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise + "orq %%rdx, %%rax\n\t" + "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero + "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference) + "shll $16, %%ebx\n\t" // ebx has same sign as difference + : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy) + : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator) + : "%rdx", "cc" ); + return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero) + // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero) + : 0; + +#else + + return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator)); + +#endif +} + +int btConvexHullInternal::Rational128::compare(const Rational128& b) const +{ + if (sign != b.sign) + { + return sign - b.sign; + } + else if (sign == 0) + { + return 0; + } + if (isInt64) + { + return -b.compare(sign * (int64_t) numerator.low); + } + + Int128 nbdLow, nbdHigh, dbnLow, dbnHigh; + DMul::mul(numerator, b.denominator, nbdLow, nbdHigh); + DMul::mul(denominator, b.numerator, dbnLow, dbnHigh); + + int cmp = nbdHigh.ucmp(dbnHigh); + if (cmp) + { + return cmp * sign; + } + return nbdLow.ucmp(dbnLow) * sign; +} + +int btConvexHullInternal::Rational128::compare(int64_t b) const +{ + if (isInt64) + { + int64_t a = sign * (int64_t) numerator.low; + return (a > b) ? 1 : (a < b) ? -1 : 0; + } + if (b > 0) + { + if (sign <= 0) + { + return -1; + } + } + else if (b < 0) + { + if (sign >= 0) + { + return 1; + } + b = -b; + } + else + { + return sign; + } + + return numerator.ucmp(denominator * b) * sign; +} + + +btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to) +{ + btAssert(from && to); + Edge* e = edgePool.newObject(); + Edge* r = edgePool.newObject(); + e->reverse = r; + r->reverse = e; + e->copy = mergeStamp; + r->copy = mergeStamp; + e->target = to; + r->target = from; + e->face = NULL; + r->face = NULL; + usedEdgePairs++; + if (usedEdgePairs > maxUsedEdgePairs) + { + maxUsedEdgePairs = usedEdgePairs; + } + return e; +} + +bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1) +{ + Vertex* v0 = h0.maxYx; + Vertex* v1 = h1.minYx; + if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y)) + { + btAssert(v0->point.z < v1->point.z); + Vertex* v1p = v1->prev; + if (v1p == v1) + { + c0 = v0; + if (v1->edges) + { + btAssert(v1->edges->next == v1->edges); + v1 = v1->edges->target; + btAssert(v1->edges->next == v1->edges); + } + c1 = v1; + return false; + } + Vertex* v1n = v1->next; + v1p->next = v1n; + v1n->prev = v1p; + if (v1 == h1.minXy) + { + if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y))) + { + h1.minXy = v1n; + } + else + { + h1.minXy = v1p; + } + } + if (v1 == h1.maxXy) + { + if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y))) + { + h1.maxXy = v1n; + } + else + { + h1.maxXy = v1p; + } + } + } + + v0 = h0.maxXy; + v1 = h1.maxXy; + Vertex* v00 = NULL; + Vertex* v10 = NULL; + int32_t sign = 1; + + for (int side = 0; side <= 1; side++) + { + int32_t dx = (v1->point.x - v0->point.x) * sign; + if (dx > 0) + { + while (true) + { + int32_t dy = v1->point.y - v0->point.y; + + Vertex* w0 = side ? v0->next : v0->prev; + if (w0 != v0) + { + int32_t dx0 = (w0->point.x - v0->point.x) * sign; + int32_t dy0 = w0->point.y - v0->point.y; + if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0)))) + { + v0 = w0; + dx = (v1->point.x - v0->point.x) * sign; + continue; + } + } + + Vertex* w1 = side ? v1->next : v1->prev; + if (w1 != v1) + { + int32_t dx1 = (w1->point.x - v1->point.x) * sign; + int32_t dy1 = w1->point.y - v1->point.y; + int32_t dxn = (w1->point.x - v0->point.x) * sign; + if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1)))) + { + v1 = w1; + dx = dxn; + continue; + } + } + + break; + } + } + else if (dx < 0) + { + while (true) + { + int32_t dy = v1->point.y - v0->point.y; + + Vertex* w1 = side ? v1->prev : v1->next; + if (w1 != v1) + { + int32_t dx1 = (w1->point.x - v1->point.x) * sign; + int32_t dy1 = w1->point.y - v1->point.y; + if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1)))) + { + v1 = w1; + dx = (v1->point.x - v0->point.x) * sign; + continue; + } + } + + Vertex* w0 = side ? v0->prev : v0->next; + if (w0 != v0) + { + int32_t dx0 = (w0->point.x - v0->point.x) * sign; + int32_t dy0 = w0->point.y - v0->point.y; + int32_t dxn = (v1->point.x - w0->point.x) * sign; + if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0)))) + { + v0 = w0; + dx = dxn; + continue; + } + } + + break; + } + } + else + { + int32_t x = v0->point.x; + int32_t y0 = v0->point.y; + Vertex* w0 = v0; + Vertex* t; + while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0)) + { + w0 = t; + y0 = t->point.y; + } + v0 = w0; + + int32_t y1 = v1->point.y; + Vertex* w1 = v1; + while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1)) + { + w1 = t; + y1 = t->point.y; + } + v1 = w1; + } + + if (side == 0) + { + v00 = v0; + v10 = v1; + + v0 = h0.minXy; + v1 = h1.minXy; + sign = -1; + } + } + + v0->prev = v1; + v1->next = v0; + + v00->next = v10; + v10->prev = v00; + + if (h1.minXy->point.x < h0.minXy->point.x) + { + h0.minXy = h1.minXy; + } + if (h1.maxXy->point.x >= h0.maxXy->point.x) + { + h0.maxXy = h1.maxXy; + } + + h0.maxYx = h1.maxYx; + + c0 = v00; + c1 = v10; + + return true; +} + +void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result) +{ + int n = end - start; + switch (n) + { + case 0: + result.minXy = NULL; + result.maxXy = NULL; + result.minYx = NULL; + result.maxYx = NULL; + return; + case 2: + { + Vertex* v = originalVertices[start]; + Vertex* w = v + 1; + if (v->point != w->point) + { + int32_t dx = v->point.x - w->point.x; + int32_t dy = v->point.y - w->point.y; + + if ((dx == 0) && (dy == 0)) + { + if (v->point.z > w->point.z) + { + Vertex* t = w; + w = v; + v = t; + } + btAssert(v->point.z < w->point.z); + v->next = v; + v->prev = v; + result.minXy = v; + result.maxXy = v; + result.minYx = v; + result.maxYx = v; + } + else + { + v->next = w; + v->prev = w; + w->next = v; + w->prev = v; + + if ((dx < 0) || ((dx == 0) && (dy < 0))) + { + result.minXy = v; + result.maxXy = w; + } + else + { + result.minXy = w; + result.maxXy = v; + } + + if ((dy < 0) || ((dy == 0) && (dx < 0))) + { + result.minYx = v; + result.maxYx = w; + } + else + { + result.minYx = w; + result.maxYx = v; + } + } + + Edge* e = newEdgePair(v, w); + e->link(e); + v->edges = e; + + e = e->reverse; + e->link(e); + w->edges = e; + + return; + } + } + // lint -fallthrough + case 1: + { + Vertex* v = originalVertices[start]; + v->edges = NULL; + v->next = v; + v->prev = v; + + result.minXy = v; + result.maxXy = v; + result.minYx = v; + result.maxYx = v; + + return; + } + } + + int split0 = start + n / 2; + Point32 p = originalVertices[split0-1]->point; + int split1 = split0; + while ((split1 < end) && (originalVertices[split1]->point == p)) + { + split1++; + } + computeInternal(start, split0, result); + IntermediateHull hull1; + computeInternal(split1, end, hull1); +#ifdef DEBUG_CONVEX_HULL + printf("\n\nMerge\n"); + result.print(); + hull1.print(); +#endif + merge(result, hull1); +#ifdef DEBUG_CONVEX_HULL + printf("\n Result\n"); + result.print(); +#endif +} + +#ifdef DEBUG_CONVEX_HULL +void btConvexHullInternal::IntermediateHull::print() +{ + printf(" Hull\n"); + for (Vertex* v = minXy; v; ) + { + printf(" "); + v->print(); + if (v == maxXy) + { + printf(" maxXy"); + } + if (v == minYx) + { + printf(" minYx"); + } + if (v == maxYx) + { + printf(" maxYx"); + } + if (v->next->prev != v) + { + printf(" Inconsistency"); + } + printf("\n"); + v = v->next; + if (v == minXy) + { + break; + } + } + if (minXy) + { + minXy->copy = (minXy->copy == -1) ? -2 : -1; + minXy->printGraph(); + } +} + +void btConvexHullInternal::Vertex::printGraph() +{ + print(); + printf("\nEdges\n"); + Edge* e = edges; + if (e) + { + do + { + e->print(); + printf("\n"); + e = e->next; + } while (e != edges); + do + { + Vertex* v = e->target; + if (v->copy != copy) + { + v->copy = copy; + v->printGraph(); + } + e = e->next; + } while (e != edges); + } +} +#endif + +btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t) +{ + btAssert(prev->reverse->target == next->reverse->target); + if (prev->next == next) + { + if (prev->prev == next) + { + Point64 n = t.cross(s); + Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target); + btAssert(!m.isZero()); + int64_t dot = n.dot(m); + btAssert(dot != 0); + return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE; + } + return COUNTER_CLOCKWISE; + } + else if (prev->prev == next) + { + return CLOCKWISE; + } + else + { + return NONE; + } +} + +btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot) +{ + Edge* minEdge = NULL; + +#ifdef DEBUG_CONVEX_HULL + printf("find max edge for %d\n", start->point.index); +#endif + Edge* e = start->edges; + if (e) + { + do + { + if (e->copy > mergeStamp) + { + Point32 t = *e->target - *start; + Rational64 cot(t.dot(sxrxs), t.dot(rxs)); +#ifdef DEBUG_CONVEX_HULL + printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN()); + e->print(); +#endif + if (cot.isNaN()) + { + btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0)); + } + else + { + int cmp; + if (minEdge == NULL) + { + minCot = cot; + minEdge = e; + } + else if ((cmp = cot.compare(minCot)) < 0) + { + minCot = cot; + minEdge = e; + } + else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE))) + { + minEdge = e; + } + } +#ifdef DEBUG_CONVEX_HULL + printf("\n"); +#endif + } + e = e->next; + } while (e != start->edges); + } + return minEdge; +} + +void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1) +{ + Edge* start0 = e0; + Edge* start1 = e1; + Point32 et0 = start0 ? start0->target->point : c0->point; + Point32 et1 = start1 ? start1->target->point : c1->point; + Point32 s = c1->point - c0->point; + Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s); + int64_t dist = c0->point.dot(normal); + btAssert(!start1 || (start1->target->point.dot(normal) == dist)); + Point64 perp = s.cross(normal); + btAssert(!perp.isZero()); + +#ifdef DEBUG_CONVEX_HULL + printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1); +#endif + + int64_t maxDot0 = et0.dot(perp); + if (e0) + { + while (e0->target != stop0) + { + Edge* e = e0->reverse->prev; + if (e->target->point.dot(normal) < dist) + { + break; + } + btAssert(e->target->point.dot(normal) == dist); + if (e->copy == mergeStamp) + { + break; + } + int64_t dot = e->target->point.dot(perp); + if (dot <= maxDot0) + { + break; + } + maxDot0 = dot; + e0 = e; + et0 = e->target->point; + } + } + + int64_t maxDot1 = et1.dot(perp); + if (e1) + { + while (e1->target != stop1) + { + Edge* e = e1->reverse->next; + if (e->target->point.dot(normal) < dist) + { + break; + } + btAssert(e->target->point.dot(normal) == dist); + if (e->copy == mergeStamp) + { + break; + } + int64_t dot = e->target->point.dot(perp); + if (dot <= maxDot1) + { + break; + } + maxDot1 = dot; + e1 = e; + et1 = e->target->point; + } + } + +#ifdef DEBUG_CONVEX_HULL + printf(" Starting at %d %d\n", et0.index, et1.index); +#endif + + int64_t dx = maxDot1 - maxDot0; + if (dx > 0) + { + while (true) + { + int64_t dy = (et1 - et0).dot(s); + + if (e0 && (e0->target != stop0)) + { + Edge* f0 = e0->next->reverse; + if (f0->copy > mergeStamp) + { + int64_t dx0 = (f0->target->point - et0).dot(perp); + int64_t dy0 = (f0->target->point - et0).dot(s); + if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0))) + { + et0 = f0->target->point; + dx = (et1 - et0).dot(perp); + e0 = (e0 == start0) ? NULL : f0; + continue; + } + } + } + + if (e1 && (e1->target != stop1)) + { + Edge* f1 = e1->reverse->next; + if (f1->copy > mergeStamp) + { + Point32 d1 = f1->target->point - et1; + if (d1.dot(normal) == 0) + { + int64_t dx1 = d1.dot(perp); + int64_t dy1 = d1.dot(s); + int64_t dxn = (f1->target->point - et0).dot(perp); + if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0)))) + { + e1 = f1; + et1 = e1->target->point; + dx = dxn; + continue; + } + } + else + { + btAssert((e1 == start1) && (d1.dot(normal) < 0)); + } + } + } + + break; + } + } + else if (dx < 0) + { + while (true) + { + int64_t dy = (et1 - et0).dot(s); + + if (e1 && (e1->target != stop1)) + { + Edge* f1 = e1->prev->reverse; + if (f1->copy > mergeStamp) + { + int64_t dx1 = (f1->target->point - et1).dot(perp); + int64_t dy1 = (f1->target->point - et1).dot(s); + if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0))) + { + et1 = f1->target->point; + dx = (et1 - et0).dot(perp); + e1 = (e1 == start1) ? NULL : f1; + continue; + } + } + } + + if (e0 && (e0->target != stop0)) + { + Edge* f0 = e0->reverse->prev; + if (f0->copy > mergeStamp) + { + Point32 d0 = f0->target->point - et0; + if (d0.dot(normal) == 0) + { + int64_t dx0 = d0.dot(perp); + int64_t dy0 = d0.dot(s); + int64_t dxn = (et1 - f0->target->point).dot(perp); + if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0)))) + { + e0 = f0; + et0 = e0->target->point; + dx = dxn; + continue; + } + } + else + { + btAssert((e0 == start0) && (d0.dot(normal) < 0)); + } + } + } + + break; + } + } +#ifdef DEBUG_CONVEX_HULL + printf(" Advanced edges to %d %d\n", et0.index, et1.index); +#endif +} + + +void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1) +{ + if (!h1.maxXy) + { + return; + } + if (!h0.maxXy) + { + h0 = h1; + return; + } + + mergeStamp--; + + Vertex* c0 = NULL; + Edge* toPrev0 = NULL; + Edge* firstNew0 = NULL; + Edge* pendingHead0 = NULL; + Edge* pendingTail0 = NULL; + Vertex* c1 = NULL; + Edge* toPrev1 = NULL; + Edge* firstNew1 = NULL; + Edge* pendingHead1 = NULL; + Edge* pendingTail1 = NULL; + Point32 prevPoint; + + if (mergeProjection(h0, h1, c0, c1)) + { + Point32 s = *c1 - *c0; + Point64 normal = Point32(0, 0, -1).cross(s); + Point64 t = s.cross(normal); + btAssert(!t.isZero()); + + Edge* e = c0->edges; + Edge* start0 = NULL; + if (e) + { + do + { + int64_t dot = (*e->target - *c0).dot(normal); + btAssert(dot <= 0); + if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) + { + if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) + { + start0 = e; + } + } + e = e->next; + } while (e != c0->edges); + } + + e = c1->edges; + Edge* start1 = NULL; + if (e) + { + do + { + int64_t dot = (*e->target - *c1).dot(normal); + btAssert(dot <= 0); + if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) + { + if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) + { + start1 = e; + } + } + e = e->next; + } while (e != c1->edges); + } + + if (start0 || start1) + { + findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL); + if (start0) + { + c0 = start0->target; + } + if (start1) + { + c1 = start1->target; + } + } + + prevPoint = c1->point; + prevPoint.z++; + } + else + { + prevPoint = c1->point; + prevPoint.x++; + } + + Vertex* first0 = c0; + Vertex* first1 = c1; + bool firstRun = true; + + while (true) + { + Point32 s = *c1 - *c0; + Point32 r = prevPoint - c0->point; + Point64 rxs = r.cross(s); + Point64 sxrxs = s.cross(rxs); + +#ifdef DEBUG_CONVEX_HULL + printf("\n Checking %d %d\n", c0->point.index, c1->point.index); +#endif + Rational64 minCot0(0, 0); + Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0); + Rational64 minCot1(0, 0); + Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1); + if (!min0 && !min1) + { + Edge* e = newEdgePair(c0, c1); + e->link(e); + c0->edges = e; + + e = e->reverse; + e->link(e); + c1->edges = e; + return; + } + else + { + int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1); +#ifdef DEBUG_CONVEX_HULL + printf(" -> Result %d\n", cmp); +#endif + if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity())) + { + Edge* e = newEdgePair(c0, c1); + if (pendingTail0) + { + pendingTail0->prev = e; + } + else + { + pendingHead0 = e; + } + e->next = pendingTail0; + pendingTail0 = e; + + e = e->reverse; + if (pendingTail1) + { + pendingTail1->next = e; + } + else + { + pendingHead1 = e; + } + e->prev = pendingTail1; + pendingTail1 = e; + } + + Edge* e0 = min0; + Edge* e1 = min1; + +#ifdef DEBUG_CONVEX_HULL + printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1); +#endif + + if (cmp == 0) + { + findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL); + } + + if ((cmp >= 0) && e1) + { + if (toPrev1) + { + for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n) + { + n = e->next; + removeEdgePair(e); + } + } + + if (pendingTail1) + { + if (toPrev1) + { + toPrev1->link(pendingHead1); + } + else + { + min1->prev->link(pendingHead1); + firstNew1 = pendingHead1; + } + pendingTail1->link(min1); + pendingHead1 = NULL; + pendingTail1 = NULL; + } + else if (!toPrev1) + { + firstNew1 = min1; + } + + prevPoint = c1->point; + c1 = e1->target; + toPrev1 = e1->reverse; + } + + if ((cmp <= 0) && e0) + { + if (toPrev0) + { + for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n) + { + n = e->prev; + removeEdgePair(e); + } + } + + if (pendingTail0) + { + if (toPrev0) + { + pendingHead0->link(toPrev0); + } + else + { + pendingHead0->link(min0->next); + firstNew0 = pendingHead0; + } + min0->link(pendingTail0); + pendingHead0 = NULL; + pendingTail0 = NULL; + } + else if (!toPrev0) + { + firstNew0 = min0; + } + + prevPoint = c0->point; + c0 = e0->target; + toPrev0 = e0->reverse; + } + } + + if ((c0 == first0) && (c1 == first1)) + { + if (toPrev0 == NULL) + { + pendingHead0->link(pendingTail0); + c0->edges = pendingTail0; + } + else + { + for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n) + { + n = e->prev; + removeEdgePair(e); + } + if (pendingTail0) + { + pendingHead0->link(toPrev0); + firstNew0->link(pendingTail0); + } + } + + if (toPrev1 == NULL) + { + pendingTail1->link(pendingHead1); + c1->edges = pendingTail1; + } + else + { + for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n) + { + n = e->next; + removeEdgePair(e); + } + if (pendingTail1) + { + toPrev1->link(pendingHead1); + pendingTail1->link(firstNew1); + } + } + + return; + } + + firstRun = false; + } +} + + +static bool pointCmp(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q) +{ + return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z)))); +} + +void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count) +{ + btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30)); + const char* ptr = (const char*) coords; + if (doubleCoords) + { + for (int i = 0; i < count; i++) + { + const double* v = (const double*) ptr; + btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); + ptr += stride; + min.setMin(p); + max.setMax(p); + } + } + else + { + for (int i = 0; i < count; i++) + { + const float* v = (const float*) ptr; + btVector3 p(v[0], v[1], v[2]); + ptr += stride; + min.setMin(p); + max.setMax(p); + } + } + + btVector3 s = max - min; + maxAxis = s.maxAxis(); + minAxis = s.minAxis(); + if (minAxis == maxAxis) + { + minAxis = (maxAxis + 1) % 3; + } + medAxis = 3 - maxAxis - minAxis; + + s /= btScalar(10216); + if (((medAxis + 1) % 3) != maxAxis) + { + s *= -1; + } + scaling = s; + + if (s[0] != 0) + { + s[0] = btScalar(1) / s[0]; + } + if (s[1] != 0) + { + s[1] = btScalar(1) / s[1]; + } + if (s[2] != 0) + { + s[2] = btScalar(1) / s[2]; + } + + center = (min + max) * btScalar(0.5); + + btAlignedObjectArray points; + points.resize(count); + ptr = (const char*) coords; + if (doubleCoords) + { + for (int i = 0; i < count; i++) + { + const double* v = (const double*) ptr; + btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); + ptr += stride; + p = (p - center) * s; + points[i].x = (int32_t) p[medAxis]; + points[i].y = (int32_t) p[maxAxis]; + points[i].z = (int32_t) p[minAxis]; + points[i].index = i; + } + } + else + { + for (int i = 0; i < count; i++) + { + const float* v = (const float*) ptr; + btVector3 p(v[0], v[1], v[2]); + ptr += stride; + p = (p - center) * s; + points[i].x = (int32_t) p[medAxis]; + points[i].y = (int32_t) p[maxAxis]; + points[i].z = (int32_t) p[minAxis]; + points[i].index = i; + } + } + points.quickSort(pointCmp); + + vertexPool.reset(); + vertexPool.setArraySize(count); + originalVertices.resize(count); + for (int i = 0; i < count; i++) + { + Vertex* v = vertexPool.newObject(); + v->edges = NULL; + v->point = points[i]; + v->copy = -1; + originalVertices[i] = v; + } + + points.clear(); + + edgePool.reset(); + edgePool.setArraySize(6 * count); + + usedEdgePairs = 0; + maxUsedEdgePairs = 0; + + mergeStamp = -3; + + IntermediateHull hull; + computeInternal(0, count, hull); + vertexList = hull.minXy; +#ifdef DEBUG_CONVEX_HULL + printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count); +#endif +} + +btVector3 btConvexHullInternal::toBtVector(const Point32& v) +{ + btVector3 p; + p[medAxis] = btScalar(v.x); + p[maxAxis] = btScalar(v.y); + p[minAxis] = btScalar(v.z); + return p * scaling; +} + +btVector3 btConvexHullInternal::getBtNormal(Face* face) +{ + return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized(); +} + +btVector3 btConvexHullInternal::getCoordinates(const Vertex* v) +{ + btVector3 p; + p[medAxis] = v->xvalue(); + p[maxAxis] = v->yvalue(); + p[minAxis] = v->zvalue(); + return p * scaling + center; +} + +btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount) +{ + if (!vertexList) + { + return 0; + } + int stamp = --mergeStamp; + btAlignedObjectArray stack; + vertexList->copy = stamp; + stack.push_back(vertexList); + btAlignedObjectArray faces; + + Point32 ref = vertexList->point; + Int128 hullCenterX(0, 0); + Int128 hullCenterY(0, 0); + Int128 hullCenterZ(0, 0); + Int128 volume(0, 0); + + while (stack.size() > 0) + { + Vertex* v = stack[stack.size() - 1]; + stack.pop_back(); + Edge* e = v->edges; + if (e) + { + do + { + if (e->target->copy != stamp) + { + e->target->copy = stamp; + stack.push_back(e->target); + } + if (e->copy != stamp) + { + Face* face = facePool.newObject(); + face->init(e->target, e->reverse->prev->target, v); + faces.push_back(face); + Edge* f = e; + + Vertex* a = NULL; + Vertex* b = NULL; + do + { + if (a && b) + { + int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref)); + btAssert(vol >= 0); + Point32 c = v->point + a->point + b->point + ref; + hullCenterX += vol * c.x; + hullCenterY += vol * c.y; + hullCenterZ += vol * c.z; + volume += vol; + } + + btAssert(f->copy != stamp); + f->copy = stamp; + f->face = face; + + a = b; + b = f->target; + + f = f->reverse->prev; + } while (f != e); + } + e = e->next; + } while (e != v->edges); + } + } + + if (volume.getSign() <= 0) + { + return 0; + } + + btVector3 hullCenter; + hullCenter[medAxis] = hullCenterX.toScalar(); + hullCenter[maxAxis] = hullCenterY.toScalar(); + hullCenter[minAxis] = hullCenterZ.toScalar(); + hullCenter /= 4 * volume.toScalar(); + hullCenter *= scaling; + + int faceCount = faces.size(); + + if (clampAmount > 0) + { + btScalar minDist = SIMD_INFINITY; + for (int i = 0; i < faceCount; i++) + { + btVector3 normal = getBtNormal(faces[i]); + btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter); + if (dist < minDist) + { + minDist = dist; + } + } + + if (minDist <= 0) + { + return 0; + } + + amount = btMin(amount, minDist * clampAmount); + } + + unsigned int seed = 243703; + for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223) + { + btSwap(faces[i], faces[seed % faceCount]); + } + + for (int i = 0; i < faceCount; i++) + { + if (!shiftFace(faces[i], amount, stack)) + { + return -amount; + } + } + + return amount; +} + +bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray stack) +{ + btVector3 origShift = getBtNormal(face) * -amount; + if (scaling[0] != 0) + { + origShift[0] /= scaling[0]; + } + if (scaling[1] != 0) + { + origShift[1] /= scaling[1]; + } + if (scaling[2] != 0) + { + origShift[2] /= scaling[2]; + } + Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]); + if (shift.isZero()) + { + return true; + } + Point64 normal = face->getNormal(); +#ifdef DEBUG_CONVEX_HULL + printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n", + face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z); +#endif + int64_t origDot = face->origin.dot(normal); + Point32 shiftedOrigin = face->origin + shift; + int64_t shiftedDot = shiftedOrigin.dot(normal); + btAssert(shiftedDot <= origDot); + if (shiftedDot >= origDot) + { + return false; + } + + Edge* intersection = NULL; + + Edge* startEdge = face->nearbyVertex->edges; +#ifdef DEBUG_CONVEX_HULL + printf("Start edge is "); + startEdge->print(); + printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot); +#endif + Rational128 optDot = face->nearbyVertex->dot(normal); + int cmp = optDot.compare(shiftedDot); +#ifdef SHOW_ITERATIONS + int n = 0; +#endif + if (cmp >= 0) + { + Edge* e = startEdge; + do + { +#ifdef SHOW_ITERATIONS + n++; +#endif + Rational128 dot = e->target->dot(normal); + btAssert(dot.compare(origDot) <= 0); +#ifdef DEBUG_CONVEX_HULL + printf("Moving downwards, edge is "); + e->print(); + printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); +#endif + if (dot.compare(optDot) < 0) + { + int c = dot.compare(shiftedDot); + optDot = dot; + e = e->reverse; + startEdge = e; + if (c < 0) + { + intersection = e; + break; + } + cmp = c; + } + e = e->prev; + } while (e != startEdge); + + if (!intersection) + { + return false; + } + } + else + { + Edge* e = startEdge; + do + { +#ifdef SHOW_ITERATIONS + n++; +#endif + Rational128 dot = e->target->dot(normal); + btAssert(dot.compare(origDot) <= 0); +#ifdef DEBUG_CONVEX_HULL + printf("Moving upwards, edge is "); + e->print(); + printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); +#endif + if (dot.compare(optDot) > 0) + { + cmp = dot.compare(shiftedDot); + if (cmp >= 0) + { + intersection = e; + break; + } + optDot = dot; + e = e->reverse; + startEdge = e; + } + e = e->prev; + } while (e != startEdge); + + if (!intersection) + { + return true; + } + } + +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to find initial intersection\n", n); +#endif + + if (cmp == 0) + { + Edge* e = intersection->reverse->next; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (e->target->dot(normal).compare(shiftedDot) <= 0) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + e = e->next; + if (e == intersection->reverse) + { + return true; + } +#ifdef DEBUG_CONVEX_HULL + printf("Checking for outwards edge, current edge is "); + e->print(); + printf("\n"); +#endif + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to check for complete containment\n", n); +#endif + } + + Edge* firstIntersection = NULL; + Edge* faceEdge = NULL; + Edge* firstFaceEdge = NULL; + +#ifdef SHOW_ITERATIONS + int m = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + m++; +#endif +#ifdef DEBUG_CONVEX_HULL + printf("Intersecting edge is "); + intersection->print(); + printf("\n"); +#endif + if (cmp == 0) + { + Edge* e = intersection->reverse->next; + startEdge = e; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + if (e->target->dot(normal).compare(shiftedDot) >= 0) + { + break; + } + intersection = e->reverse; + e = e->next; + if (e == startEdge) + { + return true; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to advance intersection\n", n); +#endif + } + +#ifdef DEBUG_CONVEX_HULL + printf("Advanced intersecting edge to "); + intersection->print(); + printf(", cmp = %d\n", cmp); +#endif + + if (!firstIntersection) + { + firstIntersection = intersection; + } + else if (intersection == firstIntersection) + { + break; + } + + int prevCmp = cmp; + Edge* prevIntersection = intersection; + Edge* prevFaceEdge = faceEdge; + + Edge* e = intersection->reverse; +#ifdef SHOW_ITERATIONS + n = 0; +#endif + while (true) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + e = e->reverse->prev; + btAssert(e != intersection->reverse); + cmp = e->target->dot(normal).compare(shiftedDot); +#ifdef DEBUG_CONVEX_HULL + printf("Testing edge "); + e->print(); + printf(" -> cmp = %d\n", cmp); +#endif + if (cmp >= 0) + { + intersection = e; + break; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to find other intersection of face\n", n); +#endif + + if (cmp > 0) + { + Vertex* removed = intersection->target; + e = intersection->reverse; + if (e->prev == e) + { + removed->edges = NULL; + } + else + { + removed->edges = e->prev; + e->prev->link(e->next); + e->link(e); + } +#ifdef DEBUG_CONVEX_HULL + printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + + Point64 n0 = intersection->face->getNormal(); + Point64 n1 = intersection->reverse->face->getNormal(); + int64_t m00 = face->dir0.dot(n0); + int64_t m01 = face->dir1.dot(n0); + int64_t m10 = face->dir0.dot(n1); + int64_t m11 = face->dir1.dot(n1); + int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0); + int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1); + Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10); + btAssert(det.getSign() != 0); + Vertex* v = vertexPool.newObject(); + v->point.index = -1; + v->copy = -1; + v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x, + Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y, + Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z, + det); + v->point.x = (int32_t) v->point128.xvalue(); + v->point.y = (int32_t) v->point128.yvalue(); + v->point.z = (int32_t) v->point128.zvalue(); + intersection->target = v; + v->edges = e; + + stack.push_back(v); + stack.push_back(removed); + stack.push_back(NULL); + } + + if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target)) + { + faceEdge = newEdgePair(prevIntersection->target, intersection->target); + if (prevCmp == 0) + { + faceEdge->link(prevIntersection->reverse->next); + } + if ((prevCmp == 0) || prevFaceEdge) + { + prevIntersection->reverse->link(faceEdge); + } + if (cmp == 0) + { + intersection->reverse->prev->link(faceEdge->reverse); + } + faceEdge->reverse->link(intersection->reverse); + } + else + { + faceEdge = prevIntersection->reverse->next; + } + + if (prevFaceEdge) + { + if (prevCmp > 0) + { + faceEdge->link(prevFaceEdge->reverse); + } + else if (faceEdge != prevFaceEdge->reverse) + { + stack.push_back(prevFaceEdge->target); + while (faceEdge->next != prevFaceEdge->reverse) + { + Vertex* removed = faceEdge->next->target; + removeEdgePair(faceEdge->next); + stack.push_back(removed); +#ifdef DEBUG_CONVEX_HULL + printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + } + stack.push_back(NULL); + } + } + faceEdge->face = face; + faceEdge->reverse->face = intersection->face; + + if (!firstFaceEdge) + { + firstFaceEdge = faceEdge; + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to process all intersections\n", m); +#endif + + if (cmp > 0) + { + firstFaceEdge->reverse->target = faceEdge->target; + firstIntersection->reverse->link(firstFaceEdge); + firstFaceEdge->link(faceEdge->reverse); + } + else if (firstFaceEdge != faceEdge->reverse) + { + stack.push_back(faceEdge->target); + while (firstFaceEdge->next != faceEdge->reverse) + { + Vertex* removed = firstFaceEdge->next->target; + removeEdgePair(firstFaceEdge->next); + stack.push_back(removed); +#ifdef DEBUG_CONVEX_HULL + printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); +#endif + } + stack.push_back(NULL); + } + + btAssert(stack.size() > 0); + vertexList = stack[0]; + +#ifdef DEBUG_CONVEX_HULL + printf("Removing part\n"); +#endif +#ifdef SHOW_ITERATIONS + n = 0; +#endif + int pos = 0; + while (pos < stack.size()) + { + int end = stack.size(); + while (pos < end) + { + Vertex* kept = stack[pos++]; +#ifdef DEBUG_CONVEX_HULL + kept->print(); +#endif + bool deeper = false; + Vertex* removed; + while ((removed = stack[pos++]) != NULL) + { +#ifdef SHOW_ITERATIONS + n++; +#endif + kept->receiveNearbyFaces(removed); + while (removed->edges) + { + if (!deeper) + { + deeper = true; + stack.push_back(kept); + } + stack.push_back(removed->edges->target); + removeEdgePair(removed->edges); + } + } + if (deeper) + { + stack.push_back(NULL); + } + } + } +#ifdef SHOW_ITERATIONS + printf("Needed %d iterations to remove part\n", n); +#endif + + stack.resize(0); + face->origin = shiftedOrigin; + + return true; +} + + +static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray& vertices) +{ + int index = vertex->copy; + if (index < 0) + { + index = vertices.size(); + vertex->copy = index; + vertices.push_back(vertex); +#ifdef DEBUG_CONVEX_HULL + printf("Vertex %d gets index *%d\n", vertex->point.index, index); +#endif + } + return index; +} + +btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp) +{ + if (count <= 0) + { + vertices.clear(); + edges.clear(); + faces.clear(); + return 0; + } + + btConvexHullInternal hull; + hull.compute(coords, doubleCoords, stride, count); + + btScalar shift = 0; + if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0)) + { + vertices.clear(); + edges.clear(); + faces.clear(); + return shift; + } + + vertices.resize(0); + edges.resize(0); + faces.resize(0); + + btAlignedObjectArray oldVertices; + getVertexCopy(hull.vertexList, oldVertices); + int copied = 0; + while (copied < oldVertices.size()) + { + btConvexHullInternal::Vertex* v = oldVertices[copied]; + vertices.push_back(hull.getCoordinates(v)); + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { + int firstCopy = -1; + int prevCopy = -1; + btConvexHullInternal::Edge* e = firstEdge; + do + { + if (e->copy < 0) + { + int s = edges.size(); + edges.push_back(Edge()); + edges.push_back(Edge()); + Edge* c = &edges[s]; + Edge* r = &edges[s + 1]; + e->copy = s; + e->reverse->copy = s + 1; + c->reverse = 1; + r->reverse = -1; + c->targetVertex = getVertexCopy(e->target, oldVertices); + r->targetVertex = copied; +#ifdef DEBUG_CONVEX_HULL + printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex()); +#endif + } + if (prevCopy >= 0) + { + edges[e->copy].next = prevCopy - e->copy; + } + else + { + firstCopy = e->copy; + } + prevCopy = e->copy; + e = e->next; + } while (e != firstEdge); + edges[firstCopy].next = prevCopy - firstCopy; + } + copied++; + } + + for (int i = 0; i < copied; i++) + { + btConvexHullInternal::Vertex* v = oldVertices[i]; + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { + btConvexHullInternal::Edge* e = firstEdge; + do + { + if (e->copy >= 0) + { +#ifdef DEBUG_CONVEX_HULL + printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex()); +#endif + faces.push_back(e->copy); + btConvexHullInternal::Edge* f = e; + do + { +#ifdef DEBUG_CONVEX_HULL + printf(" Face *%d\n", edges[f->copy].getTargetVertex()); +#endif + f->copy = -1; + f = f->reverse->prev; + } while (f != e); + } + e = e->next; + } while (e != firstEdge); + } + } + + return shift; +} + + + + + diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.h b/extern/bullet2/src/LinearMath/btConvexHullComputer.h new file mode 100644 index 00000000000..7240ac4fb52 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.h @@ -0,0 +1,103 @@ +/* +Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_HULL_COMPUTER_H +#define BT_CONVEX_HULL_COMPUTER_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +/// Convex hull implementation based on Preparata and Hong +/// See http://code.google.com/p/bullet/issues/detail?id=275 +/// Ole Kniemeyer, MAXON Computer GmbH +class btConvexHullComputer +{ + private: + btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp); + + public: + + class Edge + { + private: + int next; + int reverse; + int targetVertex; + + friend class btConvexHullComputer; + + public: + int getSourceVertex() const + { + return (this + reverse)->targetVertex; + } + + int getTargetVertex() const + { + return targetVertex; + } + + const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex + { + return this + next; + } + + const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face + { + return (this + reverse)->getNextEdgeOfVertex(); + } + + const Edge* getReverseEdge() const + { + return this + reverse; + } + }; + + + // Vertices of the output hull + btAlignedObjectArray vertices; + + // Edges of the output hull + btAlignedObjectArray edges; + + // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons + btAlignedObjectArray faces; + + /* + Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes + between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken + by that amount (each face is moved by "shrink" length units towards the center along its normal). + If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius" + is the minimum distance of a face to the center of the convex hull. + + The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large + that the resulting convex hull is empty. + + The output convex hull can be found in the member variables "vertices", "edges", "faces". + */ + btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) + { + return compute(coords, false, stride, count, shrink, shrinkClamp); + } + + // same as above, but double precision + btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) + { + return compute(coords, true, stride, count, shrink, shrinkClamp); + } +}; + + +#endif //BT_CONVEX_HULL_COMPUTER_H + diff --git a/extern/bullet2/src/LinearMath/btDefaultMotionState.h b/extern/bullet2/src/LinearMath/btDefaultMotionState.h index 7858a10d219..a6b7ef15ac8 100644 --- a/extern/bullet2/src/LinearMath/btDefaultMotionState.h +++ b/extern/bullet2/src/LinearMath/btDefaultMotionState.h @@ -1,5 +1,5 @@ -#ifndef DEFAULT_MOTION_STATE_H -#define DEFAULT_MOTION_STATE_H +#ifndef BT_DEFAULT_MOTION_STATE_H +#define BT_DEFAULT_MOTION_STATE_H #include "btMotionState.h" @@ -37,4 +37,4 @@ struct btDefaultMotionState : public btMotionState }; -#endif //DEFAULT_MOTION_STATE_H +#endif //BT_DEFAULT_MOTION_STATE_H diff --git a/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h b/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h new file mode 100644 index 00000000000..d7bd3eb8911 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h @@ -0,0 +1,110 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef GRAHAM_SCAN_2D_CONVEX_HULL_H +#define GRAHAM_SCAN_2D_CONVEX_HULL_H + + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +struct GrahamVector2 : public btVector3 +{ + GrahamVector2(const btVector3& org, int orgIndex) + :btVector3(org), + m_orgIndex(orgIndex) + { + } + btScalar m_angle; + int m_orgIndex; +}; + + +struct btAngleCompareFunc { + btVector3 m_anchor; + btAngleCompareFunc(const btVector3& anchor) + : m_anchor(anchor) + { + } + bool operator()(const GrahamVector2& a, const GrahamVector2& b) const { + if (a.m_angle != b.m_angle) + return a.m_angle < b.m_angle; + else + { + btScalar al = (a-m_anchor).length2(); + btScalar bl = (b-m_anchor).length2(); + if (al != bl) + return al < bl; + else + { + return a.m_orgIndex < b.m_orgIndex; + } + } + } +}; + +inline void GrahamScanConvexHull2D(btAlignedObjectArray& originalPoints, btAlignedObjectArray& hull) +{ + if (originalPoints.size()<=1) + { + for (int i=0;i1) { + btVector3& a = hull[hull.size()-2]; + btVector3& b = hull[hull.size()-1]; + isConvex = btCross(a-b,a-originalPoints[i]).dot(btVector3(0,0,1))> 0; + if (!isConvex) + hull.pop_back(); + else + hull.push_back(originalPoints[i]); + } + } +} + +#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H diff --git a/extern/bullet2/src/LinearMath/btHashMap.h b/extern/bullet2/src/LinearMath/btHashMap.h index e3302b5e9ff..ce07db3ac6b 100644 --- a/extern/bullet2/src/LinearMath/btHashMap.h +++ b/extern/bullet2/src/LinearMath/btHashMap.h @@ -1,3 +1,19 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + #ifndef BT_HASH_MAP_H #define BT_HASH_MAP_H diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h index 48c15806a7d..935502f844f 100644 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -14,8 +14,8 @@ subject to the following restrictions: */ -#ifndef IDEBUG_DRAW__H -#define IDEBUG_DRAW__H +#ifndef BT_IDEBUG_DRAW__H +#define BT_IDEBUG_DRAW__H #include "btVector3.h" #include "btTransform.h" @@ -46,6 +46,7 @@ class btIDebugDraw DBG_DrawConstraints = (1 << 11), DBG_DrawConstraintLimits = (1 << 12), DBG_FastWireframe = (1<<13), + DBG_DrawNormals = (1<<14), DBG_MAX_DEBUG_DRAW_MODE }; @@ -413,5 +414,5 @@ class btIDebugDraw }; -#endif //IDEBUG_DRAW__H +#endif //BT_IDEBUG_DRAW__H diff --git a/extern/bullet2/src/LinearMath/btList.h b/extern/bullet2/src/LinearMath/btList.h index c87b47faf2b..eec80a7064b 100644 --- a/extern/bullet2/src/LinearMath/btList.h +++ b/extern/bullet2/src/LinearMath/btList.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef GEN_LIST_H -#define GEN_LIST_H +#ifndef BT_GEN_LIST_H +#define BT_GEN_LIST_H class btGEN_Link { public: @@ -67,7 +67,7 @@ private: btGEN_Link m_tail; }; -#endif +#endif //BT_GEN_LIST_H diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h index 80601c1e232..5b436e9ba4e 100644 --- a/extern/bullet2/src/LinearMath/btMinMax.h +++ b/extern/bullet2/src/LinearMath/btMinMax.h @@ -14,10 +14,10 @@ subject to the following restrictions: -#ifndef GEN_MINMAX_H -#define GEN_MINMAX_H +#ifndef BT_GEN_MINMAX_H +#define BT_GEN_MINMAX_H -#include "LinearMath/btScalar.h" +#include "btScalar.h" template SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) @@ -68,4 +68,4 @@ SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) } } -#endif +#endif //BT_GEN_MINMAX_H diff --git a/extern/bullet2/src/LinearMath/btPoint3.h b/extern/bullet2/src/LinearMath/btPoint3.h deleted file mode 100644 index a2020e26d12..00000000000 --- a/extern/bullet2/src/LinearMath/btPoint3.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - - -#ifndef btPoint3_H -#define btPoint3_H - -#include "btVector3.h" - -typedef btVector3 btPoint3; - -#endif diff --git a/extern/bullet2/src/LinearMath/btPoolAllocator.h b/extern/bullet2/src/LinearMath/btPoolAllocator.h index e3b4be9b155..ef2084537a2 100644 --- a/extern/bullet2/src/LinearMath/btPoolAllocator.h +++ b/extern/bullet2/src/LinearMath/btPoolAllocator.h @@ -62,6 +62,11 @@ public: return m_maxElements - m_freeCount; } + int getMaxCount() const + { + return m_maxElements; + } + void* allocate(int size) { // release mode fix diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h index c657afd2bb1..d5e9daa45a2 100644 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -13,8 +13,8 @@ subject to the following restrictions: */ -#ifndef SIMD_QUADWORD_H -#define SIMD_QUADWORD_H +#ifndef BT_SIMD_QUADWORD_H +#define BT_SIMD_QUADWORD_H #include "btScalar.h" #include "btMinMax.h" @@ -177,4 +177,4 @@ protected: }; -#endif //SIMD_QUADWORD_H +#endif //BT_SIMD_QUADWORD_H diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h index 15cf5f868d9..ee79f6eaeee 100644 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef SIMD__QUATERNION_H_ -#define SIMD__QUATERNION_H_ +#ifndef BT_SIMD__QUATERNION_H_ +#define BT_SIMD__QUATERNION_H_ #include "btVector3.h" @@ -212,11 +212,12 @@ public: /**@brief Return the axis of the rotation represented by this quaternion */ btVector3 getAxis() const { - btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.)); + btScalar s_squared = 1.f-m_floats[3]*m_floats[3]; + if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero return btVector3(1.0, 0.0, 0.0); // Arbitrary - btScalar s = btSqrt(s_squared); - return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s); + btScalar s = 1.f/btSqrt(s_squared); + return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s); } /**@brief Return the inverse of this quaternion */ @@ -279,23 +280,25 @@ public: * Slerp interpolates assuming constant velocity. */ btQuaternion slerp(const btQuaternion& q, const btScalar& t) const { - btScalar theta = angle(q); - if (theta != btScalar(0.0)) + btScalar magnitude = btSqrt(length2() * q.length2()); + btAssert(magnitude > btScalar(0)); + + btScalar product = dot(q) / magnitude; + if (btFabs(product) != btScalar(1)) { - btScalar d = btScalar(1.0) / btSin(theta); - btScalar s0 = btSin((btScalar(1.0) - t) * theta); - btScalar s1 = btSin(t * theta); - if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp - return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d, - (m_floats[1] * s0 + -q.y() * s1) * d, - (m_floats[2] * s0 + -q.z() * s1) * d, - (m_floats[3] * s0 + -q.m_floats[3] * s1) * d); - else - return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d, - (m_floats[1] * s0 + q.y() * s1) * d, - (m_floats[2] * s0 + q.z() * s1) * d, - (m_floats[3] * s0 + q.m_floats[3] * s1) * d); - + // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp + const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1); + + const btScalar theta = btAcos(sign * product); + const btScalar s1 = btSin(sign * t * theta); + const btScalar d = btScalar(1.0) / btSin(theta); + const btScalar s0 = btSin((btScalar(1.0) - t) * theta); + + return btQuaternion( + (m_floats[0] * s0 + q.x() * s1) * d, + (m_floats[1] * s0 + q.y() * s1) * d, + (m_floats[2] * s0 + q.z() * s1) * d, + (m_floats[3] * s0 + q.m_floats[3] * s1) * d); } else { @@ -315,12 +318,6 @@ public: }; -/**@brief Return the negative of a quaternion */ -SIMD_FORCE_INLINE btQuaternion -operator-(const btQuaternion& q) -{ - return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w()); -} @@ -426,7 +423,7 @@ shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) return shortestArcQuat(v0,v1); } -#endif +#endif //BT_SIMD__QUATERNION_H_ diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp index 14534068a0d..544aee89d02 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.cpp +++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp @@ -276,7 +276,8 @@ CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : RecursionCounter( 0 ), Parent( parent ), Child( NULL ), - Sibling( NULL ) + Sibling( NULL ), + m_userPtr(0) { Reset(); } diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h index adfbbe6149c..93f3f4a60fa 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.h +++ b/extern/bullet2/src/LinearMath/btQuickprof.h @@ -12,8 +12,8 @@ -#ifndef QUICK_PROF_H -#define QUICK_PROF_H +#ifndef BT_QUICK_PROF_H +#define BT_QUICK_PROF_H //To disable built-in profiling, please comment out next line //#define BT_NO_PROFILE 1 @@ -82,7 +82,8 @@ public: const char * Get_Name( void ) { return Name; } int Get_Total_Calls( void ) { return TotalCalls; } float Get_Total_Time( void ) { return TotalTime; } - + void* GetUserPointer() const {return m_userPtr;} + void SetUserPointer(void* ptr) { m_userPtr = ptr;} protected: const char * Name; @@ -94,6 +95,7 @@ protected: CProfileNode * Parent; CProfileNode * Child; CProfileNode * Sibling; + void* m_userPtr; }; ///An iterator to navigate through the tree @@ -115,15 +117,20 @@ public: int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } + void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); } + void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);} // Access the current parent const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } + + protected: CProfileNode * CurrentParent; CProfileNode * CurrentChild; + CProfileIterator( CProfileNode * start ); friend class CProfileManager; @@ -191,6 +198,6 @@ public: -#endif //QUICK_PROF_H +#endif //BT_QUICK_PROF_H diff --git a/extern/bullet2/src/LinearMath/btRandom.h b/extern/bullet2/src/LinearMath/btRandom.h index fdf65e01caf..4cbfc6bfe9f 100644 --- a/extern/bullet2/src/LinearMath/btRandom.h +++ b/extern/bullet2/src/LinearMath/btRandom.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef GEN_RANDOM_H -#define GEN_RANDOM_H +#ifndef BT_GEN_RANDOM_H +#define BT_GEN_RANDOM_H #ifdef MT19937 @@ -38,5 +38,5 @@ SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); } #endif -#endif +#endif //BT_GEN_RANDOM_H diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 6ba6c5ad30d..ecae972243c 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef SIMD___SCALAR_H -#define SIMD___SCALAR_H +#ifndef BT_SCALAR_H +#define BT_SCALAR_H #ifdef BT_MANAGED_CODE //Aligned data types not supported in managed code @@ -25,12 +25,10 @@ subject to the following restrictions: #include #include //size_t for MSVC 6.0 -#include -#include #include -/* SVN $Revision: 35500 $ on $Date: 2011-03-12 21:34:17 +0100 (Sat, 12 Mar 2011) $ from http://bullet.googlecode.com*/ -#define BT_BULLET_VERSION 278 +/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ +#define BT_BULLET_VERSION 280 inline int btGetVersion() { @@ -521,4 +519,29 @@ struct btTypedObject return m_objectType; } }; -#endif //SIMD___SCALAR_H + + + +///align a pointer to the provided alignment, upwards +template T* btAlignPointer(T* unalignedPtr, size_t alignment) +{ + + struct btConvertPointerSizeT + { + union + { + T* ptr; + size_t integer; + }; + }; + btConvertPointerSizeT converter; + + + const size_t bit_mask = ~(alignment - 1); + converter.ptr = unalignedPtr; + converter.integer += alignment-1; + converter.integer &= bit_mask; + return converter.ptr; +} + +#endif //BT_SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btSerializer.cpp b/extern/bullet2/src/LinearMath/btSerializer.cpp index c6d387e6133..49c25b7ea2a 100644 --- a/extern/bullet2/src/LinearMath/btSerializer.cpp +++ b/extern/bullet2/src/LinearMath/btSerializer.cpp @@ -1,5 +1,5 @@ -unsigned char sBulletDNAstr[]= { -83,68,78,65,78,65,77,69,42,1,0,0,109,95,115,105,122,101,0,109, +char sBulletDNAstr[]= { +83,68,78,65,78,65,77,69,44,1,0,0,109,95,115,105,122,101,0,109, 95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95, 99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111, 108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110, @@ -130,292 +130,297 @@ unsigned char sBulletDNAstr[]= { 112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114, 97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108, 105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66, -111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,116,121, -112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112, -105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109, -95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101, -0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101, -65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110, -97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109, -111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109, -95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108, -111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109, -105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109, -95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97, -116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112, -97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116, -119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109, -95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95, -108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97, -110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97, -110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117, -115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97, -109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111, -110,115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102, -68,97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100, -91,54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105, -110,116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110, -101,115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105, -110,103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110, -101,115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101, -115,115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115, -0,42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116, -105,111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105, -111,110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117, -109,117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97, -108,0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95, -110,111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115, -116,76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109, -95,110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101, -115,116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100, -101,73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111, -108,117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0, -109,95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105, -100,66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95, -97,101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116, -101,0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114, -101,115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121, -110,97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101, -77,97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116, -72,97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111, -110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116, -67,111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110, -99,104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82, -105,103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0, -109,95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114, -72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67, -108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102, -116,82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101, -83,112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67, -108,117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109, -95,115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117, -108,115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101, -0,109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99, -105,116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105, -116,105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105, -102,116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116, -101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109, -95,115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42, -109,95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104, -116,115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95, -110,117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0, -109,95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114, -109,0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95, -118,105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117, -108,115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109, -95,102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110, -100,105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117, -109,70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101, -115,0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97, -115,115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108, -115,101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110, -100,97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109, -95,97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103, -0,109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73, -109,112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105, -111,110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111, -110,116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105, -100,101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109, -95,98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101, -102,115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95, -115,112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108, -80,111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116, -121,112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111, -105,110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95, -109,97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42, -109,95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95, -116,101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114, -115,0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105, -110,116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109, -95,110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115, -0,109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110, -117,109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116, -101,114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111, -110,102,105,103,0,0,0,0,84,89,80,69,72,0,0,0,99,104,97,114, -0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0, -105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116, -0,100,111,117,98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114, -65,114,114,97,121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101, -109,0,76,105,115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51, -70,108,111,97,116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68, -111,117,98,108,101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120, -51,70,108,111,97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51, -120,51,68,111,117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115, -102,111,114,109,70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110, -115,102,111,114,109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118, -104,83,117,98,116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79, -112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116, -68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78, -111,100,101,68,111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110, -116,105,122,101,100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81, -117,97,110,116,105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97, -0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108, -101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97, -112,101,68,97,116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101, -83,104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110, -116,101,114,110,97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111, -115,105,116,105,111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117, -108,116,105,83,112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98, -116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114, -116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114, -116,73,110,116,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97, -0,98,116,67,104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68, -97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98, -116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97, -99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115, -104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108, -101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101, -100,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97, -116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104, -105,108,100,68,97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104, -97,112,101,68,97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104, -97,112,101,68,97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97, +111,100,105,101,115,0,109,95,111,118,101,114,114,105,100,101,78,117,109,83, +111,108,118,101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,98,114, +101,97,107,105,110,103,73,109,112,117,108,115,101,84,104,114,101,115,104,111, +108,100,0,109,95,105,115,69,110,97,98,108,101,100,0,109,95,116,121,112, +101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,105, +118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,95, +114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,0, +109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,65, +0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,97, +98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,111, +116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,95, +109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,111, +119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,105, +116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,95, +98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,116, +105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,97, +110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,119, +105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,95, +108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,108, +105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,115, +101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,109, +101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,110, +115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,68, +97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,91, +54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,110, +116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,101, +115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,110, +103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,101, +115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,115, +115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,0, +42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,105, +111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,111, +110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,109, +117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,108, +0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,110, +111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,116, +76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,95, +110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,115, +116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,101, +73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,108, +117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,109, +95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,100, +66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,97, +101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,101, +0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,101, +115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,110, +97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,77, +97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,72, +97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,110, +116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,67, +111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,99, +104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,105, +103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109, +95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,72, +97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,108, +117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116, +82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,83, +112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,108, +117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,95, +115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,108, +115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,0, +109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,105, +116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,116, +105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,102, +116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,101, +114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,95, +115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,109, +95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,116, +115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,110, +117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,109, +95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,109, +0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,118, +105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,108, +115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,95, +102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,100, +105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,109, +70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,115, +0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,115, +115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,115, +101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,100, +97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,95, +97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,0, +109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,109, +112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,111, +110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,110, +116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,100, +101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,95, +98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,102, +115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,115, +112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,80, +111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,121, +112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,105, +110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,109, +97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,109, +95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,116, +101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,115, +0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,110, +116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,95, +110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,0, +109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,117, +109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,101, +114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,110, +102,105,103,0,84,89,80,69,72,0,0,0,99,104,97,114,0,117,99,104, +97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,105,110,116,0, +108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117, +98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,65,114,114,97, +121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,109,0,76,105, +115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,70,108,111,97, +116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,111,117,98,108, +101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,70,108,111, +97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,68,111, +117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,109, +70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114, +109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,104,83,117,98, +116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,112,116,105,109, +105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,68,97,116,97, +0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,68, +111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101, +100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,117,97,110,116, +105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,0,98,116,81, +117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,101,68,97,116, +97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,68,97, +116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,83,104,97,112, +101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,116,101,114,110, +97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,115,105,116,105, +111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,108,116,105,83, +112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,98,116,67, +104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0, +98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,116,83,116,114, +105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,99,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97, 112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102, -111,68,97,116,97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83, -104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108, -108,83,104,97,112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105, -111,110,79,98,106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98, -116,67,111,108,108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97, -116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111, -97,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111, -117,98,108,101,68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110, -116,73,110,102,111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114, -97,105,110,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121, -68,97,116,97,0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111, -110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116, -80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110, -116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67, -111,110,115,116,114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0, -98,116,72,105,110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111, -97,116,68,97,116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111, -110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114, -105,99,54,68,111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97, -0,98,116,71,101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103, -67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105, -100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111, -102,116,66,111,100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83, -111,102,116,66,111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116, -66,111,100,121,76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100, -121,70,97,99,101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101, -116,114,97,68,97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99, -104,111,114,68,97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102, -105,103,68,97,116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68, -97,116,97,0,83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68, -97,116,97,0,98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68, -97,116,97,0,98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68, -97,116,97,0,84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0, -4,0,4,0,8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0, -96,0,64,0,-128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0, -52,0,52,0,20,0,64,0,4,0,4,0,8,0,4,0,32,0,28,0, -60,0,56,0,76,0,76,0,24,0,60,0,60,0,16,0,64,0,68,0, --56,1,-8,0,-32,1,-104,3,8,0,44,0,0,0,76,0,108,0,84,1, --44,0,-52,0,-12,0,84,1,-60,0,16,0,100,0,20,0,36,0,100,0, -92,0,104,0,-64,0,92,1,104,0,-92,1,83,84,82,67,61,0,0,0, -10,0,3,0,4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0, -10,0,3,0,10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0, -9,0,7,0,13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0, -15,0,1,0,13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0, -15,0,10,0,13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0, -19,0,4,0,4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0, -20,0,6,0,13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0, -4,0,20,0,0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0, -4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0, -2,0,14,0,2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0, -13,0,24,0,13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0, -4,0,29,0,20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0, -4,0,34,0,24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0, -4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0, -22,0,31,0,4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0, -0,0,35,0,4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0, -13,0,39,0,13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0, -25,0,38,0,13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0, -28,0,2,0,13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0, -28,0,48,0,4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0, -31,0,2,0,2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0, -0,0,51,0,33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0, -13,0,54,0,14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0, -31,0,59,0,4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0, -13,0,63,0,4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0, -35,0,65,0,23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0, -0,0,69,0,38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0, -17,0,71,0,25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0, -25,0,38,0,39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0, -27,0,47,0,4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0, -4,0,77,0,0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0, -7,0,80,0,7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0, -43,0,84,0,4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0, -7,0,89,0,7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0, -4,0,94,0,0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0, -13,0,39,0,7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0, -13,0,96,0,14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0, -9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0, -18,0,104,0,14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0, -8,0,109,0,8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0, -8,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0, -4,0,119,0,4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0, -9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0, -17,0,104,0,13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0, -7,0,109,0,7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0, -7,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0, -4,0,119,0,4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0, -15,0,123,0,13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0, -13,0,-128,0,13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0, -7,0,-123,0,7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0, -7,0,-118,0,7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0, -49,0,22,0,46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0, -14,0,126,0,14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0, -14,0,-125,0,14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0, -8,0,-120,0,8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0, -8,0,-115,0,4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0, -4,0,-112,0,51,0,11,0,52,0,-111,0,52,0,-110,0,0,0,35,0, -4,0,-109,0,4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0, -7,0,-104,0,4,0,-103,0,0,0,-102,0,53,0,3,0,51,0,-101,0, -13,0,-100,0,13,0,-99,0,54,0,3,0,51,0,-101,0,14,0,-100,0, -14,0,-99,0,55,0,13,0,51,0,-101,0,18,0,-98,0,18,0,-97,0, -4,0,-96,0,4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0, -7,0,-91,0,7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0, -56,0,13,0,51,0,-101,0,17,0,-98,0,17,0,-97,0,4,0,-96,0, -4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0, -7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,57,0,11,0, -51,0,-101,0,17,0,-98,0,17,0,-97,0,7,0,-86,0,7,0,-85,0, -7,0,-84,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-83,0, -0,0,21,0,58,0,9,0,51,0,-101,0,17,0,-98,0,17,0,-97,0, -13,0,-82,0,13,0,-81,0,13,0,-80,0,13,0,-79,0,4,0,-78,0, -4,0,-77,0,59,0,5,0,58,0,-76,0,4,0,-75,0,7,0,-74,0, -7,0,-73,0,7,0,-72,0,60,0,9,0,51,0,-101,0,17,0,-98,0, -17,0,-97,0,7,0,-82,0,7,0,-81,0,7,0,-80,0,7,0,-79,0, -4,0,-78,0,4,0,-77,0,61,0,4,0,7,0,-71,0,7,0,-70,0, -7,0,-69,0,4,0,78,0,62,0,10,0,61,0,-68,0,13,0,-67,0, -13,0,-66,0,13,0,-65,0,13,0,-64,0,13,0,-63,0,7,0,-123,0, -7,0,-62,0,4,0,-61,0,4,0,53,0,63,0,4,0,61,0,-68,0, -4,0,-60,0,7,0,-59,0,4,0,-58,0,64,0,4,0,13,0,-63,0, -61,0,-68,0,4,0,-57,0,7,0,-56,0,65,0,7,0,13,0,-55,0, -61,0,-68,0,4,0,-54,0,7,0,-53,0,7,0,-52,0,7,0,-51,0, -4,0,53,0,66,0,6,0,15,0,-50,0,13,0,-52,0,13,0,-49,0, -52,0,-48,0,4,0,-47,0,7,0,-51,0,67,0,26,0,4,0,-46,0, -7,0,-45,0,7,0,-83,0,7,0,-44,0,7,0,-43,0,7,0,-42,0, -7,0,-41,0,7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0, -7,0,-36,0,7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0, -7,0,-31,0,7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0, -4,0,-26,0,4,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,116,0, -68,0,12,0,15,0,-22,0,15,0,-21,0,15,0,-20,0,13,0,-19,0, -13,0,-18,0,7,0,-17,0,4,0,-16,0,4,0,-15,0,4,0,-14,0, -4,0,-13,0,7,0,-53,0,4,0,53,0,69,0,27,0,17,0,-12,0, -15,0,-11,0,15,0,-10,0,13,0,-19,0,13,0,-9,0,13,0,-8,0, -13,0,-7,0,13,0,-6,0,13,0,-5,0,4,0,-4,0,7,0,-3,0, -4,0,-2,0,4,0,-1,0,4,0,0,1,7,0,1,1,7,0,2,1, -4,0,3,1,4,0,4,1,7,0,5,1,7,0,6,1,7,0,7,1, -7,0,8,1,7,0,9,1,7,0,10,1,4,0,11,1,4,0,12,1, -4,0,13,1,70,0,12,0,9,0,14,1,9,0,15,1,13,0,16,1, -7,0,17,1,7,0,18,1,7,0,19,1,4,0,20,1,13,0,21,1, -4,0,22,1,4,0,23,1,4,0,24,1,4,0,53,0,71,0,19,0, -47,0,122,0,68,0,25,1,61,0,26,1,62,0,27,1,63,0,28,1, -64,0,29,1,65,0,30,1,66,0,31,1,69,0,32,1,70,0,33,1, -4,0,34,1,4,0,-1,0,4,0,35,1,4,0,36,1,4,0,37,1, -4,0,38,1,4,0,39,1,4,0,40,1,67,0,41,1,}; +111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,100,84,114,105, +97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98, +116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68, +97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68, +97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68, +97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116, +97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101, +68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97, +112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98, +106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108, +108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116, +97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97, +116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101, +68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102, +111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116, +68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97, +0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114, +97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110, +116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117, +98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116, +114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105, +110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97, +116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114, +97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68, +111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71, +101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,67,111,110,115, +116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,100,101,114,67, +111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,102,116,66,111, +100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,111,102,116,66, +111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,66,111,100,121, +76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,121,70,97,99, +101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,116,114,97,68, +97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,104,111,114,68, +97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,105,103,68,97, +116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,97,116,97,0, +83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,97,116,97,0, +84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0, +8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0,96,0,64,0, +-128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0,52,0,52,0, +20,0,64,0,4,0,4,0,8,0,4,0,32,0,28,0,60,0,56,0, +76,0,76,0,24,0,60,0,60,0,16,0,64,0,68,0,-56,1,-8,0, +-32,1,-104,3,8,0,52,0,0,0,84,0,116,0,92,1,-36,0,-44,0, +-4,0,92,1,-52,0,16,0,100,0,20,0,36,0,100,0,92,0,104,0, +-64,0,92,1,104,0,-92,1,83,84,82,67,61,0,0,0,10,0,3,0, +4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,10,0,3,0, +10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,9,0,7,0, +13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,15,0,1,0, +13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,15,0,10,0, +13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,19,0,4,0, +4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,20,0,6,0, +13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0, +0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,4,0,18,0, +4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,2,0,14,0, +2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,13,0,24,0, +13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0, +20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,4,0,34,0, +24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,4,0,26,0, +4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,22,0,31,0, +4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,0,0,35,0, +4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,13,0,39,0, +13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,25,0,38,0, +13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,28,0,2,0, +13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,28,0,48,0, +4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,31,0,2,0, +2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,0,0,51,0, +33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,13,0,54,0, +14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,31,0,59,0, +4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,13,0,63,0, +4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,35,0,65,0, +23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,0,0,69,0, +38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,17,0,71,0, +25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,25,0,38,0, +39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,27,0,47,0, +4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,4,0,77,0, +0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,7,0,80,0, +7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,43,0,84,0, +4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,7,0,89,0, +7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,4,0,94,0, +0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,13,0,39,0, +7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,13,0,96,0, +14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,18,0,104,0, +14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,8,0,109,0, +8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,8,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,17,0,104,0, +13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,7,0,109,0, +7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,7,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,15,0,123,0, +13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0, +13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,7,0,-123,0, +7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0, +7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,49,0,22,0, +46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0, +14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,14,0,-125,0, +14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0, +8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,8,0,-115,0, +4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,4,0,-112,0, +51,0,13,0,52,0,-111,0,52,0,-110,0,0,0,35,0,4,0,-109,0, +4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,7,0,-104,0, +4,0,-103,0,4,0,-102,0,7,0,-101,0,4,0,-100,0,53,0,3,0, +51,0,-99,0,13,0,-98,0,13,0,-97,0,54,0,3,0,51,0,-99,0, +14,0,-98,0,14,0,-97,0,55,0,13,0,51,0,-99,0,18,0,-96,0, +18,0,-95,0,4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0, +7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0, +7,0,-85,0,56,0,13,0,51,0,-99,0,17,0,-96,0,17,0,-95,0, +4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,7,0,-90,0, +7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +57,0,11,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,7,0,-84,0, +7,0,-83,0,7,0,-82,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +7,0,-81,0,0,0,21,0,58,0,9,0,51,0,-99,0,17,0,-96,0, +17,0,-95,0,13,0,-80,0,13,0,-79,0,13,0,-78,0,13,0,-77,0, +4,0,-76,0,4,0,-75,0,59,0,5,0,58,0,-74,0,4,0,-73,0, +7,0,-72,0,7,0,-71,0,7,0,-70,0,60,0,9,0,51,0,-99,0, +17,0,-96,0,17,0,-95,0,7,0,-80,0,7,0,-79,0,7,0,-78,0, +7,0,-77,0,4,0,-76,0,4,0,-75,0,61,0,4,0,7,0,-69,0, +7,0,-68,0,7,0,-67,0,4,0,78,0,62,0,10,0,61,0,-66,0, +13,0,-65,0,13,0,-64,0,13,0,-63,0,13,0,-62,0,13,0,-61,0, +7,0,-123,0,7,0,-60,0,4,0,-59,0,4,0,53,0,63,0,4,0, +61,0,-66,0,4,0,-58,0,7,0,-57,0,4,0,-56,0,64,0,4,0, +13,0,-61,0,61,0,-66,0,4,0,-55,0,7,0,-54,0,65,0,7,0, +13,0,-53,0,61,0,-66,0,4,0,-52,0,7,0,-51,0,7,0,-50,0, +7,0,-49,0,4,0,53,0,66,0,6,0,15,0,-48,0,13,0,-50,0, +13,0,-47,0,52,0,-46,0,4,0,-45,0,7,0,-49,0,67,0,26,0, +4,0,-44,0,7,0,-43,0,7,0,-81,0,7,0,-42,0,7,0,-41,0, +7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,7,0,-36,0, +7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,7,0,-31,0, +7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0, +7,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,-22,0,4,0,-21,0, +4,0,116,0,68,0,12,0,15,0,-20,0,15,0,-19,0,15,0,-18,0, +13,0,-17,0,13,0,-16,0,7,0,-15,0,4,0,-14,0,4,0,-13,0, +4,0,-12,0,4,0,-11,0,7,0,-51,0,4,0,53,0,69,0,27,0, +17,0,-10,0,15,0,-9,0,15,0,-8,0,13,0,-17,0,13,0,-7,0, +13,0,-6,0,13,0,-5,0,13,0,-4,0,13,0,-3,0,4,0,-2,0, +7,0,-1,0,4,0,0,1,4,0,1,1,4,0,2,1,7,0,3,1, +7,0,4,1,4,0,5,1,4,0,6,1,7,0,7,1,7,0,8,1, +7,0,9,1,7,0,10,1,7,0,11,1,7,0,12,1,4,0,13,1, +4,0,14,1,4,0,15,1,70,0,12,0,9,0,16,1,9,0,17,1, +13,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,4,0,22,1, +13,0,23,1,4,0,24,1,4,0,25,1,4,0,26,1,4,0,53,0, +71,0,19,0,47,0,122,0,68,0,27,1,61,0,28,1,62,0,29,1, +63,0,30,1,64,0,31,1,65,0,32,1,66,0,33,1,69,0,34,1, +70,0,35,1,4,0,36,1,4,0,1,1,4,0,37,1,4,0,38,1, +4,0,39,1,4,0,40,1,4,0,41,1,4,0,42,1,67,0,43,1, +}; int sBulletDNAlen= sizeof(sBulletDNAstr); -unsigned char sBulletDNAstr64[]= { -83,68,78,65,78,65,77,69,42,1,0,0,109,95,115,105,122,101,0,109, + + char sBulletDNAstr64[]= { +83,68,78,65,78,65,77,69,44,1,0,0,109,95,115,105,122,101,0,109, 95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95, 99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111, 108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110, @@ -546,287 +551,291 @@ unsigned char sBulletDNAstr64[]= { 112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114, 97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108, 105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66, -111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,116,121, -112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112, -105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109, -95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101, -0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101, -65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110, -97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109, -111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109, -95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108, -111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109, -105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109, -95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97, -116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112, -97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116, -119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109, -95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95, -108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97, -110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97, -110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117, -115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97, -109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111, -110,115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102, -68,97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100, -91,54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105, -110,116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110, -101,115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105, -110,103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110, -101,115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101, -115,115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115, -0,42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116, -105,111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105, -111,110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117, -109,117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97, -108,0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95, -110,111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115, -116,76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109, -95,110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101, -115,116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100, -101,73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111, -108,117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0, -109,95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105, -100,66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95, -97,101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116, -101,0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114, -101,115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121, -110,97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101, -77,97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116, -72,97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111, -110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116, -67,111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110, -99,104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82, -105,103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0, -109,95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114, -72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67, -108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102, -116,82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101, -83,112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67, -108,117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109, -95,115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117, -108,115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101, -0,109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99, -105,116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105, -116,105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105, -102,116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116, -101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109, -95,115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42, -109,95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104, -116,115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95, -110,117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0, -109,95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114, -109,0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95, -118,105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117, -108,115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109, -95,102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110, -100,105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117, -109,70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101, -115,0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97, -115,115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108, -115,101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110, -100,97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109, -95,97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103, -0,109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73, -109,112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105, -111,110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111, -110,116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105, -100,101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109, -95,98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101, -102,115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95, -115,112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108, -80,111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116, -121,112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111, -105,110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95, -109,97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42, -109,95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95, -116,101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114, -115,0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105, -110,116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109, -95,110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115, -0,109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110, -117,109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116, -101,114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111, -110,102,105,103,0,0,0,0,84,89,80,69,72,0,0,0,99,104,97,114, -0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0, -105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116, -0,100,111,117,98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114, -65,114,114,97,121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101, -109,0,76,105,115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51, -70,108,111,97,116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68, -111,117,98,108,101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120, -51,70,108,111,97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51, -120,51,68,111,117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115, -102,111,114,109,70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110, -115,102,111,114,109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118, -104,83,117,98,116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79, -112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116, -68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78, -111,100,101,68,111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110, -116,105,122,101,100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81, -117,97,110,116,105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97, -0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108, -101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97, -112,101,68,97,116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101, -83,104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110, -116,101,114,110,97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111, -115,105,116,105,111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117, -108,116,105,83,112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98, -116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114, -116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114, -116,73,110,116,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97, -0,98,116,67,104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68, -97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98, -116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97, -99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115, -104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108, -101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101, -100,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97, -116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104, -105,108,100,68,97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104, -97,112,101,68,97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104, -97,112,101,68,97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97, +111,100,105,101,115,0,109,95,111,118,101,114,114,105,100,101,78,117,109,83, +111,108,118,101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,98,114, +101,97,107,105,110,103,73,109,112,117,108,115,101,84,104,114,101,115,104,111, +108,100,0,109,95,105,115,69,110,97,98,108,101,100,0,109,95,116,121,112, +101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,105, +118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,95, +114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,0, +109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,65, +0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,97, +98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,111, +116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,95, +109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,111, +119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,105, +116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,95, +98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,116, +105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,97, +110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,119, +105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,95, +108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,108, +105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,110, +103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,115, +101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,109, +101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,110, +115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,68, +97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,91, +54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,110, +116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,101, +115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,110, +103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,101, +115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,115, +115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,0, +42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,105, +111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,111, +110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,109, +117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,108, +0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,110, +111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,116, +76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,95, +110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,115, +116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,101, +73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,108, +117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,109, +95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,100, +66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,97, +101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,101, +0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,101, +115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,110, +97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,77, +97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,72, +97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,110, +116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,67, +111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,99, +104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,105, +103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109, +95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,72, +97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,108, +117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116, +82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,83, +112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,108, +117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,95, +115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,108, +115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,0, +109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,105, +116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,116, +105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,102, +116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,101, +114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,95, +115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,109, +95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,116, +115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,110, +117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,109, +95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,109, +0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,118, +105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,108, +115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,95, +102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,100, +105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,109, +70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,115, +0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,115, +115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,115, +101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,100, +97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,95, +97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,0, +109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,109, +112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,111, +110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,110, +116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,100, +101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,95, +98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,102, +115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,115, +112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,80, +111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,121, +112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,105, +110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,109, +97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,109, +95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,116, +101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,115, +0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,110, +116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,95, +110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,0, +109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,117, +109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,101, +114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,110, +102,105,103,0,84,89,80,69,72,0,0,0,99,104,97,114,0,117,99,104, +97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,105,110,116,0, +108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117, +98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,65,114,114,97, +121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,109,0,76,105, +115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,70,108,111,97, +116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,111,117,98,108, +101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,70,108,111, +97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,68,111, +117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,109, +70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114, +109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,104,83,117,98, +116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,112,116,105,109, +105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,68,97,116,97, +0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,68, +111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101, +100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,117,97,110,116, +105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,0,98,116,81, +117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,101,68,97,116, +97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,68,97, +116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,83,104,97,112, +101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,116,101,114,110, +97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,115,105,116,105, +111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,108,116,105,83, +112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116, +73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,98,116,67, +104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0, +98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,116,83,116,114, +105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,99,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97, 112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102, -111,68,97,116,97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83, -104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108, -108,83,104,97,112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105, -111,110,79,98,106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98, -116,67,111,108,108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97, -116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111, -97,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111, -117,98,108,101,68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110, -116,73,110,102,111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114, -97,105,110,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121, -68,97,116,97,0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111, -110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116, -80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110, -116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67, -111,110,115,116,114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0, -98,116,72,105,110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111, -97,116,68,97,116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111, -110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114, -105,99,54,68,111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97, -0,98,116,71,101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103, -67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105, -100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111, -102,116,66,111,100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83, -111,102,116,66,111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116, -66,111,100,121,76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100, -121,70,97,99,101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101, -116,114,97,68,97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99, -104,111,114,68,97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102, -105,103,68,97,116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68, -97,116,97,0,83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68, -97,116,97,0,98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68, -97,116,97,0,98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68, -97,116,97,0,84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0, -4,0,4,0,8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0, -96,0,64,0,-128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0, -56,0,56,0,20,0,72,0,4,0,4,0,8,0,4,0,56,0,32,0, -80,0,72,0,96,0,80,0,32,0,64,0,64,0,16,0,72,0,80,0, --40,1,8,1,-16,1,-88,3,8,0,56,0,0,0,88,0,120,0,96,1, --32,0,-40,0,0,1,96,1,-48,0,16,0,104,0,24,0,40,0,104,0, -96,0,104,0,-56,0,104,1,112,0,-40,1,83,84,82,67,61,0,0,0, -10,0,3,0,4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0, -10,0,3,0,10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0, -9,0,7,0,13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0, -15,0,1,0,13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0, -15,0,10,0,13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0, -19,0,4,0,4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0, -20,0,6,0,13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0, -4,0,20,0,0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0, -4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0, -2,0,14,0,2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0, -13,0,24,0,13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0, -4,0,29,0,20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0, -4,0,34,0,24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0, -4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0, -22,0,31,0,4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0, -0,0,35,0,4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0, -13,0,39,0,13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0, -25,0,38,0,13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0, -28,0,2,0,13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0, -28,0,48,0,4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0, -31,0,2,0,2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0, -0,0,51,0,33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0, -13,0,54,0,14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0, -31,0,59,0,4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0, -13,0,63,0,4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0, -35,0,65,0,23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0, -0,0,69,0,38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0, -17,0,71,0,25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0, -25,0,38,0,39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0, -27,0,47,0,4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0, -4,0,77,0,0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0, -7,0,80,0,7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0, -43,0,84,0,4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0, -7,0,89,0,7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0, -4,0,94,0,0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0, -13,0,39,0,7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0, -13,0,96,0,14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0, -9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0, -18,0,104,0,14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0, -8,0,109,0,8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0, -8,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0, -4,0,119,0,4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0, -9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0, -17,0,104,0,13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0, -7,0,109,0,7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0, -7,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0, -4,0,119,0,4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0, -15,0,123,0,13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0, -13,0,-128,0,13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0, -7,0,-123,0,7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0, -7,0,-118,0,7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0, -49,0,22,0,46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0, -14,0,126,0,14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0, -14,0,-125,0,14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0, -8,0,-120,0,8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0, -8,0,-115,0,4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0, -4,0,-112,0,51,0,11,0,52,0,-111,0,52,0,-110,0,0,0,35,0, -4,0,-109,0,4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0, -7,0,-104,0,4,0,-103,0,0,0,-102,0,53,0,3,0,51,0,-101,0, -13,0,-100,0,13,0,-99,0,54,0,3,0,51,0,-101,0,14,0,-100,0, -14,0,-99,0,55,0,13,0,51,0,-101,0,18,0,-98,0,18,0,-97,0, -4,0,-96,0,4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0, -7,0,-91,0,7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0, -56,0,13,0,51,0,-101,0,17,0,-98,0,17,0,-97,0,4,0,-96,0, -4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0, -7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,57,0,11,0, -51,0,-101,0,17,0,-98,0,17,0,-97,0,7,0,-86,0,7,0,-85,0, -7,0,-84,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-83,0, -0,0,21,0,58,0,9,0,51,0,-101,0,17,0,-98,0,17,0,-97,0, -13,0,-82,0,13,0,-81,0,13,0,-80,0,13,0,-79,0,4,0,-78,0, -4,0,-77,0,59,0,5,0,58,0,-76,0,4,0,-75,0,7,0,-74,0, -7,0,-73,0,7,0,-72,0,60,0,9,0,51,0,-101,0,17,0,-98,0, -17,0,-97,0,7,0,-82,0,7,0,-81,0,7,0,-80,0,7,0,-79,0, -4,0,-78,0,4,0,-77,0,61,0,4,0,7,0,-71,0,7,0,-70,0, -7,0,-69,0,4,0,78,0,62,0,10,0,61,0,-68,0,13,0,-67,0, -13,0,-66,0,13,0,-65,0,13,0,-64,0,13,0,-63,0,7,0,-123,0, -7,0,-62,0,4,0,-61,0,4,0,53,0,63,0,4,0,61,0,-68,0, -4,0,-60,0,7,0,-59,0,4,0,-58,0,64,0,4,0,13,0,-63,0, -61,0,-68,0,4,0,-57,0,7,0,-56,0,65,0,7,0,13,0,-55,0, -61,0,-68,0,4,0,-54,0,7,0,-53,0,7,0,-52,0,7,0,-51,0, -4,0,53,0,66,0,6,0,15,0,-50,0,13,0,-52,0,13,0,-49,0, -52,0,-48,0,4,0,-47,0,7,0,-51,0,67,0,26,0,4,0,-46,0, -7,0,-45,0,7,0,-83,0,7,0,-44,0,7,0,-43,0,7,0,-42,0, -7,0,-41,0,7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0, -7,0,-36,0,7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0, -7,0,-31,0,7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0, -4,0,-26,0,4,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,116,0, -68,0,12,0,15,0,-22,0,15,0,-21,0,15,0,-20,0,13,0,-19,0, -13,0,-18,0,7,0,-17,0,4,0,-16,0,4,0,-15,0,4,0,-14,0, -4,0,-13,0,7,0,-53,0,4,0,53,0,69,0,27,0,17,0,-12,0, -15,0,-11,0,15,0,-10,0,13,0,-19,0,13,0,-9,0,13,0,-8,0, -13,0,-7,0,13,0,-6,0,13,0,-5,0,4,0,-4,0,7,0,-3,0, -4,0,-2,0,4,0,-1,0,4,0,0,1,7,0,1,1,7,0,2,1, -4,0,3,1,4,0,4,1,7,0,5,1,7,0,6,1,7,0,7,1, -7,0,8,1,7,0,9,1,7,0,10,1,4,0,11,1,4,0,12,1, -4,0,13,1,70,0,12,0,9,0,14,1,9,0,15,1,13,0,16,1, -7,0,17,1,7,0,18,1,7,0,19,1,4,0,20,1,13,0,21,1, -4,0,22,1,4,0,23,1,4,0,24,1,4,0,53,0,71,0,19,0, -47,0,122,0,68,0,25,1,61,0,26,1,62,0,27,1,63,0,28,1, -64,0,29,1,65,0,30,1,66,0,31,1,69,0,32,1,70,0,33,1, -4,0,34,1,4,0,-1,0,4,0,35,1,4,0,36,1,4,0,37,1, -4,0,38,1,4,0,39,1,4,0,40,1,67,0,41,1,}; +111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,100,84,114,105, +97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98, +116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68, +97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68, +97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68, +97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97, +116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116, +97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101, +68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97, +112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98, +106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108, +108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116, +97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97, +116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101, +68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102, +111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116, +68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97, +0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114, +97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110, +116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117, +98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116, +114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105, +110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97, +116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114, +97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68, +111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71, +101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,67,111,110,115, +116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,100,101,114,67, +111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,102,116,66,111, +100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,111,102,116,66, +111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,66,111,100,121, +76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,121,70,97,99, +101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,116,114,97,68, +97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,104,111,114,68, +97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,105,103,68,97, +116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,97,116,97,0, +83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,97,116,97,0, +98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,97,116,97,0, +84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0, +8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0,96,0,64,0, +-128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0,56,0,56,0, +20,0,72,0,4,0,4,0,8,0,4,0,56,0,32,0,80,0,72,0, +96,0,80,0,32,0,64,0,64,0,16,0,72,0,80,0,-40,1,8,1, +-16,1,-88,3,8,0,64,0,0,0,96,0,-128,0,104,1,-24,0,-32,0, +8,1,104,1,-40,0,16,0,104,0,24,0,40,0,104,0,96,0,104,0, +-56,0,104,1,112,0,-40,1,83,84,82,67,61,0,0,0,10,0,3,0, +4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,10,0,3,0, +10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,9,0,7,0, +13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,15,0,1,0, +13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,15,0,10,0, +13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,19,0,4,0, +4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,20,0,6,0, +13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0, +0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,4,0,18,0, +4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,2,0,14,0, +2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,13,0,24,0, +13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0, +20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,4,0,34,0, +24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,4,0,26,0, +4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,22,0,31,0, +4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,0,0,35,0, +4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,13,0,39,0, +13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,25,0,38,0, +13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,28,0,2,0, +13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,28,0,48,0, +4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,31,0,2,0, +2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,0,0,51,0, +33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,13,0,54,0, +14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,31,0,59,0, +4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,13,0,63,0, +4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,35,0,65,0, +23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,0,0,69,0, +38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,17,0,71,0, +25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,25,0,38,0, +39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,27,0,47,0, +4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,4,0,77,0, +0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,7,0,80,0, +7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,43,0,84,0, +4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,7,0,89,0, +7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,4,0,94,0, +0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,13,0,39,0, +7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,13,0,96,0, +14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,18,0,104,0, +14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,8,0,109,0, +8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,8,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,9,0,100,0, +9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,17,0,104,0, +13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,7,0,109,0, +7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,7,0,114,0, +4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0, +4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,15,0,123,0, +13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0, +13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,7,0,-123,0, +7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0, +7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,49,0,22,0, +46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0, +14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,14,0,-125,0, +14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0, +8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,8,0,-115,0, +4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,4,0,-112,0, +51,0,13,0,52,0,-111,0,52,0,-110,0,0,0,35,0,4,0,-109,0, +4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,7,0,-104,0, +4,0,-103,0,4,0,-102,0,7,0,-101,0,4,0,-100,0,53,0,3,0, +51,0,-99,0,13,0,-98,0,13,0,-97,0,54,0,3,0,51,0,-99,0, +14,0,-98,0,14,0,-97,0,55,0,13,0,51,0,-99,0,18,0,-96,0, +18,0,-95,0,4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0, +7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0, +7,0,-85,0,56,0,13,0,51,0,-99,0,17,0,-96,0,17,0,-95,0, +4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,7,0,-90,0, +7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +57,0,11,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,7,0,-84,0, +7,0,-83,0,7,0,-82,0,7,0,-87,0,7,0,-86,0,7,0,-85,0, +7,0,-81,0,0,0,21,0,58,0,9,0,51,0,-99,0,17,0,-96,0, +17,0,-95,0,13,0,-80,0,13,0,-79,0,13,0,-78,0,13,0,-77,0, +4,0,-76,0,4,0,-75,0,59,0,5,0,58,0,-74,0,4,0,-73,0, +7,0,-72,0,7,0,-71,0,7,0,-70,0,60,0,9,0,51,0,-99,0, +17,0,-96,0,17,0,-95,0,7,0,-80,0,7,0,-79,0,7,0,-78,0, +7,0,-77,0,4,0,-76,0,4,0,-75,0,61,0,4,0,7,0,-69,0, +7,0,-68,0,7,0,-67,0,4,0,78,0,62,0,10,0,61,0,-66,0, +13,0,-65,0,13,0,-64,0,13,0,-63,0,13,0,-62,0,13,0,-61,0, +7,0,-123,0,7,0,-60,0,4,0,-59,0,4,0,53,0,63,0,4,0, +61,0,-66,0,4,0,-58,0,7,0,-57,0,4,0,-56,0,64,0,4,0, +13,0,-61,0,61,0,-66,0,4,0,-55,0,7,0,-54,0,65,0,7,0, +13,0,-53,0,61,0,-66,0,4,0,-52,0,7,0,-51,0,7,0,-50,0, +7,0,-49,0,4,0,53,0,66,0,6,0,15,0,-48,0,13,0,-50,0, +13,0,-47,0,52,0,-46,0,4,0,-45,0,7,0,-49,0,67,0,26,0, +4,0,-44,0,7,0,-43,0,7,0,-81,0,7,0,-42,0,7,0,-41,0, +7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,7,0,-36,0, +7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,7,0,-31,0, +7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0, +7,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,-22,0,4,0,-21,0, +4,0,116,0,68,0,12,0,15,0,-20,0,15,0,-19,0,15,0,-18,0, +13,0,-17,0,13,0,-16,0,7,0,-15,0,4,0,-14,0,4,0,-13,0, +4,0,-12,0,4,0,-11,0,7,0,-51,0,4,0,53,0,69,0,27,0, +17,0,-10,0,15,0,-9,0,15,0,-8,0,13,0,-17,0,13,0,-7,0, +13,0,-6,0,13,0,-5,0,13,0,-4,0,13,0,-3,0,4,0,-2,0, +7,0,-1,0,4,0,0,1,4,0,1,1,4,0,2,1,7,0,3,1, +7,0,4,1,4,0,5,1,4,0,6,1,7,0,7,1,7,0,8,1, +7,0,9,1,7,0,10,1,7,0,11,1,7,0,12,1,4,0,13,1, +4,0,14,1,4,0,15,1,70,0,12,0,9,0,16,1,9,0,17,1, +13,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,4,0,22,1, +13,0,23,1,4,0,24,1,4,0,25,1,4,0,26,1,4,0,53,0, +71,0,19,0,47,0,122,0,68,0,27,1,61,0,28,1,62,0,29,1, +63,0,30,1,64,0,31,1,65,0,32,1,66,0,33,1,69,0,34,1, +70,0,35,1,4,0,36,1,4,0,1,1,4,0,37,1,4,0,38,1, +4,0,39,1,4,0,40,1,4,0,41,1,4,0,42,1,67,0,43,1, +}; int sBulletDNAlen64= sizeof(sBulletDNAstr64); diff --git a/extern/bullet2/src/LinearMath/btSerializer.h b/extern/bullet2/src/LinearMath/btSerializer.h index 52520d72b9e..76f3cf32f8e 100644 --- a/extern/bullet2/src/LinearMath/btSerializer.h +++ b/extern/bullet2/src/LinearMath/btSerializer.h @@ -28,9 +28,9 @@ subject to the following restrictions: ///only the 32bit versions for now -extern unsigned char sBulletDNAstr[]; +extern char sBulletDNAstr[]; extern int sBulletDNAlen; -extern unsigned char sBulletDNAstr64[]; +extern char sBulletDNAstr64[]; extern int sBulletDNAlen64; SIMD_FORCE_INLINE int btStrLen(const char* str) @@ -213,7 +213,7 @@ protected: int *intPtr=0; short *shtPtr=0; - char *cp = 0;int dataLen =0;long nr=0; + char *cp = 0;int dataLen =0; intPtr = (int*)m_dna; /* @@ -246,15 +246,7 @@ protected: while (*cp)cp++; cp++; } - { - nr= (long)cp; - // long mask=3; - nr= ((nr+3)&~3)-nr; - while (nr--) - { - cp++; - } - } + cp = btAlignPointer(cp,4); /* TYPE (4 bytes) @@ -281,15 +273,7 @@ protected: cp++; } - { - nr= (long)cp; - // long mask=3; - nr= ((nr+3)&~3)-nr; - while (nr--) - { - cp++; - } - } + cp = btAlignPointer(cp,4); /* @@ -453,8 +437,8 @@ public: buffer[9] = '2'; - buffer[10] = '7'; - buffer[11] = '8'; + buffer[10] = '8'; + buffer[11] = '0'; } diff --git a/extern/bullet2/src/LinearMath/btSimdMinMax.h b/extern/bullet2/src/LinearMath/btSimdMinMax.h deleted file mode 100644 index 75e83f3c53f..00000000000 --- a/extern/bullet2/src/LinearMath/btSimdMinMax.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - - -#ifndef SIMD_MINMAX_H -#define SIMD_MINMAX_H -#include "btScalar.h" - -template -SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) { - return b < a ? b : a; -} - -template -SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) { - return a < b ? b : a; -} - -template -SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) { - if (a > b) a = b; -} - -template -SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) { - if (a < b) a = b; -} - -#endif diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h index 187b09116cc..5e52d183acb 100644 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef btTransform_H -#define btTransform_H +#ifndef BT_TRANSFORM_H +#define BT_TRANSFORM_H #include "btMatrix3x3.h" @@ -298,7 +298,7 @@ SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleDat } -#endif +#endif //BT_TRANSFORM_H diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h index 626110ce4ee..2303c274275 100644 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -13,8 +13,8 @@ subject to the following restrictions: */ -#ifndef SIMD_TRANSFORM_UTIL_H -#define SIMD_TRANSFORM_UTIL_H +#ifndef BT_TRANSFORM_UTIL_H +#define BT_TRANSFORM_UTIL_H #include "btTransform.h" #define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI @@ -224,5 +224,5 @@ public: }; -#endif //SIMD_TRANSFORM_UTIL_H +#endif //BT_TRANSFORM_UTIL_H diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h index 068e87c94ab..d99b7c83ae3 100644 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -14,8 +14,8 @@ subject to the following restrictions: -#ifndef SIMD__VECTOR3_H -#define SIMD__VECTOR3_H +#ifndef BT_VECTOR3_H +#define BT_VECTOR3_H #include "btScalar.h" @@ -763,4 +763,4 @@ SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn } -#endif //SIMD__VECTOR3_H +#endif //BT_VECTOR3_H diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index cd94df257ec..8a3db17f6d1 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -21,25 +21,18 @@ elif sys.platform=='darwin': defs += ' NDEBUG' cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] -linearmath_src = env.Glob("LinearMath/*.cpp") - -bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") + env.Glob("BulletDynamics/Character/*.cpp") - -collision_broadphase_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") -collision_dispatch_src = env.Glob("BulletCollision/CollisionDispatch/*.cpp") -collision_gimpact_src = env.Glob("BulletCollision/Gimpact/*.cpp") -collision_shapes_src = env.Glob("BulletCollision/CollisionShapes/*.cpp") -collision_narrowphase_src = env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") - -softbody_src = env.Glob("BulletSoftBody/*.cpp") +bullet2_src = env.Glob("LinearMath/*.cpp") +bullet2_src += env.Glob("BulletCollision/BroadphaseCollision/*.cpp") +bullet2_src += env.Glob("BulletCollision/CollisionDispatch/*.cpp") +bullet2_src += env.Glob("BulletCollision/Gimpact/*.cpp") +bullet2_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") +bullet2_src += env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") +bullet2_src += env.Glob("BulletDynamics/Vehicle/*.cpp") +bullet2_src += env.Glob("BulletDynamics/ConstraintSolver/*.cpp") +bullet2_src += env.Glob("BulletDynamics/Dynamics/*.cpp") +bullet2_src += env.Glob("BulletDynamics/Character/*.cpp") +bullet2_src += env.Glob("BulletSoftBody/*.cpp") incs = '. BulletCollision BulletDynamics LinearMath BulletSoftBody' -env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,137], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[19,136], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision_broadphase', sources=collision_broadphase_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[25,145], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision_dispatch', sources=collision_dispatch_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision_gimpact', sources=collision_gimpact_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision_shapes', sources=collision_shapes_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision_narrowphase', sources=collision_narrowphase_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,138], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[30,135], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2', sources=bullet2_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,137], compileflags=cflags ) diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h index db8b37989f5..ccfad19b87a 100644 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -20,7 +20,6 @@ subject to the following restrictions: #include "btBulletCollisionCommon.h" #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" -#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h" #include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" #include "BulletDynamics/Dynamics/btRigidBody.h" -- cgit v1.2.3 From 5e1bbde01d0a77c7b032197cff860305462a9cb2 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Fri, 8 Jun 2012 16:17:57 +0000 Subject: Particle Info node for Cycles. This can be used to access particle information in material shaders for dupli objects. For now only the particle Age and individual Lifetime (in frames) are supported, more attributes can be added when needed. The particle data is stored in a separate texture if any of the dupli objects uses particle info nodes in shaders. To map dupli objects onto particles the store an additional particle_index value, which is different from the simple dupli object index (only visible particles, also works for particle dupli groups mode). Some simple use cases on the code.blender.org blog: http://code.blender.org/index.php/2012/05/particle-info-node/ --- intern/cycles/blender/CMakeLists.txt | 1 + intern/cycles/blender/blender_object.cpp | 43 +++--- intern/cycles/blender/blender_particles.cpp | 158 +++++++++++++++++++++ intern/cycles/blender/blender_shader.cpp | 4 + intern/cycles/blender/blender_sync.h | 5 +- intern/cycles/kernel/kernel_object.h | 25 ++++ intern/cycles/kernel/kernel_textures.h | 3 + intern/cycles/kernel/kernel_types.h | 2 + intern/cycles/kernel/svm/svm.h | 3 + intern/cycles/kernel/svm/svm_geometry.h | 22 +++ intern/cycles/kernel/svm/svm_types.h | 8 +- intern/cycles/render/nodes.cpp | 41 ++++++ intern/cycles/render/nodes.h | 6 + intern/cycles/render/object.cpp | 44 +++++- intern/cycles/render/object.h | 9 ++ intern/cycles/render/scene.h | 3 + source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/anim.c | 61 ++++---- source/blender/blenkernel/intern/node.c | 1 + source/blender/makesdna/DNA_object_types.h | 9 ++ .../blender/makesrna/intern/rna_nodetree_types.h | 1 + source/blender/makesrna/intern/rna_object.c | 10 ++ source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_shader.h | 1 + .../nodes/shader/nodes/node_shader_particle_info.c | 48 +++++++ 25 files changed, 460 insertions(+), 50 deletions(-) create mode 100644 intern/cycles/blender/blender_particles.cpp create mode 100644 source/blender/nodes/shader/nodes/node_shader_particle_info.c diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 003c6c84f8f..a8c7eef89fa 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -22,6 +22,7 @@ set(SRC blender_camera.cpp blender_mesh.cpp blender_object.cpp + blender_particles.cpp blender_python.cpp blender_session.cpp blender_shader.cpp diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index cea3b0256bd..b70491a7b82 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -192,7 +192,7 @@ void BlenderSync::sync_background_light() /* Object */ -void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag, int motion) +void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) { /* light is handled separately */ if(object_is_light(b_ob)) { @@ -270,6 +270,12 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, object->visibility &= ~PATH_RAY_CAMERA; } + object->particle_id = particle_id; + + /* particle sync */ + if (object_use_particles(b_ob)) + sync_particles(object, b_ob); + object->tag_update(scene); } } @@ -292,54 +298,51 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) /* object loop */ BL::Scene::objects_iterator b_ob; BL::Scene b_sce = b_scene; + int particle_offset = 0; for(; b_sce; b_sce = b_sce.background_set()) { for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) { bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); uint ob_layer = get_layer(b_ob->layers()); + hide = hide || !(ob_layer & scene_layer); + + if(!hide) { + + int num_particles = object_count_particles(*b_ob); - if(!hide && (ob_layer & scene_layer)) { if(b_ob->is_duplicator()) { + hide = true; /* duplicators hidden by default */ + /* dupli objects */ object_create_duplilist(*b_ob, b_scene); BL::Object::dupli_list_iterator b_dup; - int b_index = 0; - for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) { Transform tfm = get_transform(b_dup->matrix()); BL::Object b_dup_ob = b_dup->object(); bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render(); - if(!(b_dup->hide() || dup_hide)) - sync_object(*b_ob, b_index, b_dup_ob, tfm, ob_layer, motion); - - b_index++; + if(!(b_dup->hide() || dup_hide)) { + sync_object(*b_ob, b_dup->index(), b_dup_ob, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); + } } object_free_duplilist(*b_ob); - - hide = true; } /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; - bool render_emitter = false; - - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { - if(b_psys->settings().use_render_emitter()) { + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + if(b_psys->settings().use_render_emitter()) hide = false; - render_emitter = true; - } - else if(!render_emitter) - hide = true; - } if(!hide) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion); + sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion, 0); } + + particle_offset += num_particles; } } } diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp new file mode 100644 index 00000000000..8a208cb5676 --- /dev/null +++ b/intern/cycles/blender/blender_particles.cpp @@ -0,0 +1,158 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "object.h" + +#include "mesh.h" +#include "blender_sync.h" +#include "blender_util.h" + +#include "util_foreach.h" + +CCL_NAMESPACE_BEGIN + +/* Utilities */ + + +/* Particles Sync */ + +bool BlenderSync::object_use_particles(BL::Object b_ob) +{ + /* Particle data is only needed for + * a) Billboard render mode if object's own material uses particle info + * b) object/group render mode if any dupli object's material uses particle info + * + * Note: Meshes have to be synced at this point! + */ + bool use_particles = false; + + BL::Object::particle_systems_iterator b_psys; + for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { + switch (b_psys->settings().render_type()) { + /* XXX not implemented yet! + * billboards/strands would become part of the mesh data (?), + * so the mesh attributes would store whether particle info is required. + */ + #if 0 + case BL::ParticleSettings::render_type_BILLBOARD: + case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */ + BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data(); + Mesh *mesh = mesh_map.find(key); + if (mesh) { + use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE); + } + break; + } + #endif + + case BL::ParticleSettings::render_type_OBJECT: { + BL::Object b_dupli_ob = b_psys->settings().dupli_object(); + if (b_dupli_ob) { + BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); + Mesh *mesh = mesh_map.find(key); + if (mesh) { + use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE); + } + } + break; + } + + case BL::ParticleSettings::render_type_GROUP: { + BL::Group b_dupli_group = b_psys->settings().dupli_group(); + if (b_dupli_group) { + BL::Group::objects_iterator b_gob; + for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { + BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data(); + Mesh *mesh = mesh_map.find(key); + if (mesh) { + use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE); + } + } + } + break; + } + } + } + + return use_particles; +} + +static bool use_particle_system(BL::ParticleSystem b_psys) +{ + /* only use duplicator particles? disabled particle info for + * halo and billboard to reduce particle count. + * Probably not necessary since particles don't contain a huge amount + * of data compared to other textures. + */ + #if 0 + int render_type = b_psys->settings().render_type(); + return (render_type == BL::ParticleSettings::render_type_OBJECT + || render_type == BL::ParticleSettings::render_type_GROUP); + #endif + + return true; +} + +static bool use_particle(BL::Particle b_pa) +{ + return b_pa.is_exist() && b_pa.is_visible() && b_pa.alive_state()==BL::Particle::alive_state_ALIVE; +} + +int BlenderSync::object_count_particles(BL::Object b_ob) +{ + int tot = 0; + BL::Object::particle_systems_iterator b_psys; + for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { + if (use_particle_system(*b_psys)) { + BL::ParticleSystem::particles_iterator b_pa; + for(b_psys->particles.begin(b_pa); b_pa != b_psys->particles.end(); ++b_pa) { + if(use_particle(*b_pa)) + ++tot; + } + } + } + return tot; +} + +void BlenderSync::sync_particles(Object *ob, BL::Object b_ob) +{ + int tot = object_count_particles(b_ob); + + ob->particles.clear(); + ob->particles.reserve(tot); + + int index; + BL::Object::particle_systems_iterator b_psys; + for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { + if (use_particle_system(*b_psys)) { + BL::ParticleSystem::particles_iterator b_pa; + for(b_psys->particles.begin(b_pa), index=0; b_pa != b_psys->particles.end(); ++b_pa, ++index) { + if(use_particle(*b_pa)) { + Particle pa; + + pa.age = b_scene.frame_current() - b_pa->birth_time(); + pa.lifetime = b_pa->lifetime(); + + ob->particles.push_back(pa); + } + } + } + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 130b73a2808..a7be0a8fb54 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -337,6 +337,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = new ObjectInfoNode(); break; } + case BL::ShaderNode::type_PARTICLE_INFO: { + node = new ParticleInfoNode(); + break; + } case BL::ShaderNode::type_TEX_IMAGE: { BL::ShaderNodeTexImage b_image_node(b_node); BL::Image b_image(b_image_node.image()); diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index bc6258d35ac..8c31c4b86ba 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -80,17 +80,20 @@ private: void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); - void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion); + void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion, int particle_id); void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm); void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); void sync_camera_motion(BL::Object b_ob, int motion); + void sync_particles(Object *ob, BL::Object b_ob); /* util */ void find_shader(BL::ID id, vector& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); bool object_is_mesh(BL::Object b_ob); bool object_is_light(BL::Object b_ob); + bool object_use_particles(BL::Object b_ob); + int object_count_particles(BL::Object b_ob); /* variables */ BL::BlendData b_data; diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 05c45c490d8..18e0b1e8a87 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -154,10 +154,35 @@ __device_inline float object_random_number(KernelGlobals *kg, int object) return f.z; } +__device_inline uint object_particle_id(KernelGlobals *kg, int object) +{ + if(object == ~0) + return 0.0f; + + int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES; + float4 f = kernel_tex_fetch(__objects, offset); + return __float_as_int(f.w); +} + __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd) { return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1); } +__device float particle_age(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f = kernel_tex_fetch(__particles, offset); + return f.x; +} + +__device float particle_lifetime(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f = kernel_tex_fetch(__particles, offset); + return f.y; +} + + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 482f886df3e..c1b8eed3dff 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -52,6 +52,9 @@ KERNEL_TEX(float4, texture_float4, __light_data) KERNEL_TEX(float2, texture_float2, __light_background_marginal_cdf) KERNEL_TEX(float2, texture_float2, __light_background_conditional_cdf) +/* particles */ +KERNEL_TEX(float4, texture_float4, __particles) + /* shaders */ KERNEL_TEX(uint4, texture_uint4, __svm_nodes) KERNEL_TEX(uint, texture_uint, __shader_flag) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 4fd57a5f2b3..77a800b0e67 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -33,6 +33,7 @@ CCL_NAMESPACE_BEGIN #define LIGHT_SIZE 4 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 +#define PARTICLE_SIZE 1 #define TIME_INVALID FLT_MAX /* device capabilities */ @@ -359,6 +360,7 @@ typedef enum AttributeStandard { ATTR_STD_POSITION_UNDISPLACED, ATTR_STD_MOTION_PRE, ATTR_STD_MOTION_POST, + ATTR_STD_PARTICLE, ATTR_STD_NUM, ATTR_STD_NOT_FOUND = ~0 diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 6a05639beb9..8901e5e9628 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -269,6 +269,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_OBJECT_INFO: svm_node_object_info(kg, sd, stack, node.y, node.z); break; + case NODE_PARTICLE_INFO: + svm_node_particle_info(kg, sd, stack, node.y, node.z); + break; #endif case NODE_CONVERT: svm_node_convert(sd, stack, node.y, node.z, node.w); diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index dab19983946..88127b56474 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -94,5 +94,27 @@ __device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *sta stack_store_float(stack, out_offset, data); } +/* Particle Info */ + +__device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) +{ + float data; + + switch(type) { + case NODE_INFO_PAR_AGE: { + uint particle_id = object_particle_id(kg, sd->object); + data = particle_age(kg, particle_id); + stack_store_float(stack, out_offset, data); + break; + } + case NODE_INFO_PAR_LIFETIME: { + uint particle_id = object_particle_id(kg, sd->object); + data = particle_lifetime(kg, particle_id); + stack_store_float(stack, out_offset, data); + break; + } + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 97849736ef6..2d756d57f41 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -93,7 +93,8 @@ typedef enum NodeType { NODE_RGB_CURVES = 6000, NODE_MIN_MAX = 6100, NODE_LIGHT_FALLOFF = 6200, - NODE_OBJECT_INFO = 6300 + NODE_OBJECT_INFO = 6300, + NODE_PARTICLE_INFO = 6400 } NodeType; typedef enum NodeAttributeType { @@ -117,6 +118,11 @@ typedef enum NodeObjectInfo { NODE_INFO_OB_RANDOM } NodeObjectInfo; +typedef enum NodeParticleInfo { + NODE_INFO_PAR_AGE, + NODE_INFO_PAR_LIFETIME +} NodeParticleInfo; + typedef enum NodeLightPath { NODE_LP_camera = 0, NODE_LP_shadow, diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 16c6b07261a..1c9eeacddbe 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1789,6 +1789,47 @@ void ObjectInfoNode::compile(OSLCompiler& compiler) compiler.add(this, "node_object_info"); } +/* Particle Info */ + +ParticleInfoNode::ParticleInfoNode() +: ShaderNode("particle_info") +{ + add_output("Age", SHADER_SOCKET_FLOAT); + add_output("Lifetime", SHADER_SOCKET_FLOAT); +} + +void ParticleInfoNode::attributes(AttributeRequestSet *attributes) +{ + if(!output("Age")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); + if(!output("Lifetime")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); + + ShaderNode::attributes(attributes); +} + +void ParticleInfoNode::compile(SVMCompiler& compiler) +{ + ShaderOutput *out; + + out = output("Age"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, out->stack_offset); + } + + out = output("Lifetime"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, out->stack_offset); + } +} + +void ParticleInfoNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_particle_info"); +} + /* Value */ ValueNode::ValueNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 2d0d58d1e94..650758a6113 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -290,6 +290,12 @@ public: SHADER_NODE_CLASS(ObjectInfoNode) }; +class ParticleInfoNode : public ShaderNode { +public: + SHADER_NODE_CLASS(ParticleInfoNode) + void attributes(AttributeRequestSet *attributes); +}; + class ValueNode : public ShaderNode { public: SHADER_NODE_CLASS(ValueNode) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 5c7e48a38eb..259a0d25bcc 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -25,6 +25,7 @@ #include "util_foreach.h" #include "util_map.h" #include "util_progress.h" +#include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -38,6 +39,7 @@ Object::Object() visibility = ~0; random_id = 0; pass_id = 0; + particle_id = 0; bounds = BoundBox::empty; motion.pre = transform_identity(); motion.post = transform_identity(); @@ -200,7 +202,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene memcpy(&objects[offset], &tfm, sizeof(float4)*3); memcpy(&objects[offset+3], &itfm, sizeof(float4)*3); - objects[offset+6] = make_float4(surface_area, pass_id, random_number, 0.0f); + objects[offset+6] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id)); if(need_motion == Scene::MOTION_PASS) { /* motion transformations, is world/object space depending if mesh @@ -246,6 +248,38 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene device->tex_alloc("__object_flag", dscene->object_flag); } +void ObjectManager::device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +{ + /* count particles. + * adds one dummy particle at the beginning to avoid invalid lookups, + * in case a shader uses particle info without actual particle data. + */ + int num_particles = 1; + foreach(Object *ob, scene->objects) + num_particles += ob->particles.size(); + + float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles); + + /* dummy particle */ + particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + int i = 1; + foreach(Object *ob, scene->objects) { + foreach(Particle &pa, ob->particles) { + /* pack in texture */ + int offset = i*PARTICLE_SIZE; + + particles[offset] = make_float4(pa.age, pa.lifetime, 0.0f, 0.0f); + + i++; + + if(progress.get_cancel()) return; + } + } + + device->tex_alloc("__particles", dscene->particles); +} + void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { if(!need_update) @@ -271,6 +305,11 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc if(progress.get_cancel()) return; + progress.set_status("Updating Objects", "Copying Particles to device"); + device_update_particles(device, dscene, scene, progress); + + if(progress.get_cancel()) return; + need_update = false; } @@ -281,6 +320,9 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->object_flag); dscene->object_flag.clear(); + + device->tex_free(dscene->particles); + dscene->particles.clear(); } void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index a3bd748a8a4..6d674731b07 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -35,6 +35,11 @@ struct Transform; /* Object */ +struct Particle { + float age; + float lifetime; +}; + class Object { public: Mesh *mesh; @@ -49,6 +54,9 @@ public: bool use_motion; bool use_holdout; + int particle_id; + vector particles; + Object(); ~Object(); @@ -69,6 +77,7 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 90bc47d5c8e..8b9944cb76e 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -82,6 +82,9 @@ public: device_vector light_background_marginal_cdf; device_vector light_background_conditional_cdf; + /* particles */ + device_vector particles; + /* shaders */ device_vector svm_nodes; device_vector shader_flag; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 5fbd58e26a5..b1e5fabc456 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -527,6 +527,7 @@ struct ShadeResult; #define SH_NODE_BRIGHTCONTRAST 165 #define SH_NODE_LIGHT_FALLOFF 166 #define SH_NODE_OBJECT_INFO 167 +#define SH_NODE_PARTICLE_INFO 168 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index f73221066b1..701ce6c8299 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -75,7 +75,7 @@ /* --------------------- */ /* forward declarations */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated); +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated); /* ******************************************************************** */ /* Animation Visualisation */ @@ -699,7 +699,7 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua /* ******************************************************************** */ /* Dupli-Geometry */ -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int type, int animated) +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, int animated) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); @@ -709,6 +709,7 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i copy_m4_m4(dob->omat, ob->obmat); dob->origlay = ob->lay; dob->index = index; + dob->particle_index = par_index; dob->type = type; dob->animated = (type == OB_DUPLIGROUP) && animated; ob->lay = lay; @@ -716,7 +717,7 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i return dob; } -static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated) { DupliObject *dob; Group *group; @@ -748,7 +749,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, i mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } - dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); + dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, animated); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || @@ -763,14 +764,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, i if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, level + 1, animated); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -818,7 +819,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); - dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated); + dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, animated); copy_m4_m4(dob->omat, copyob.obmat); } } @@ -849,6 +850,7 @@ typedef struct vertexDupliData { Scene *scene; Object *ob, *par; float (*orco)[3]; + int par_index; } vertexDupliData; /* ------------- */ @@ -885,7 +887,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], origlay = vdd->ob->lay; - dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated); + dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->animated); /* restore the original layer so that each dupli will have proper dob->origlay */ vdd->ob->lay = origlay; @@ -897,12 +899,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->level + 1, vdd->animated); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated); copy_m4_m4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated) { Object *ob, *ob_iter; Mesh *me = par->data; @@ -986,6 +988,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.scene = scene; vdd.par = par; copy_m4_m4(vdd.pmat, pmat); + vdd.par_index = par_index; /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ @@ -1024,7 +1027,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated) { Object *ob, *ob_iter; Base *base = NULL; @@ -1171,7 +1174,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); - dob = new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIFACES, animated); + dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, animated); if (G.rendering) { w = 1.0f / (float)mp->totloop; @@ -1194,7 +1197,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level + 1, animated); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1214,7 +1217,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; @@ -1228,7 +1231,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0; float (*obmat)[4], (*oldobmat)[4]; - int a, b, counter, hair = 0; + int a, b, counter, index, hair = 0; int totpart, totchild, totgroup = 0 /*, pa_num */; int no_draw_flag = PARS_UNEXIST; @@ -1342,6 +1345,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else a = totpart; + index = 0; for (pa = psys->particles, counter = 0; a < totpart + totchild; a++, pa++, counter++) { if (a < totpart) { /* handle parent particle */ @@ -1437,7 +1441,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else copy_m4_m4(mat, tmat); - dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); + dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, obcopylist[b].obmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); @@ -1479,11 +1483,14 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); + dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, oldobmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } + + /* only counts visible particles */ + ++index; } /* restore objects since they were changed in BKE_object_where_is_calc_time */ @@ -1530,7 +1537,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, int animated) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, int animated) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1569,7 +1576,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, i copy_m4_m4(obmat, par->obmat); copy_v3_v3(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a, OB_DUPLIVERTS, animated); + new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, animated); } } @@ -1578,7 +1585,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, i /* ------------- */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1598,31 +1605,31 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, psys, level + 1, animated); + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated); } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, level + 1, animated); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, scene, ob, level + 1, animated); + font_duplilist(duplilist, scene, ob, par_index, level + 1, animated); } } } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, level + 1, animated); + face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, scene, ob, level + 1, animated); + frames_duplilist(duplilist, scene, ob, par_index, level + 1, animated); } } else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, level + 1, animated); /* now recursive */ + group_duplilist(duplilist, scene, ob, par_index, level + 1, animated); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1638,7 +1645,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0); return duplilist; } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 86a1f715c3c..d62e91dbde5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1956,6 +1956,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_fresnel(ttype); register_node_type_sh_layer_weight(ttype); register_node_type_sh_tex_coord(ttype); + register_node_type_sh_particle_info(ttype); register_node_type_sh_background(ttype); register_node_type_sh_bsdf_diffuse(ttype); diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 44d7ec660f2..24d33b49db2 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -301,6 +301,15 @@ typedef struct DupliObject { short type; /* from Object.transflag */ char no_draw, animated; + + /* Lowest-level particle index. + * Note: This is needed for particle info in shaders. + * Otherwise dupli groups in particle systems would override the + * index value from higher dupli levels. Would be nice to have full generic access + * to all dupli levels somehow, but for now this should cover most use-cases. + */ + int particle_index; + int pad; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 2b8050adca7..3981afe5349 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -80,6 +80,7 @@ DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NE DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" ) DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) +DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" ) DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" ) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 7e3b368aa64..0399a8ee60d 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2545,6 +2545,16 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Hide", "Don't show dupli object in viewport or render"); + prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "index"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Index", "Index in the lowest-level dupli list"); + + prop = RNA_def_property(srna, "particle_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "particle_index"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list"); + /* TODO: DupliObject has more properties that can be wrapped */ } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index c637e3606f1..8b2a5ebd263 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -159,6 +159,7 @@ set(SRC shader/nodes/node_shader_light_path.c shader/nodes/node_shader_light_falloff.c shader/nodes/node_shader_object_info.c + shader/nodes/node_shader_particle_info.c shader/nodes/node_shader_mix_shader.c shader/nodes/node_shader_add_shader.c shader/nodes/node_shader_output_lamp.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index dd6d25380b4..6b000181953 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -78,6 +78,7 @@ void register_node_type_sh_object_info(struct bNodeTreeType *ttype); void register_node_type_sh_fresnel(struct bNodeTreeType *ttype); void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype); void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype); +void register_node_type_sh_particle_info(struct bNodeTreeType *ttype); void register_node_type_sh_background(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c new file mode 100644 index 00000000000..6456742e22b --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c @@ -0,0 +1,48 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +static bNodeSocketTemplate outputs[] = { + { SOCK_FLOAT, 0, "Age" }, + { SOCK_FLOAT, 0, "Lifetime" }, + { -1, 0, "" } +}; + +/* node type definition */ +void register_node_type_sh_particle_info(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, NULL, outputs); + node_type_size(&ntype, 150, 60, 200); + + nodeRegisterType(ttype, &ntype); +} + -- cgit v1.2.3 From 04766ab071e43d041f19c586baa316da1432f614 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 16:42:24 +0000 Subject: Added sorting by average reprojection error to motion tracking dopesheet. --- source/blender/blenkernel/BKE_tracking.h | 1 + source/blender/blenkernel/intern/tracking.c | 28 ++++++++++++++++++++++++++++ source/blender/makesdna/DNA_space_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 1 + 4 files changed, 31 insertions(+) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 817cb477aba..4d9a5746c87 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -202,5 +202,6 @@ void BKE_tracking_dopesheet_update(struct MovieTracking *tracking, int sort_meth #define TRACK_SORT_NAME 0 #define TRACK_SORT_LONGEST 1 #define TRACK_SORT_TOTAL 2 +#define TRACK_SORT_AVERAGE_ERROR 3 #endif diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 4abb461bc81..fb78e89cc30 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -3115,6 +3115,17 @@ static int channels_longest_segment_sort(void *a, void *b) return 0; } +static int channels_average_error_sort(void *a, void *b) +{ + MovieTrackingDopesheetChannel *channel_a = a; + MovieTrackingDopesheetChannel *channel_b = b; + + if (channel_a->track->error > channel_b->track->error) + return 1; + else + return 0; +} + static int channels_alpha_inverse_sort(void *a, void *b) { if (channels_alpha_sort(a, b)) @@ -3139,6 +3150,17 @@ static int channels_longest_segment_inverse_sort(void *a, void *b) return 1; } +static int channels_average_error_inverse_sort(void *a, void *b) +{ + MovieTrackingDopesheetChannel *channel_a = a; + MovieTrackingDopesheetChannel *channel_b = b; + + if (channel_a->track->error < channel_b->track->error) + return 1; + else + return 0; +} + static void channels_segments_calc(MovieTrackingDopesheetChannel *channel) { MovieTrackingTrack *track = channel->track; @@ -3234,6 +3256,9 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, i else if (sort_method == TRACK_SORT_TOTAL) { BLI_sortlist(&dopesheet->channels, channels_total_track_inverse_sort); } + else if (sort_method == TRACK_SORT_AVERAGE_ERROR) { + BLI_sortlist(&dopesheet->channels, channels_average_error_inverse_sort); + } } else { if (sort_method == TRACK_SORT_NAME) { @@ -3245,6 +3270,9 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, i else if (sort_method == TRACK_SORT_TOTAL) { BLI_sortlist(&dopesheet->channels, channels_total_track_sort); } + else if (sort_method == TRACK_SORT_AVERAGE_ERROR) { + BLI_sortlist(&dopesheet->channels, channels_average_error_sort); + } } dopesheet->sort_method = sort_method; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 213195eb9c8..7e9a1d976d8 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1060,6 +1060,7 @@ typedef enum eSpaceClip_Dopesheet_Sort { SC_DOPE_SORT_NAME = 0, SC_DOPE_SORT_LONGEST, SC_DOPE_SORT_TOTAL, + SC_DOPE_SORT_AVERAGE_ERROR, } eSpaceClip_Dopesheet_Sort; /* SpaceClip->dope_flag */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 082c7c406e2..98ff8ab70bf 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2999,6 +2999,7 @@ static void rna_def_space_clip(BlenderRNA *brna) {SC_DOPE_SORT_NAME, "NAME", 0, "Name", "Sort channels by their names"}, {SC_DOPE_SORT_LONGEST, "LONGEST", 0, "Longest", "Sort channels by longest tracked segment"}, {SC_DOPE_SORT_TOTAL, "TOTAL", 0, "Total", "Sort channels by overall amount of tracked segments"}, + {SC_DOPE_SORT_AVERAGE_ERROR, "AVERAGE_ERROR", 0, "Average Error", "Sort channels by average reprojection error of tracks after solve"}, {0, NULL, 0, NULL, NULL} }; -- cgit v1.2.3 From ff792f3249d6c02557860733e63ffb4f3eb8b0e1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 16:51:38 +0000 Subject: Selecting track channel in tracking dopesheet would make track active, just as it happens with curve view. --- source/blender/editors/space_clip/clip_dopesheet_ops.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index 0fd17523425..7c08f1e2668 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -93,6 +93,10 @@ static int dopesheet_select_channel_exec(bContext *C, wmOperator *op) track->flag ^= TRACK_DOPE_SEL; else track->flag |= TRACK_DOPE_SEL; + + if (track->flag & TRACK_DOPE_SEL) { + tracking->act_track = track; + } } else if (!extend) track->flag &= ~TRACK_DOPE_SEL; -- cgit v1.2.3 From 6563a05cad33880c53bb002c7b3d217f948f12b4 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Fri, 8 Jun 2012 17:02:02 +0000 Subject: Added a default case in switch to avoid paranoid compiler warnings. --- intern/cycles/blender/blender_particles.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index 8a208cb5676..2b19009989a 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -86,6 +86,10 @@ bool BlenderSync::object_use_particles(BL::Object b_ob) } break; } + + default: + /* avoid compiler warning */ + break; } } -- cgit v1.2.3 From 916524d650a5d9a6e397f64c164d91171b84d129 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 17:16:32 +0000 Subject: Fixed issue with non-updating frame in clip editor when toggling undistorted render while frame is grayscaled. Also corrected some typos in movieclip. --- source/blender/blenkernel/intern/movieclip.c | 8 ++++---- source/blender/editors/space_clip/clip_editor.c | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 985fc433c13..abdc8835d43 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -314,7 +314,7 @@ typedef struct MovieClipCache { /* cache for undistorted shot */ float principal[2]; float k1, k2, k3; - short undistoriton_used; + short undistortion_used; int proxy; short render_flag; @@ -627,7 +627,7 @@ static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *use if (!check_undistortion_cache_flags(clip)) return NULL; } - else if (cache->postprocessed.undistoriton_used) + else if (cache->postprocessed.undistortion_used) return NULL; IMB_refImBuf(cache->postprocessed.ibuf); @@ -660,11 +660,11 @@ static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *u if (need_undistortion_postprocess(user, flag)) { copy_v2_v2(cache->postprocessed.principal, camera->principal); copy_v3_v3(&cache->postprocessed.k1, &camera->k1); - cache->postprocessed.undistoriton_used = TRUE; + cache->postprocessed.undistortion_used = TRUE; postproc_ibuf = get_undistorted_ibuf(clip, NULL, ibuf); } else { - cache->postprocessed.undistoriton_used = FALSE; + cache->postprocessed.undistortion_used = FALSE; } if (postprocess_flag) { diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index bcda1d59555..504d96df072 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -522,6 +522,7 @@ typedef struct SpaceClipDrawContext { /* fields to check if cache is still valid */ int framenr, start_frame; + short render_size, render_flag; } SpaceClipDrawContext; int ED_space_clip_texture_buffer_supported(SpaceClip *sc) @@ -559,6 +560,8 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) * so not changed image buffer pointer means unchanged image content */ need_rebind |= context->texture_ibuf != ibuf; need_rebind |= context->framenr != sc->user.framenr; + need_rebind |= context->render_size != sc->user.render_size; + need_rebind |= context->render_flag != sc->user.render_flag; need_rebind |= context->start_frame != clip->start_frame; if (need_rebind) { @@ -614,6 +617,8 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf) context->image_width = ibuf->x; context->image_height = ibuf->y; context->framenr = sc->user.framenr; + context->render_size = sc->user.render_size; + context->render_flag = sc->user.render_flag; context->start_frame = clip->start_frame; } else { -- cgit v1.2.3 From 73a47caa08e7f034819943e65136a588aa304496 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 8 Jun 2012 18:16:20 +0000 Subject: Fixed issue with missed reconstruction error in clip editor header Actually was causes by error in RNA bindings which lead to empty reconstruction returned for cameraObject.reconstruction. --- source/blender/makesrna/intern/rna_tracking.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 7a6753ad588..b1d2bc7ac8d 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -338,6 +338,20 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po } } +static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr) +{ + MovieTrackingObject *object = (MovieTrackingObject* )ptr->data; + + if (object->flag & TRACKING_OBJECT_CAMERA) { + MovieClip *clip = (MovieClip*)ptr->id.data; + + return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingReconstruction, &clip->tracking.reconstruction); + } + else { + return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingReconstruction, &object->reconstruction); + } +} + static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr) { MovieClip *clip = (MovieClip*)ptr->id.data; @@ -1330,6 +1344,7 @@ static void rna_def_trackingObject(BlenderRNA *brna) /* reconstruction */ prop = RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MovieTrackingReconstruction"); + RNA_def_property_pointer_funcs(prop, "rna_trackingObject_reconstruction_get", NULL, NULL, NULL); /* scale */ prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); -- cgit v1.2.3 From 3d740121ed6f0264ae85eeafe6c0a5addf68ac8c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 8 Jun 2012 19:21:12 +0000 Subject: Cycles / Code Cleanup: * Removed a workaround for the NodeType enum, uses consecutive values now. I could not find issues with CUDA, when compiling with Toolkit 4.2 (all sm kernels) and regression files rendered fine on my GPU with sm_21. --- intern/cycles/kernel/svm/svm_types.h | 121 +++++++++++++++++------------------ 1 file changed, 58 insertions(+), 63 deletions(-) diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 2d756d57f41..e02e16b6ff4 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -30,71 +30,66 @@ CCL_NAMESPACE_BEGIN /* Nodes */ -/* note that we do not simply use 0, 1, 2, .. as values for these. this works - * around an obscure CUDA bug that happens when compiling for fermi. why it - * happens i have no idea, but consecutive values are problematic, maybe it - * generates an incorrect jump table. */ - typedef enum NodeType { NODE_END = 0, - NODE_CLOSURE_BSDF = 100, - NODE_CLOSURE_EMISSION = 200, - NODE_CLOSURE_BACKGROUND = 300, - NODE_CLOSURE_SET_WEIGHT = 400, - NODE_CLOSURE_WEIGHT = 500, - NODE_MIX_CLOSURE = 600, - NODE_JUMP = 700, - NODE_TEX_IMAGE = 1000, - NODE_TEX_SKY = 1100, - NODE_GEOMETRY = 1200, - NODE_LIGHT_PATH = 1300, - NODE_VALUE_F = 1400, - NODE_VALUE_V = 1500, - NODE_MIX = 1600, - NODE_ATTR = 1700, - NODE_CONVERT = 1900, - NODE_FRESNEL = 2000, - NODE_EMISSION_WEIGHT = 2100, - NODE_TEX_GRADIENT = 2200, - NODE_TEX_VORONOI = 2300, - NODE_TEX_MUSGRAVE = 2400, - NODE_TEX_WAVE = 2500, - NODE_TEX_MAGIC = 2600, - NODE_TEX_NOISE = 3000, - NODE_SHADER_JUMP = 3100, - NODE_SET_DISPLACEMENT = 3200, - NODE_GEOMETRY_BUMP_DX = 3300, - NODE_GEOMETRY_BUMP_DY = 3400, - NODE_SET_BUMP = 3500, - NODE_MATH = 3600, - NODE_VECTOR_MATH = 3700, - NODE_MAPPING = 3800, - NODE_TEX_COORD = 3900, - NODE_TEX_COORD_BUMP_DX = 4000, - NODE_TEX_COORD_BUMP_DY = 4100, - NODE_ADD_CLOSURE = 4200, - NODE_EMISSION_SET_WEIGHT_TOTAL = 4300, - NODE_ATTR_BUMP_DX = 4400, - NODE_ATTR_BUMP_DY = 4500, - NODE_TEX_ENVIRONMENT = 4600, - NODE_CLOSURE_HOLDOUT = 4700, - NODE_LAYER_WEIGHT = 4800, - NODE_CLOSURE_VOLUME = 4900, - NODE_SEPARATE_RGB = 5000, - NODE_COMBINE_RGB = 5100, - NODE_HSV = 5200, - NODE_CAMERA = 5300, - NODE_INVERT = 5400, - NODE_NORMAL = 5500, - NODE_GAMMA = 5600, - NODE_TEX_CHECKER = 5700, - NODE_BRIGHTCONTRAST = 5800, - NODE_RGB_RAMP = 5900, - NODE_RGB_CURVES = 6000, - NODE_MIN_MAX = 6100, - NODE_LIGHT_FALLOFF = 6200, - NODE_OBJECT_INFO = 6300, - NODE_PARTICLE_INFO = 6400 + NODE_CLOSURE_BSDF, + NODE_CLOSURE_EMISSION, + NODE_CLOSURE_BACKGROUND, + NODE_CLOSURE_SET_WEIGHT, + NODE_CLOSURE_WEIGHT, + NODE_MIX_CLOSURE, + NODE_JUMP, + NODE_TEX_IMAGE, + NODE_TEX_SKY, + NODE_GEOMETRY, + NODE_LIGHT_PATH, + NODE_VALUE_F, + NODE_VALUE_V, + NODE_MIX, + NODE_ATTR, + NODE_CONVERT, + NODE_FRESNEL, + NODE_EMISSION_WEIGHT, + NODE_TEX_GRADIENT, + NODE_TEX_VORONOI, + NODE_TEX_MUSGRAVE, + NODE_TEX_WAVE, + NODE_TEX_MAGIC, + NODE_TEX_NOISE, + NODE_SHADER_JUMP, + NODE_SET_DISPLACEMENT, + NODE_GEOMETRY_BUMP_DX, + NODE_GEOMETRY_BUMP_DY, + NODE_SET_BUMP, + NODE_MATH, + NODE_VECTOR_MATH, + NODE_MAPPING, + NODE_TEX_COORD, + NODE_TEX_COORD_BUMP_DX, + NODE_TEX_COORD_BUMP_DY, + NODE_ADD_CLOSURE, + NODE_EMISSION_SET_WEIGHT_TOTAL, + NODE_ATTR_BUMP_DX, + NODE_ATTR_BUMP_DY, + NODE_TEX_ENVIRONMENT, + NODE_CLOSURE_HOLDOUT, + NODE_LAYER_WEIGHT, + NODE_CLOSURE_VOLUME, + NODE_SEPARATE_RGB, + NODE_COMBINE_RGB, + NODE_HSV, + NODE_CAMERA, + NODE_INVERT, + NODE_NORMAL, + NODE_GAMMA, + NODE_TEX_CHECKER, + NODE_BRIGHTCONTRAST, + NODE_RGB_RAMP, + NODE_RGB_CURVES, + NODE_MIN_MAX, + NODE_LIGHT_FALLOFF, + NODE_OBJECT_INFO, + NODE_PARTICLE_INFO } NodeType; typedef enum NodeAttributeType { -- cgit v1.2.3 From 7c87f646c256dc8b8a97de2ad2d5c4b0dbe1a4a0 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 8 Jun 2012 19:57:25 +0000 Subject: Cycles / Textures: * Some code cleanup, removed old enums, which are not used anymore. * Some renaming for consistency and to match new texture names. --- intern/cycles/kernel/svm/svm_gradient.h | 4 ++-- intern/cycles/kernel/svm/svm_texture.h | 2 +- intern/cycles/kernel/svm/svm_types.h | 29 ++++++----------------------- intern/cycles/kernel/svm/svm_wave.h | 6 +++--- 4 files changed, 12 insertions(+), 29 deletions(-) diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h index c7013800d6b..ce551a680b8 100644 --- a/intern/cycles/kernel/svm/svm_gradient.h +++ b/intern/cycles/kernel/svm/svm_gradient.h @@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN /* Gradient */ -__device float svm_gradient(float3 p, NodeBlendType type) +__device float svm_gradient(float3 p, NodeGradientType type) { float x, y, z; @@ -67,7 +67,7 @@ __device void svm_node_tex_gradient(ShaderData *sd, float *stack, uint4 node) float3 co = stack_load_float3(stack, co_offset); - float f = svm_gradient(co, (NodeBlendType)type); + float f = svm_gradient(co, (NodeGradientType)type); f = clamp(f, 0.0f, 1.0f); if(stack_valid(fac_offset)) diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index 448132bff46..da74654f25e 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -188,7 +188,7 @@ __device float noise_basis_hard(float3 p, NodeNoiseBasis basis, int hard) /* Waves */ -__device float noise_wave(NodeWaveType wave, float a) +__device float noise_wave(NodeWaveBasis wave, float a) { if(wave == NODE_WAVE_SINE) { return 0.5f + 0.5f*sin(a); diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index e02e16b6ff4..c1eeeb55268 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -221,11 +221,11 @@ typedef enum NodeNoiseBasis { NODE_NOISE_CELL_NOISE } NodeNoiseBasis; -typedef enum NodeWaveType { +typedef enum NodeWaveBasis { NODE_WAVE_SINE, NODE_WAVE_SAW, NODE_WAVE_TRI -} NodeWaveType; +} NodeWaveBasis; typedef enum NodeMusgraveType { NODE_MUSGRAVE_MULTIFRACTAL, @@ -235,12 +235,12 @@ typedef enum NodeMusgraveType { NODE_MUSGRAVE_HETERO_TERRAIN } NodeMusgraveType; -typedef enum NodeWoodType { +typedef enum NodeWaveType { NODE_WAVE_BANDS, NODE_WAVE_RINGS -} NodeWoodType; +} NodeWaveType; -typedef enum NodeBlendType { +typedef enum NodeGradientType { NODE_BLEND_LINEAR, NODE_BLEND_QUADRATIC, NODE_BLEND_EASING, @@ -248,24 +248,7 @@ typedef enum NodeBlendType { NODE_BLEND_RADIAL, NODE_BLEND_QUADRATIC_SPHERE, NODE_BLEND_SPHERICAL -} NodeBlendType; - -typedef enum NodeBlendAxis { - NODE_BLEND_HORIZONTAL, - NODE_BLEND_VERTICAL -} NodeBlendAxis; - -typedef enum NodeMarbleType { - NODE_MARBLE_SOFT, - NODE_MARBLE_SHARP, - NODE_MARBLE_SHARPER -} NodeMarbleType; - -typedef enum NodeStucciType { - NODE_STUCCI_PLASTIC, - NODE_STUCCI_WALL_IN, - NODE_STUCCI_WALL_OUT -} NodeStucciType; +} NodeGradientType; typedef enum NodeVoronoiColoring { NODE_VORONOI_INTENSITY, diff --git a/intern/cycles/kernel/svm/svm_wave.h b/intern/cycles/kernel/svm/svm_wave.h index 39edd7d9fff..7050bbe7f00 100644 --- a/intern/cycles/kernel/svm/svm_wave.h +++ b/intern/cycles/kernel/svm/svm_wave.h @@ -18,9 +18,9 @@ CCL_NAMESPACE_BEGIN -/* Marble */ +/* Wave */ -__device_noinline float svm_wave(NodeWoodType type, float3 p, float scale, float detail, float distortion, float dscale) +__device_noinline float svm_wave(NodeWaveType type, float3 p, float scale, float detail, float distortion, float dscale) { float w, n; @@ -55,7 +55,7 @@ __device void svm_node_tex_wave(KernelGlobals *kg, ShaderData *sd, float *stack, float distortion = stack_load_float_default(stack, distortion_offset, node2.z); float dscale = stack_load_float_default(stack, dscale_offset, node2.w); - float f = svm_wave((NodeWoodType)type, co, scale, detail, distortion, dscale); + float f = svm_wave((NodeWaveType)type, co, scale, detail, distortion, dscale); if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f); if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, make_float3(f, f, f)); -- cgit v1.2.3 From 8a4f16739ae44c96568a0efae9f668c46bcf8035 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Fri, 8 Jun 2012 19:57:28 +0000 Subject: Fixing a BGE bug where textures could get loaded into VRAM twice. --- source/gameengine/Ketsji/KX_BlenderMaterial.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 018a8d44cc1..939f0693161 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -175,8 +175,8 @@ void KX_BlenderMaterial::OnConstruction(int layer) spit("unable to initialize image("<matname<< ", image will not be available"); } - - else { + // If we're using glsl materials, the textures are handled by bf_gpu, so don't load them twice! + else if (!mMaterial->glslmat) { if ( mMaterial->img[i] ) { if ( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) spit("unable to initialize image("< Date: Fri, 8 Jun 2012 20:17:02 +0000 Subject: Cycles / Cleanup: * All references to old textures should now be finally removed. --- intern/cycles/app/cycles_xml.cpp | 6 +++--- intern/cycles/render/nodes.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index cfa4095104b..1190ee185fd 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -392,9 +392,9 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug snode = dist; } else if(string_iequals(node.name(), "wave_texture")) { - WaveTextureNode *wood = new WaveTextureNode(); - xml_read_enum(&wood->type, WaveTextureNode::type_enum, node, "type"); - snode = wood; + WaveTextureNode *wave = new WaveTextureNode(); + xml_read_enum(&wave->type, WaveTextureNode::type_enum, node, "type"); + snode = wave; } else if(string_iequals(node.name(), "normal")) { snode = new NormalNode(); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 1c9eeacddbe..8fb92d2476e 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -695,7 +695,7 @@ static ShaderEnum wave_type_init() ShaderEnum WaveTextureNode::type_enum = wave_type_init(); WaveTextureNode::WaveTextureNode() -: TextureNode("marble_texture") +: TextureNode("wave_texture") { type = ustring("Bands"); -- cgit v1.2.3 From dfa307f73f593000143d69d868683cc16efd0c1e Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 8 Jun 2012 21:04:48 +0000 Subject: constraints names are not matching (rna and constraint.c). doing rna->constraint.c --- source/blender/blenkernel/intern/constraint.c | 12 ++++++------ source/blender/makesdna/DNA_constraint_types.h | 2 +- source/blender/makesrna/intern/rna_constraint.c | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index afd50de8159..0150646a96c 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1460,7 +1460,7 @@ static bConstraintTypeInfo CTI_ROTLIMIT = { rotlimit_evaluate /* evaluate */ }; -/* --------- Limit Scaling --------- */ +/* --------- Limit Scale --------- */ static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) @@ -1507,7 +1507,7 @@ static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *U static bConstraintTypeInfo CTI_SIZELIMIT = { CONSTRAINT_TYPE_SIZELIMIT, /* type */ sizeof(bSizeLimitConstraint), /* size */ - "Limit Scaling", /* name */ + "Limit Scale", /* name */ "bSizeLimitConstraint", /* struct name */ NULL, /* free data */ NULL, /* id looper */ @@ -1721,7 +1721,7 @@ static bConstraintTypeInfo CTI_ROTLIKE = { rotlike_evaluate /* evaluate */ }; -/* ---------- Copy Scaling ---------- */ +/* ---------- Copy Scale ---------- */ static void sizelike_new_data(void *cdata) { @@ -3352,7 +3352,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t static bConstraintTypeInfo CTI_TRANSFORM = { CONSTRAINT_TYPE_TRANSFORM, /* type */ sizeof(bTransformConstraint), /* size */ - "Transform", /* name */ + "Transformation", /* name */ "bTransformConstraint", /* struct name */ NULL, /* free data */ transform_id_looper, /* id looper */ @@ -4213,10 +4213,10 @@ static void constraints_init_typeinfo(void) constraintsTypeInfo[4] = &CTI_FOLLOWPATH; /* Follow-Path Constraint */ constraintsTypeInfo[5] = &CTI_ROTLIMIT; /* Limit Rotation Constraint */ constraintsTypeInfo[6] = &CTI_LOCLIMIT; /* Limit Location Constraint */ - constraintsTypeInfo[7] = &CTI_SIZELIMIT; /* Limit Scaling Constraint */ + constraintsTypeInfo[7] = &CTI_SIZELIMIT; /* Limit Scale Constraint */ constraintsTypeInfo[8] = &CTI_ROTLIKE; /* Copy Rotation Constraint */ constraintsTypeInfo[9] = &CTI_LOCLIKE; /* Copy Location Constraint */ - constraintsTypeInfo[10] = &CTI_SIZELIKE; /* Copy Scaling Constraint */ + constraintsTypeInfo[10] = &CTI_SIZELIKE; /* Copy Scale Constraint */ constraintsTypeInfo[11] = &CTI_PYTHON; /* Python/Script Constraint */ constraintsTypeInfo[12] = &CTI_ACTION; /* Action Constraint */ constraintsTypeInfo[13] = &CTI_LOCKTRACK; /* Locked-Track Constraint */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 7a2d2929e47..59d8e81de39 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -380,7 +380,7 @@ typedef struct bRotLimitConstraint { short flag2; } bRotLimitConstraint; -/* Limit Scaling Constraint */ +/* Limit Scale Constraint */ typedef struct bSizeLimitConstraint { float xmin, xmax; float ymin, ymax; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index e1f1ab97726..8e29e5c2e79 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -44,6 +44,7 @@ #include "ED_object.h" #include "WM_types.h" +/* please keep the names in sync with constraint.c */ EnumPropertyItem constraint_type_items[] = { {0, "", 0, N_("Motion Tracking"), ""}, {CONSTRAINT_TYPE_CAMERASOLVER, "CAMERA_SOLVER", ICON_CONSTRAINT_DATA, "Camera Solver", ""}, -- cgit v1.2.3 From 2f5612ba33d98ce45fcd76cd17975d7eeb0915b2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 21:48:04 +0000 Subject: code cleanup: name mask and grease pencil dope sheet editor functions more consistantly --- .../blender/editors/gpencil/editaction_gpencil.c | 40 +++++++++++----------- source/blender/editors/include/ED_gpencil.h | 22 ++++++------ source/blender/editors/include/ED_mask.h | 32 +++++++++-------- source/blender/editors/mask/mask_editaction.c | 20 +++++------ source/blender/editors/space_action/action_edit.c | 8 ++--- .../blender/editors/space_action/action_select.c | 34 +++++++++--------- 6 files changed, 80 insertions(+), 76 deletions(-) diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 9cc738b016e..262ae13ece3 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -62,7 +62,7 @@ /* Generics - Loopers */ /* Loops over the gp-frames for a gp-layer, and applies the given callback */ -short gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *)) +short ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *)) { bGPDframe *gpf; @@ -85,7 +85,7 @@ short gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDfr /* Data Conversion Tools */ /* make a listing all the gp-frames in a layer as cfraelems */ -void gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, short onlysel) +void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, short onlysel) { bGPDframe *gpf; CfraElem *ce; @@ -111,7 +111,7 @@ void gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, short onlysel) /* Selection Tools */ /* check if one of the frames in this layer is selected */ -short is_gplayer_frame_selected(bGPDlayer *gpl) +short ED_gplayer_frame_select_check(bGPDlayer *gpl) { bGPDframe *gpf; @@ -149,7 +149,7 @@ static void gpframe_select(bGPDframe *gpf, short select_mode) } /* set all/none/invert select (like above, but with SELECT_* modes) */ -void select_gpencil_frames(bGPDlayer *gpl, short select_mode) +void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode) { bGPDframe *gpf; @@ -164,18 +164,18 @@ void select_gpencil_frames(bGPDlayer *gpl, short select_mode) } /* set all/none/invert select */ -void set_gplayer_frame_selection(bGPDlayer *gpl, short mode) +void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode) { /* error checking */ if (gpl == NULL) return; /* now call the standard function */ - select_gpencil_frames(gpl, mode); + ED_gpencil_select_frames(gpl, mode); } /* select the frame in this layer that occurs on this frame (there should only be one at most) */ -void select_gpencil_frame(bGPDlayer *gpl, int selx, short select_mode) +void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode) { bGPDframe *gpf; @@ -193,7 +193,7 @@ void select_gpencil_frame(bGPDlayer *gpl, int selx, short select_mode) } /* select the frames in this layer that occur within the bounds specified */ -void borderselect_gplayer_frames(bGPDlayer *gpl, float min, float max, short select_mode) +void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short select_mode) { bGPDframe *gpf; @@ -211,7 +211,7 @@ void borderselect_gplayer_frames(bGPDlayer *gpl, float min, float max, short sel /* Frame Editing Tools */ /* Delete selected frames */ -void delete_gplayer_frames(bGPDlayer *gpl) +void ED_gplayer_frames_delete(bGPDlayer *gpl) { bGPDframe *gpf, *gpfn; @@ -229,7 +229,7 @@ void delete_gplayer_frames(bGPDlayer *gpl) } /* Duplicate selected frames from given gp-layer */ -void duplicate_gplayer_frames(bGPDlayer *gpl) +void ED_gplayer_frames_duplicate(bGPDlayer *gpl) { bGPDframe *gpf, *gpfn; @@ -502,19 +502,19 @@ void snap_gplayer_frames(bGPDlayer *gpl, Scene *scene, short mode) { switch (mode) { case 1: /* snap to nearest frame */ - gplayer_frames_looper(gpl, scene, snap_gpf_nearest); + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); break; case 2: /* snap to current frame */ - gplayer_frames_looper(gpl, scene, snap_gpf_cframe); + ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe); break; case 3: /* snap to nearest marker */ - gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); break; case 4: /* snap to nearest second */ - gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); break; default: /* just in case */ - gplayer_frames_looper(gpl, scene, snap_gpf_nearest); + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); break; } } @@ -604,21 +604,21 @@ void mirror_gplayer_frames(bGPDlayer *gpl, Scene *scene, short mode) { switch (mode) { case 1: /* mirror over current frame */ - gplayer_frames_looper(gpl, scene, mirror_gpf_cframe); + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe); break; case 2: /* mirror over frame 0 */ - gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); break; case 3: /* mirror over value 0 */ - gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis); + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis); break; case 4: /* mirror over marker */ mirror_gpf_marker(NULL, NULL); - gplayer_frames_looper(gpl, scene, mirror_gpf_marker); + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker); mirror_gpf_marker(NULL, NULL); break; default: /* just in case */ - gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); break; } } diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 80f7fb9d1ed..32eb63a26d5 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -83,25 +83,27 @@ void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion void gpencil_panel_standard(const struct bContext *C, struct Panel *pa); /* ----------- Grease-Pencil AnimEdit API ------------------ */ -short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, - short (*gpf_cb)(struct bGPDframe *, struct Scene *)); -void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel); +short ED_gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, + short (*gpf_cb)(struct bGPDframe *, struct Scene *)); +void ED_gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel); -short is_gplayer_frame_selected(struct bGPDlayer *gpl); -void set_gplayer_frame_selection(struct bGPDlayer *gpl, short mode); -void select_gpencil_frames(struct bGPDlayer *gpl, short select_mode); -void select_gpencil_frame(struct bGPDlayer *gpl, int selx, short select_mode); -void borderselect_gplayer_frames(struct bGPDlayer *gpl, float min, float max, short select_mode); +short ED_gplayer_frame_select_check(struct bGPDlayer *gpl); +void ED_gplayer_frame_select_set(struct bGPDlayer *gpl, short mode); +void ED_gplayer_frames_select_border(struct bGPDlayer *gpl, float min, float max, short select_mode); +void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode); +void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode); -void delete_gplayer_frames(struct bGPDlayer *gpl); -void duplicate_gplayer_frames(struct bGPDlayer *gpl); +void ED_gplayer_frames_delete(struct bGPDlayer *gpl); +void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl); +#if 0 void free_gpcopybuf(void); void copy_gpdata(void); void paste_gpdata(void); void snap_gplayer_frames(struct bGPDlayer *gpl, short mode); void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode); +#endif /* ------------ Grease-Pencil Undo System ------------------ */ int ED_gpencil_session_active(void); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index bbfc47c582a..773da04bc7b 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -49,24 +49,26 @@ int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame); int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame); /* ----------- Mask AnimEdit API ------------------ */ -short masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene, - short (*masklay_shape_cb)(struct MaskLayerShape *, struct Scene *)); -void masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, short onlysel); +short ED_masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene, + short (*masklay_shape_cb)(struct MaskLayerShape *, struct Scene *)); +void ED_masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, short onlysel); -short is_masklayer_frame_selected(struct MaskLayer *masklay); -void set_masklayer_frame_selection(struct MaskLayer *masklay, short mode); -void select_mask_frames(struct MaskLayer *masklay, short select_mode); -void select_mask_frame(struct MaskLayer *masklay, int selx, short select_mode); -void borderselect_masklayer_frames(struct MaskLayer *masklay, float min, float max, short select_mode); +short ED_masklayer_frame_select_check(struct MaskLayer *masklay); +void ED_masklayer_frame_select_set(struct MaskLayer *masklay, short mode); +void ED_masklayer_frames_select_border(struct MaskLayer *masklay, float min, float max, short select_mode); +void ED_mask_select_frames(struct MaskLayer *masklay, short select_mode); +void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mode); -void delete_masklayer_frames(struct MaskLayer *masklay); -void duplicate_masklayer_frames(struct MaskLayer *masklay); +void ED_masklayer_frames_delete(struct MaskLayer *masklay); +void ED_masklayer_frames_duplicate(struct MaskLayer *masklay); -//void free_gpcopybuf(void); -//void copy_gpdata(void); -//void paste_gpdata(void); +#if 0 +void free_gpcopybuf(void); +void copy_gpdata(void); +void paste_gpdata(void); -void snap_masklayer_frames(struct MaskLayer *masklay, short mode); -void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); + void snap_masklayer_frames(struct MaskLayer *masklay, short mode); + void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); +#endif #endif /* __ED_MASK_H__ */ diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index c773e13e2eb..a629883a446 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -59,7 +59,7 @@ /* Generics - Loopers */ /* Loops over the gp-frames for a gp-layer, and applies the given callback */ -short masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *)) +short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *)) { MaskLayerShape *masklay_shape; @@ -82,7 +82,7 @@ short masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_ /* Data Conversion Tools */ /* make a listing all the gp-frames in a layer as cfraelems */ -void masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel) +void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel) { MaskLayerShape *masklay_shape; CfraElem *ce; @@ -108,7 +108,7 @@ void masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel /* Selection Tools */ /* check if one of the frames in this layer is selected */ -short is_masklayer_frame_selected(MaskLayer *masklay) +short ED_masklayer_frame_select_check(MaskLayer *masklay) { MaskLayerShape *masklay_shape; @@ -146,7 +146,7 @@ static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode } /* set all/none/invert select (like above, but with SELECT_* modes) */ -void select_mask_frames(MaskLayer *masklay, short select_mode) +void ED_mask_select_frames(MaskLayer *masklay, short select_mode) { MaskLayerShape *masklay_shape; @@ -161,18 +161,18 @@ void select_mask_frames(MaskLayer *masklay, short select_mode) } /* set all/none/invert select */ -void set_masklayer_frame_selection(MaskLayer *masklay, short mode) +void ED_masklayer_frame_select_set(MaskLayer *masklay, short mode) { /* error checking */ if (masklay == NULL) return; /* now call the standard function */ - select_mask_frames(masklay, mode); + ED_mask_select_frames(masklay, mode); } /* select the frame in this layer that occurs on this frame (there should only be one at most) */ -void select_mask_frame(MaskLayer *masklay, int selx, short select_mode) +void ED_mask_select_frame(MaskLayer *masklay, int selx, short select_mode) { MaskLayerShape *masklay_shape; @@ -190,7 +190,7 @@ void select_mask_frame(MaskLayer *masklay, int selx, short select_mode) } /* select the frames in this layer that occur within the bounds specified */ -void borderselect_masklayer_frames(MaskLayer *masklay, float min, float max, short select_mode) +void ED_masklayer_frames_select_border(MaskLayer *masklay, float min, float max, short select_mode) { MaskLayerShape *masklay_shape; @@ -208,7 +208,7 @@ void borderselect_masklayer_frames(MaskLayer *masklay, float min, float max, sho /* Frame Editing Tools */ /* Delete selected frames */ -void delete_masklayer_frames(MaskLayer *masklay) +void ED_masklayer_frames_delete(MaskLayer *masklay) { MaskLayerShape *masklay_shape, *masklay_shape_next; @@ -226,7 +226,7 @@ void delete_masklayer_frames(MaskLayer *masklay) } /* Duplicate selected frames from given gp-layer */ -void duplicate_masklayer_frames(MaskLayer *masklay) +void ED_masklayer_frames_duplicate(MaskLayer *masklay) { MaskLayerShape *masklay_shape, *gpfn; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 8b26461cc4f..b5cd49cc15c 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -702,9 +702,9 @@ static void duplicate_action_keys(bAnimContext *ac) if (ale->type == ANIMTYPE_FCURVE) duplicate_fcurve_keys((FCurve *)ale->key_data); else if (ale->type == ANIMTYPE_GPLAYER) - duplicate_gplayer_frames((bGPDlayer *)ale->data); + ED_gplayer_frames_duplicate((bGPDlayer *)ale->data); else if (ale->type == ANIMTYPE_MASKLAYER) - duplicate_masklayer_frames((MaskLayer *)ale->data); + ED_masklayer_frames_duplicate((MaskLayer *)ale->data); else BLI_assert(0); } @@ -777,10 +777,10 @@ static void delete_action_keys(bAnimContext *ac) /* loop through filtered data and delete selected keys */ for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { - delete_gplayer_frames((bGPDlayer *)ale->data); + ED_gplayer_frames_delete((bGPDlayer *)ale->data); } else if (ale->type == ANIMTYPE_MASKLAYER) { - delete_masklayer_frames((MaskLayer *)ale->data); + ED_masklayer_frames_delete((MaskLayer *)ale->data); } else { FCurve *fcu = (FCurve *)ale->key_data; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index bd73e35815b..539a32161e5 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -109,13 +109,13 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) if (test) { for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { - if (is_gplayer_frame_selected(ale->data)) { + if (ED_gplayer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } } else if (ale->type == ANIMTYPE_MASKLAYER) { - if (is_masklayer_frame_selected(ale->data)) { + if (ED_masklayer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } @@ -135,9 +135,9 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel) /* Now set the flags */ for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) - set_gplayer_frame_selection(ale->data, sel); + ED_gplayer_frame_select_set(ale->data, sel); else if (ale->type == ANIMTYPE_MASKLAYER) - set_masklayer_frame_selection(ale->data, sel); + ED_masklayer_frame_select_set(ale->data, sel); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); } @@ -259,9 +259,9 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s { /* loop over data selecting */ if (ale->type == ANIMTYPE_GPLAYER) - borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); + ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); else if (ale->type == ANIMTYPE_MASKLAYER) - borderselect_masklayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); + ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); else ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); } @@ -410,10 +410,10 @@ static void markers_selectkeys_between(bAnimContext *ac) ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else if (ale->type == ANIMTYPE_GPLAYER) { - borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD); + ED_gplayer_frames_select_border(ale->data, min, max, SELECT_ADD); } else if (ale->type == ANIMTYPE_MASKLAYER) { - borderselect_masklayer_frames(ale->data, min, max, SELECT_ADD); + ED_masklayer_frames_select_border(ale->data, min, max, SELECT_ADD); } else { ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); @@ -447,7 +447,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) - gplayer_make_cfra_list(ale->data, &ked.list, 1); + ED_gplayer_make_cfra_list(ale->data, &ked.list, 1); } else { filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/); @@ -503,9 +503,9 @@ static void columnselect_action_keys(bAnimContext *ac, short mode) /* select elements with frame number matching cfraelem */ if (ale->type == ANIMTYPE_GPLAYER) - select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD); + ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD); else if (ale->type == ANIMTYPE_MASKLAYER) - select_mask_frame(ale->data, ce->cfra, SELECT_ADD); + ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -788,9 +788,9 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else if (ale->type == ANIMTYPE_GPLAYER) - borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode); + ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) - borderselect_masklayer_frames(ale->data, ked.f1, ked.f2, select_mode); + ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -927,9 +927,9 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s /* select the nominated keyframe on the given frame */ if (ale->type == ANIMTYPE_GPLAYER) - select_gpencil_frame(ale->data, selx, select_mode); + ED_gpencil_select_frame(ale->data, selx, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) - select_mask_frame(ale->data, selx, select_mode); + ED_mask_select_frame(ale->data, selx, select_mode); else ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); } @@ -971,9 +971,9 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se /* select elements with frame number matching cfra */ if (ale->type == ANIMTYPE_GPLAYER) - select_gpencil_frame(ale->key_data, selx, select_mode); + ED_gpencil_select_frame(ale->key_data, selx, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) - select_mask_frame(ale->key_data, selx, select_mode); + ED_mask_select_frame(ale->key_data, selx, select_mode); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } -- cgit v1.2.3 From a8e0011c96c6bbf60e79911f870b25384e06f60d Mon Sep 17 00:00:00 2001 From: Dan Eicher Date: Fri, 8 Jun 2012 22:05:26 +0000 Subject: rna_SequenceElements_pop --> use memcpy instead of strcpy --- source/blender/makesrna/intern/rna_sequencer_api.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index e20435a07cd..3a534cd22b4 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -339,7 +339,6 @@ static StripElem *rna_SequenceElements_push(ID *id, Sequence *seq, const char *f static void rna_SequenceElements_pop(ID *id, Sequence *seq, ReportList *reports, int index) { - int i; Scene *scene = (Scene *)id; StripElem *new_seq, *se; @@ -361,12 +360,12 @@ static void rna_SequenceElements_pop(ID *id, Sequence *seq, ReportList *reports, new_seq = MEM_callocN(sizeof(StripElem) * (seq->len - 1), "SequenceElements_pop"); seq->len--; - /* TODO - simply use 2 memcpy calls */ - for (i = 0, se = seq->strip->stripdata; i < seq->len; i++, se++) { - if (i == index) - se++; - BLI_strncpy(new_seq[i].name, se->name, sizeof(se->name)); - } + se = seq->strip->stripdata; + if (index > 0) + memcpy(new_seq, se, sizeof(StripElem) * index); + + if (index < seq->len) + memcpy(&new_seq[index], &se[index + 1], sizeof(StripElem) * (seq->len - index)); MEM_freeN(seq->strip->stripdata); seq->strip->stripdata = new_seq; -- cgit v1.2.3 From c96c63ad3afe66e04d7a2f7c351abbc53242f03a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 22:07:57 +0000 Subject: add a utility function to get an exact match for a grease pencil frame. --- source/blender/blenkernel/BKE_gpencil.h | 1 + source/blender/blenkernel/intern/gpencil.c | 13 +++++++++++++ source/blender/editors/gpencil/editaction_gpencil.c | 13 +++++-------- source/blender/editors/mask/mask_editaction.c | 11 ++++------- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 134ec1acd8e..f3223fb4af1 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -57,6 +57,7 @@ struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd); void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf); +struct bGPDframe *BKE_gpencil_layer_find_frame(struct bGPDlayer *gpl, int cframe); struct bGPDframe *gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, short addnew); void gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf); struct bGPDlayer *gpencil_layer_getactive(struct bGPdata *gpd); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 6ec19018ab5..c317dc63ef7 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -321,6 +321,19 @@ void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf) /* -------- GP-Layer API ---------- */ +bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe) +{ + bGPDframe *gpf; + + for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) { + if (gpf->framenum == cframe) { + return gpf; + } + } + + return NULL; +} + /* get the appropriate gp-frame from a given layer * - this sets the layer's actframe var (if allowed to) * - extension beyond range (if first gp-frame is after all frame in interest and cannot add) diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 262ae13ece3..a7beaa74eb7 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -181,14 +181,11 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode) if (gpl == NULL) return; - - /* search through frames for a match */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - /* there should only be one frame with this frame-number */ - if (gpf->framenum == selx) { - gpframe_select(gpf, select_mode); - break; - } + + gpf = BKE_gpencil_layer_find_frame(gpl, selx); + + if (gpf) { + gpframe_select(gpf, select_mode); } } diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index a629883a446..3836b393bf8 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -179,13 +179,10 @@ void ED_mask_select_frame(MaskLayer *masklay, int selx, short select_mode) if (masklay == NULL) return; - /* search through frames for a match */ - for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { - /* there should only be one frame with this frame-number */ - if (masklay_shape->frame == selx) { - masklayshape_select(masklay_shape, select_mode); - break; - } + masklay_shape = BKE_mask_layer_shape_find_frame(masklay, selx); + + if (masklay_shape) { + masklayshape_select(masklay_shape, select_mode); } } -- cgit v1.2.3 From 56c5c63f57a6e4e5f88a3ca6ad141684ecd3ac09 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 8 Jun 2012 23:43:11 +0000 Subject: code cleanup: doxy comment filename corrections --- source/blender/blenlib/BLI_string_cursor_utf8.h | 2 +- source/blender/bmesh/operators/bmo_mesh_conv.c | 2 +- source/blender/bmesh/operators/bmo_triangulate.c | 2 +- source/blender/bmesh/operators/bmo_utils.c | 2 +- source/blender/editors/mask/mask_edit.c | 2 +- source/blender/editors/mask/mask_relationships.c | 2 +- source/blender/editors/space_clip/clip_dopesheet_draw.c | 2 +- source/blender/editors/space_clip/clip_dopesheet_ops.c | 2 +- source/blender/nodes/composite/nodes/node_composite_bokehblur.c | 2 +- source/blender/nodes/composite/nodes/node_composite_bokehimage.c | 2 +- source/blender/nodes/composite/nodes/node_composite_boxmask.c | 2 +- source/blender/nodes/composite/nodes/node_composite_ellipsemask.c | 2 +- source/blender/nodes/composite/nodes/node_composite_switch.c | 2 +- source/blender/python/bmesh/bmesh_py_utils.c | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/source/blender/blenlib/BLI_string_cursor_utf8.h b/source/blender/blenlib/BLI_string_cursor_utf8.h index 11c91aac6ac..3c38c0380e0 100644 --- a/source/blender/blenlib/BLI_string_cursor_utf8.h +++ b/source/blender/blenlib/BLI_string_cursor_utf8.h @@ -26,7 +26,7 @@ #ifndef __BLI_STRING_CURSOR_UTF8_H__ #define __BLI_STRING_CURSOR_UTF8_H__ -/** \file BLI_string_utf8.h +/** \file BLI_string_cursor_utf8.h * \ingroup bli */ diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index 4578270d571..c550a17e696 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/operators/bmesh_mesh_conv.c +/** \file blender/bmesh/operators/bmo_mesh_conv.c * \ingroup bmesh * * This file contains functions diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index e53144bd597..0903620f9a0 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/operators/bmo_subdivide.c +/** \file blender/bmesh/operators/bmo_triangulate.c * \ingroup bmesh */ diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index 4377eb3e883..3ebc7b04aa4 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/operators/bmo_subdivide.c +/** \file blender/bmesh/operators/bmo_utils.c * \ingroup bmesh * * utility bmesh operators, e.g. transform, diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 6a59279934e..24f55f66bb8 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/mask/mask_ops.c +/** \file blender/editors/mask/mask_edit.c * \ingroup edmask */ diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 7c0a598ba9f..77fe2a71225 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/mask/mask_relationshops.c +/** \file blender/editors/mask/mask_relationships.c * \ingroup edmask */ diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index e264d7f3885..63148c2b69d 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/space_clip/clip_graph_draw.c +/** \file blender/editors/space_clip/clip_dopesheet_draw.c * \ingroup spclip */ diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index 7c08f1e2668..914e82472bb 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/space_clip/clip_graph_ops.c +/** \file blender/editors/space_clip/clip_dopesheet_ops.c * \ingroup spclip */ diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c index 06b6e79444a..6b24bdb5c52 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c @@ -28,7 +28,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/nodes/intern/CMP_nodes/CMP_blur.c +/** \file blender/nodes/composite/nodes/node_composite_bokehblur.c * \ingroup cmpnodes */ diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c index b46e7e646de..24378c4d5b7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c +++ b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c @@ -28,7 +28,7 @@ */ -/** \file blender/nodes/intern/CMP_nodes/CMP_gamma.c +/** \file blender/nodes/composite/nodes/node_composite_bokehimage.c * \ingroup cmpnodes */ diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c index 4bd6ab4698b..81c13980f22 100644 --- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c +++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c @@ -27,7 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/nodes/intern/CMP_nodes/CMP_math.c +/** \file blender/nodes/composite/nodes/node_composite_boxmask.c * \ingroup cmpnodes */ diff --git a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c index 7a1e82ddd9b..18a86680245 100644 --- a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c +++ b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c @@ -27,7 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/nodes/intern/CMP_nodes/CMP_math.c +/** \file blender/nodes/composite/nodes/node_composite_ellipsemask.c * \ingroup cmpnodes */ diff --git a/source/blender/nodes/composite/nodes/node_composite_switch.c b/source/blender/nodes/composite/nodes/node_composite_switch.c index 8c2c2746593..258fac18c11 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switch.c +++ b/source/blender/nodes/composite/nodes/node_composite_switch.c @@ -27,7 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/nodes/intern/CMP_nodes/CMP_switch.c +/** \file blender/nodes/composite/nodes/node_composite_switch.c * \ingroup cmpnodes */ diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 9fecc0cdeda..374a01c51f8 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -23,7 +23,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/python/bmesh/bmesh_py_api.c +/** \file blender/python/bmesh/bmesh_py_utils.c * \ingroup pybmesh * * This file defines the 'bmesh.utils' module. -- cgit v1.2.3 From 2f60d9b0b9af1df967e29fd1822d82ffd2450d0f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 Jun 2012 16:45:42 +0000 Subject: fix for un-handled exception when entering in multiple values to a button, floats were not correctly checked for. --- source/blender/python/intern/bpy_interface.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 73188b3f830..ac9ff4c8ef5 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -537,7 +537,12 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const short ve val = 0.0; for (i = 0; i < PyTuple_GET_SIZE(retval); i++) { - val += PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i)); + const double val_item = PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i)); + if (val_item == -1 && PyErr_Occurred()) { + val = -1; + break; + } + val += val_item; } } else { -- cgit v1.2.3 From 0fbb6bff27139d66951fe223ff322c609d368a18 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 Jun 2012 17:22:52 +0000 Subject: style cleanup: block comments --- intern/cycles/blender/blender_camera.cpp | 6 +- intern/cycles/blender/blender_mesh.cpp | 12 +-- intern/cycles/blender/blender_object.cpp | 2 +- intern/cycles/blender/blender_session.cpp | 6 +- intern/cycles/blender/blender_shader.cpp | 2 +- intern/cycles/blender/blender_sync.cpp | 2 +- intern/cycles/blender/blender_util.h | 10 ++- intern/cycles/bvh/bvh.cpp | 10 +-- intern/cycles/bvh/bvh.h | 6 +- intern/cycles/bvh/bvh_binning.cpp | 2 +- intern/cycles/bvh/bvh_sort.h | 2 +- intern/cycles/device/device.cpp | 2 +- intern/cycles/device/device_cpu.cpp | 2 +- intern/cycles/device/device_cuda.cpp | 2 +- intern/cycles/device/device_network.h | 6 +- intern/cycles/device/device_opencl.cpp | 6 +- intern/cycles/kernel/kernel_accumulate.h | 4 +- intern/cycles/kernel/kernel_bvh.h | 6 +- intern/cycles/kernel/kernel_compat_cpu.h | 12 +-- intern/cycles/kernel/kernel_emission.h | 6 +- intern/cycles/kernel/kernel_globals.h | 14 ++-- intern/cycles/kernel/kernel_light.h | 10 +-- intern/cycles/kernel/kernel_montecarlo.h | 2 +- intern/cycles/kernel/kernel_optimized.cpp | 4 +- intern/cycles/kernel/kernel_path.h | 22 +++--- intern/cycles/kernel/kernel_projection.h | 2 +- intern/cycles/kernel/kernel_random.h | 6 +- intern/cycles/kernel/kernel_triangle.h | 4 +- intern/cycles/kernel/osl/nodes/node_fresnel.h | 2 +- intern/cycles/kernel/osl/osl_services.cpp | 18 ++--- intern/cycles/kernel/osl/osl_services.h | 8 +- intern/cycles/kernel/svm/bsdf.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h | 2 +- intern/cycles/kernel/svm/bsdf_diffuse.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_microfacet.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_reflection.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_refraction.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_transparent.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_ward.h | 62 +++++++-------- intern/cycles/kernel/svm/bsdf_westin.h | 62 +++++++-------- intern/cycles/kernel/svm/emissive.h | 62 +++++++-------- intern/cycles/kernel/svm/svm_closure.h | 10 +-- intern/cycles/kernel/svm/svm_image.h | 14 ++-- intern/cycles/kernel/svm/svm_noise.h | 2 +- intern/cycles/kernel/svm/svm_texture.h | 2 +- intern/cycles/kernel/svm/volume.h | 2 +- intern/cycles/render/buffers.h | 6 +- intern/cycles/render/film.cpp | 2 +- intern/cycles/render/graph.cpp | 12 +-- intern/cycles/render/image.cpp | 12 +-- intern/cycles/render/light.cpp | 2 +- intern/cycles/render/mesh.cpp | 6 +- intern/cycles/render/object.cpp | 8 +- intern/cycles/render/osl.cpp | 2 +- intern/cycles/render/session.cpp | 28 +++---- intern/cycles/render/shader.cpp | 8 +- intern/cycles/render/shader.h | 6 +- intern/cycles/render/svm.cpp | 22 +++--- intern/cycles/subd/subd_build.cpp | 15 ++-- intern/cycles/subd/subd_dice.cpp | 10 +-- intern/cycles/subd/subd_ring.cpp | 8 +- intern/cycles/util/util_cuda.cpp | 4 +- intern/cycles/util/util_md5.cpp | 26 +++---- intern/cycles/util/util_opencl.h | 98 ++++++++++++------------ intern/cycles/util/util_path.cpp | 4 +- intern/cycles/util/util_system.cpp | 12 ++- intern/cycles/util/util_task.cpp | 2 +- intern/cycles/util/util_thread.h | 2 +- intern/cycles/util/util_transform.cpp | 2 +- intern/cycles/util/util_transform.h | 2 +- 70 files changed, 551 insertions(+), 536 deletions(-) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 9bc82344fcc..3bc1fa34a98 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -141,7 +141,7 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob) bcam->lens = b_camera.lens(); /* allow f/stop number to change aperture_size but still - give manual control over aperture radius */ + * give manual control over aperture radius */ int aperture_type = RNA_enum_get(&ccamera, "aperture_type"); if(aperture_type == 1) { @@ -179,8 +179,8 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type) if(type == CAMERA_PANORAMA) { /* make it so environment camera needs to be pointed in the direction - of the positive x-axis to match an environment texture, this way - it is looking at the center of the texture */ + * of the positive x-axis to match an environment texture, this way + * it is looking at the center of the texture */ result = tfm * make_transform( 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index ad91022de07..f9d26c40a74 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -68,8 +68,8 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } /* create generated coordinates. todo: we should actually get the orco - coordinates from modifiers, for now we use texspace loc/size which - is available in the api. */ + * coordinates from modifiers, for now we use texspace loc/size which + * is available in the api. */ if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); float3 loc = get_float3(b_mesh.texspace_location()); @@ -181,8 +181,10 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con if(n == 4) sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]); - /*else - sdmesh.add_face(vi[0], vi[1], vi[2]);*/ +#if 0 + else + sdmesh.add_face(vi[0], vi[1], vi[2]); +#endif } /* finalize subd mesh */ @@ -232,7 +234,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated) /* if transform was applied to mesh, need full update */ if(object_updated && mesh->transform_applied); /* test if shaders changed, these can be object level so mesh - does not get tagged for recalc */ + * does not get tagged for recalc */ else if(mesh->used_shaders != used_shaders); else { /* even if not tagged for recalc, we may need to sync anyway diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index b70491a7b82..c4b58d6fa76 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -264,7 +264,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, } /* camera flag is not actually used, instead is tested - against render layer flags */ + * against render layer flags */ if(object->visibility & PATH_RAY_CAMERA) { object->visibility |= layer_flag << PATH_RAY_LAYER_SHIFT; object->visibility &= ~PATH_RAY_CAMERA; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 9726f7b94cf..aeda40ae40e 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -304,7 +304,7 @@ void BlenderSession::synchronize() session->set_pause(BlenderSync::get_session_pause(b_scene, background)); /* copy recalc flags, outside of mutex so we can decide to do the real - synchronization at a later time to not block on running updates */ + * synchronization at a later time to not block on running updates */ sync->sync_recalc(); /* try to acquire mutex. if we don't want to or can't, come back later */ @@ -334,7 +334,7 @@ void BlenderSession::synchronize() bool BlenderSession::draw(int w, int h) { /* before drawing, we verify camera and viewport size changes, because - we do not get update callbacks for those, we must detect them here */ + * we do not get update callbacks for those, we must detect them here */ if(session->ready_to_reset()) { bool reset = false; @@ -429,7 +429,7 @@ void BlenderSession::tag_redraw() { if(background) { /* update stats and progress, only for background here because - in 3d view we do it in draw for thread safety reasons */ + * in 3d view we do it in draw for thread safety reasons */ update_status_progress(); /* offline render, redraw if timeout passed */ diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index a7be0a8fb54..f9331fc1b14 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -641,7 +641,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap to_pair = sockets_map[b_to_sock.ptr.data]; /* either node may be NULL when the node was not exported, typically - because the node type is not supported */ + * because the node type is not supported */ if(from_pair.first && to_pair.first) { ShaderOutput *output = from_pair.first->output(from_pair.second.c_str()); ShaderInput *input = to_pair.first->input(to_pair.second.c_str()); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 488fea8d12b..a9714d6d72f 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -63,7 +63,7 @@ BlenderSync::~BlenderSync() bool BlenderSync::sync_recalc() { /* sync recalc flags from blender to cycles. actual update is done separate, - so we can do it later on if doing it immediate is not suitable */ + * so we can do it later on if doing it immediate is not suitable */ BL::BlendData::materials_iterator b_mat; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index b9c60738b36..9b9e0d3a425 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -27,7 +27,7 @@ #include "util_vector.h" /* Hacks to hook into Blender API - todo: clean this up ... */ + * todo: clean this up ... */ extern "C" { @@ -121,7 +121,7 @@ static inline Transform get_transform(BL::Array array) Transform tfm; /* we assume both types to be just 16 floats, and transpose because blender - use column major matrix order while we use row major */ + * use column major matrix order while we use row major */ memcpy(&tfm, &array, sizeof(float)*16); tfm = transform_transpose(tfm); @@ -164,12 +164,14 @@ static inline uint get_layer(BL::Array array) return layer; } -/*static inline float3 get_float3(PointerRNA& ptr, const char *name) +#if 0 +static inline float3 get_float3(PointerRNA& ptr, const char *name) { float3 f; RNA_float_get_array(&ptr, name, &f.x); return f; -}*/ +} +#endif static inline bool get_boolean(PointerRNA& ptr, const char *name) { diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 15695dddf45..a383ad317ab 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -292,13 +292,13 @@ void BVH::pack_triangles() void BVH::pack_instances(size_t nodes_size) { /* The BVH's for instances are built separately, but for traversal all - BVH's are stored in global arrays. This function merges them into the - top level BVH, adjusting indexes and offsets where appropriate. */ + * BVH's are stored in global arrays. This function merges them into the + * top level BVH, adjusting indexes and offsets where appropriate. */ bool use_qbvh = params.use_qbvh; size_t nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE; /* adjust primitive index to point to the triangle in the global array, for - meshes with transform applied and already in the top level BVH */ + * meshes with transform applied and already in the top level BVH */ for(size_t i = 0; i < pack.prim_index.size(); i++) if(pack.prim_index[i] != -1) pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset; @@ -356,14 +356,14 @@ void BVH::pack_instances(size_t nodes_size) Mesh *mesh = ob->mesh; /* if mesh transform is applied, that means it's already in the top - level BVH, and we don't need to merge it in */ + * level BVH, and we don't need to merge it in */ if(mesh->transform_applied) { pack.object_node[object_offset++] = 0; continue; } /* if mesh already added once, don't add it again, but used set - node offset for this object */ + * node offset for this object */ map::iterator it = mesh_map.find(mesh); if(mesh_map.find(mesh) != mesh_map.end()) { diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 30ae7dac106..549f1e3ac1d 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -46,7 +46,7 @@ class Progress; struct PackedBVH { /* BVH nodes storage, one node is 4x int4, and contains two bounding boxes, - and child, triangle or object indexes dependening on the node type */ + * and child, triangle or object indexes dependening on the node type */ array nodes; /* object index to BVH node index mapping for instances */ array object_node; @@ -55,12 +55,12 @@ struct PackedBVH { /* visibility visibilitys for primitives */ array prim_visibility; /* mapping from BVH primitive index to true primitive index, as primitives - may be duplicated due to spatial splits. -1 for instances. */ + * may be duplicated due to spatial splits. -1 for instances. */ array prim_index; /* mapping from BVH primitive index, to the object id of that primitive. */ array prim_object; /* quick array to lookup if a node is a leaf, not used for traversal, only - for instance BVH merging */ + * for instance BVH merging */ array is_leaf; /* index of the root node. */ diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp index e4b88584a33..05a674a47a7 100644 --- a/intern/cycles/bvh/bvh_binning.cpp +++ b/intern/cycles/bvh/bvh_binning.cpp @@ -200,7 +200,7 @@ void BVHObjectBinning::split(BVHReference* prims, BVHObjectBinning& left_o, BVHO } /* object medium split if we did not make progress, can happen when all - primitives have same centroid */ + * primitives have same centroid */ lgeom_bounds = BoundBox::empty; rgeom_bounds = BoundBox::empty; lcent_bounds = BoundBox::empty; diff --git a/intern/cycles/bvh/bvh_sort.h b/intern/cycles/bvh/bvh_sort.h index ba35ba3fae7..18aafb5f1ff 100644 --- a/intern/cycles/bvh/bvh_sort.h +++ b/intern/cycles/bvh/bvh_sort.h @@ -1,4 +1,4 @@ - /* +/* * Adapted from code copyright 2009-2010 NVIDIA Corporation * Modifications Copyright 2011, Blender Foundation. * diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 42dda1180c7..33040f287d1 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -124,7 +124,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w uint8_t *pixels = (uint8_t*)rgba.data_pointer; /* for multi devices, this assumes the ineffecient method that we allocate - all pixels on the device even though we only render to a subset */ + * all pixels on the device even though we only render to a subset */ pixels += 4*y*w; glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 5f422332cd2..070b20aec49 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -226,7 +226,7 @@ public: void task_add(DeviceTask& task) { /* split task into smaller ones, more than number of threads for uneven - workloads where some parts of the image render slower than others */ + * workloads where some parts of the image render slower than others */ list tasks; task.split(tasks, TaskScheduler::num_threads()*10); diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 491a63a7cf2..357f99145b2 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -771,7 +771,7 @@ public: cuda_push_context(); /* for multi devices, this assumes the ineffecient method that we allocate - all pixels on the device even though we only render to a subset */ + * all pixels on the device even though we only render to a subset */ size_t offset = sizeof(uint8_t)*4*y*w; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pmem.cuPBO); diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h index 591216a77b9..e3afe46d2b0 100644 --- a/intern/cycles/device/device_network.h +++ b/intern/cycles/device/device_network.h @@ -126,8 +126,10 @@ typedef struct RPCReceive { if(len == data_size) { archive_str = (data.size())? string(&data[0], data.size()): string(""); - /*istringstream archive_stream(archive_str); - boost::archive::text_iarchive archive(archive_stream);*/ +#if 0 + istringstream archive_stream(archive_str); + boost::archive::text_iarchive archive(archive_stream); +#endif archive_stream = new istringstream(archive_str); archive = new boost::archive::text_iarchive(*archive_stream); diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index bb2b852d4e1..c979065d23a 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -239,7 +239,7 @@ public: } /* we don't check CL_DEVICE_VERSION since for e.g. nvidia sm 1.3 cards this is - 1.0 even if the language features are there, just limited shared memory */ + * 1.0 even if the language features are there, just limited shared memory */ return true; } @@ -344,8 +344,8 @@ public: bool compile_kernel(const string& kernel_path, const string& kernel_md5) { /* we compile kernels consisting of many files. unfortunately opencl - kernel caches do not seem to recognize changes in included files. - so we force recompile on changes by adding the md5 hash of all files */ + * kernel caches do not seem to recognize changes in included files. + * so we force recompile on changes by adding the md5 hash of all files */ string source = "#include \"kernel.cl\" // " + kernel_md5 + "\n"; source = path_source_replace_includes(source, kernel_path); diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 6c3ade1c531..d99beb8905a 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -271,8 +271,8 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) #ifdef __PASSES__ if(L->use_light_pass) { /* this division is a bit ugly, but means we only have to keep track of - only a single throughput further along the path, here we recover just - the indirect parth that is not influenced by any particular BSDF type */ + * only a single throughput further along the path, here we recover just + * the indirect parth that is not influenced by any particular BSDF type */ L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput); L->direct_diffuse += L->indirect_diffuse*L->direct_emission; L->direct_glossy += L->indirect_glossy*L->direct_emission; diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 522f9861c35..34a44af8b8d 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -34,8 +34,8 @@ CCL_NAMESPACE_BEGIN #define TRI_NODE_SIZE 3 /* silly workaround for float extended precision that happens when compiling - without sse support on x86, it results in different results for float ops - that you would otherwise expect to compare correctly */ + * without sse support on x86, it results in different results for float ops + * that you would otherwise expect to compare correctly */ #if !defined(__i386__) || defined(__SSE__) #define NO_EXTENDED_PRECISION #else @@ -160,7 +160,7 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise if(v >= 0.0f && u + v <= 1.0f) { #ifdef __VISIBILITY_FLAG__ /* visibility flag test. we do it here under the assumption - that most triangles are culled by node flags */ + * that most triangles are culled by node flags */ if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility) #endif { diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 2bd0b61b4fa..cc8f1f3323b 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -28,13 +28,13 @@ CCL_NAMESPACE_BEGIN /* Assertions inside the kernel only work for the CPU device, so we wrap it in - a macro which is empty for other devices */ + * a macro which is empty for other devices */ #define kernel_assert(cond) assert(cond) /* Texture types to be compatible with CUDA textures. These are really just - simple arrays and after inlining fetch hopefully revert to being a simple - pointer lookup. */ + * simple arrays and after inlining fetch hopefully revert to being a simple + * pointer lookup. */ template struct texture { T fetch(int index) @@ -43,7 +43,8 @@ template struct texture { return data[index]; } - /*__m128 fetch_m128(int index) +#if 0 + __m128 fetch_m128(int index) { kernel_assert(index >= 0 && index < width); return ((__m128*)data)[index]; @@ -53,7 +54,8 @@ template struct texture { { kernel_assert(index >= 0 && index < width); return ((__m128i*)data)[index]; - }*/ + } +#endif float interp(float x, int size) { diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 881d25ad7ba..f582ace69f0 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -44,7 +44,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, ls->Ng = sd.Ng; /* no path flag, we're evaluating this for all closures. that's weak but - we'd have to do multiple evaluations otherwise */ + * we'd have to do multiple evaluations otherwise */ shader_eval_surface(kg, &sd, rando, 0); /* evaluate emissive closure */ @@ -145,7 +145,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) { /* multiple importance sampling, get triangle light pdf, - and compute weight with respect to BSDF pdf */ + * and compute weight with respect to BSDF pdf */ float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t); float mis_weight = power_heuristic(bsdf_pdf, pdf); @@ -172,7 +172,7 @@ __device float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, if(!(path_flag & PATH_RAY_MIS_SKIP) && res) { /* multiple importance sampling, get background light pdf for ray - direction, and compute weight with respect to BSDF pdf */ + * direction, and compute weight with respect to BSDF pdf */ float pdf = background_light_pdf(kg, ray->D); float mis_weight = power_heuristic(bsdf_pdf, pdf); diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h index 1f2fc97e685..a99fffbc519 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -29,9 +29,9 @@ CCL_NAMESPACE_BEGIN /* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in - the kernel, to access constant data. These are all stored as "textures", but - these are really just standard arrays. We can't use actually globals because - multiple renders may be running inside the same process. */ + * the kernel, to access constant data. These are all stored as "textures", but + * these are really just standard arrays. We can't use actually globals because + * multiple renders may be running inside the same process. */ #ifdef __KERNEL_CPU__ @@ -45,7 +45,7 @@ typedef struct KernelGlobals { #ifdef __OSL__ /* On the CPU, we also have the OSL globals here. Most data structures are shared - with SVM, the difference is in the shaders and object/mesh attributes. */ + * with SVM, the difference is in the shaders and object/mesh attributes. */ OSLGlobals osl; #endif @@ -54,9 +54,9 @@ typedef struct KernelGlobals { #endif /* For CUDA, constant memory textures must be globals, so we can't put them - into a struct. As a result we don't actually use this struct and use actual - globals and simply pass along a NULL pointer everywhere, which we hope gets - optimized out. */ + * into a struct. As a result we don't actually use this struct and use actual + * globals and simply pass along a NULL pointer everywhere, which we hope gets + * optimized out. */ #ifdef __KERNEL_CUDA__ diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 2bc5a882ce5..edc302cd6e3 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -64,8 +64,8 @@ __device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float __device float3 background_light_sample(KernelGlobals *kg, float randu, float randv, float *pdf) { /* for the following, the CDF values are actually a pair of floats, with the - function value as X and the actual CDF as Y. The last entry's function - value is the CDF total. */ + * function value as X and the actual CDF as Y. The last entry's function + * value is the CDF total. */ int res = kernel_data.integrator.pdf_background_res; int cdf_count = res + 1; @@ -326,9 +326,9 @@ __device float triangle_light_pdf(KernelGlobals *kg, __device int light_distribution_sample(KernelGlobals *kg, float randt) { /* this is basically std::upper_bound as used by pbrt, to find a point light or - triangle to emit from, proportional to area. a good improvement would be to - also sample proportional to power, though it's not so well defined with - OSL shaders. */ + * triangle to emit from, proportional to area. a good improvement would be to + * also sample proportional to power, though it's not so well defined with + * OSL shaders. */ int first = 0; int len = kernel_data.integrator.num_distribution + 1; diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index bdd147f83d3..939f3915b6c 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -28,7 +28,7 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ #ifndef __KERNEL_MONTECARLO_CL__ #define __KERNEL_MONTECARLO_CL__ diff --git a/intern/cycles/kernel/kernel_optimized.cpp b/intern/cycles/kernel/kernel_optimized.cpp index 393686bb203..0b662095133 100644 --- a/intern/cycles/kernel/kernel_optimized.cpp +++ b/intern/cycles/kernel/kernel_optimized.cpp @@ -17,8 +17,8 @@ */ /* Optimized CPU kernel entry points. This file is compiled with SSE3 - optimization flags and nearly all functions inlined, while kernel.cpp - is compiled without for other CPU's. */ + * optimization flags and nearly all functions inlined, while kernel.cpp + * is compiled without for other CPU's. */ #ifdef WITH_OPTIMIZED_KERNEL diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index e41a5a62c14..16fd0499b00 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -59,7 +59,7 @@ __device_inline void path_state_init(PathState *state) __device_inline void path_state_next(KernelGlobals *kg, PathState *state, int label) { /* ray through transparent keeps same flags from previous ray and is - not counted as a regular bounce, transparent has separate max */ + * not counted as a regular bounce, transparent has separate max */ if(label & LABEL_TRANSPARENT) { state->flag |= PATH_RAY_TRANSPARENT; state->transparent_bounce++; @@ -159,13 +159,13 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra #ifdef __TRANSPARENT_SHADOWS__ if(result && kernel_data.integrator.transparent_shadows) { /* transparent shadows work in such a way to try to minimize overhead - in cases where we don't need them. after a regular shadow ray is - cast we check if the hit primitive was potentially transparent, and - only in that case start marching. this gives on extra ray cast for - the cases were we do want transparency. - - also note that for this to work correct, multi close sampling must - be used, since we don't pass a random number to shader_eval_surface */ + * in cases where we don't need them. after a regular shadow ray is + * cast we check if the hit primitive was potentially transparent, and + * only in that case start marching. this gives on extra ray cast for + * the cases were we do want transparency. + * + * also note that for this to work correct, multi close sampling must + * be used, since we don't pass a random number to shader_eval_surface */ if(shader_transparent_shadow(kg, &isect)) { float3 throughput = make_float3(1.0f, 1.0f, 1.0f); float3 Pend = ray->P + ray->D*ray->t; @@ -266,7 +266,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput); /* blurring of bsdf after bounces, for rays that have a small likelihood - of following this particular path (diffuse, rough glossy) */ + * of following this particular path (diffuse, rough glossy) */ if(kernel_data.integrator.filter_glossy != FLT_MAX) { float blur_pdf = kernel_data.integrator.filter_glossy*min_ray_pdf; @@ -305,8 +305,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R #endif /* path termination. this is a strange place to put the termination, it's - mainly due to the mixed in MIS that we use. gives too many unneeded - shader evaluations, only need emission if we are going to terminate */ + * mainly due to the mixed in MIS that we use. gives too many unneeded + * shader evaluations, only need emission if we are going to terminate */ float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index 72d36811626..64747bcb42e 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -28,7 +28,7 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ #ifndef __KERNEL_PROJECTION_CL__ #define __KERNEL_PROJECTION_CL__ diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 6d15100f8a3..008ef2061a2 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -23,8 +23,8 @@ typedef uint RNG; #ifdef __SOBOL__ /* skip initial numbers that are not as well distributed, especially the - first sequence is just 0 everywhere, which can be problematic for e.g. - path termination */ + * first sequence is just 0 everywhere, which can be problematic for e.g. + * path termination */ #define SOBOL_SKIP 64 /* High Dimensional Sobol */ @@ -66,7 +66,7 @@ __device uint sobol_inverse(uint i) } /* multidimensional sobol with generator matrices - dimension 0 and 1 are equal to van_der_corput() and sobol() respectively */ + * dimension 0 and 1 are equal to van_der_corput() and sobol() respectively */ __device uint sobol_dimension(KernelGlobals *kg, int index, int dimension) { uint result = 0; diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index 674c3b52539..384c3a8a506 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -208,7 +208,7 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd) motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL); /* object motion. note that depending on the mesh having motion vectors, this - transformation was set match the world/object space of motion_pre/post */ + * transformation was set match the world/object space of motion_pre/post */ Transform tfm; tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_PRE); @@ -220,7 +220,7 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd) float3 P; /* camera motion, for perspective/orthographic motion.pre/post will be a - world-to-raster matrix, for panorama it's world-to-camera */ + * world-to-raster matrix, for panorama it's world-to-camera */ if (kernel_data.cam.type != CAMERA_PANORAMA) { tfm = kernel_data.cam.worldtoraster; P = transform_perspective(&tfm, sd->P); diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.h b/intern/cycles/kernel/osl/nodes/node_fresnel.h index de5d29a3c18..dfd0a23fe1e 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.h +++ b/intern/cycles/kernel/osl/nodes/node_fresnel.h @@ -17,7 +17,7 @@ float fresnel_dielectric(vector Incoming, normal Normal, float eta) { /* compute fresnel reflectance without explicitly computing - the refracted direction */ + * the refracted direction */ float c = fabs(dot(Incoming, Normal)); float g = eta * eta - 1 + c * c; float result; diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 12f3a377ef4..a1574d6e0db 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -65,7 +65,7 @@ void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_) bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) { /* this is only used for shader and object space, we don't really have - a concept of shader space, so we just use object space for both. */ + * a concept of shader space, so we just use object space for both. */ if (xform) { KernelGlobals *kg = kernel_globals; const ShaderData *sd = (const ShaderData *)xform; @@ -86,7 +86,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) { /* this is only used for shader and object space, we don't really have - a concept of shader space, so we just use object space for both. */ + * a concept of shader space, so we just use object space for both. */ if (xform) { KernelGlobals *kg = kernel_globals; const ShaderData *sd = (const ShaderData *)xform; @@ -305,11 +305,11 @@ void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names, AttrQuery &query = m_attr_queries.back(); /* make space for what we need. the only reason to use - std::vector is to skip the delete */ + * std::vector is to skip the delete */ query.attr_names.resize(nattrs); query.attr_partio_types.resize(nattrs); /* capacity will keep the length of the smallest array passed - to the query. Just to prevent buffer overruns */ + * to the query. Just to prevent buffer overruns */ query.capacity = -1; for (int i = 0; i < nattrs; ++i) { @@ -323,7 +323,7 @@ void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names, query.capacity = min(query.capacity, (int)attr_types[i].numelements()); /* convert the OSL (OIIO) type to the equivalent Partio type so - we can do a fast check at query time. */ + * we can do a fast check at query time. */ if (element_type == TypeDesc::TypeFloat) { query.attr_partio_types[i] = Partio::FLOAT; } @@ -359,7 +359,7 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo int max_points, void *_attr_query, void **attr_outdata) { /* todo: this code has never been tested, and most likely does not - work. it's based on the example code in OSL */ + * work. it's based on the example code in OSL */ #ifdef WITH_PARTIO /* query Partio for this pointcloud lookup using cached attr_query */ @@ -374,7 +374,7 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo Partio::ParticlesData *cloud = get_pointcloud(filename); /* now we have to look up all the attributes in the file. we can't do this - before hand cause we never know what we are going to load. */ + * before hand cause we never know what we are going to load. */ int nattrs = attr_query->attr_names.size(); Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs); @@ -414,8 +414,8 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo } else { /* note we make a single call per attribute, we don't loop over the - points. Partio does it, so it is there that we have to care about - performance */ + * points. Partio does it, so it is there that we have to care about + * performance */ cloud->data(attr[j], count, &indices[0], true, attr_outdata[j]); } } diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 88735c073c2..e637b53ab78 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -76,14 +76,14 @@ private: #ifdef WITH_PARTIO /* OSL gets pointers to this but its definition is private. - right now it only caches the types already converted to - Partio constants. this is what get_pointcloud_attr_query - returns */ + * right now it only caches the types already converted to + * Partio constants. this is what get_pointcloud_attr_query + * returns */ struct AttrQuery { /* names of the attributes to query */ std::vector attr_names; /* types as (enum Partio::ParticleAttributeType) of the - attributes in the query */ + * attributes in the query */ std::vector attr_partio_types; /* for sanity checks, capacity of the output arrays */ int capacity; diff --git a/intern/cycles/kernel/svm/bsdf.h b/intern/cycles/kernel/svm/bsdf.h index 18c1da73fbd..ba78a93f54f 100644 --- a/intern/cycles/kernel/svm/bsdf.h +++ b/intern/cycles/kernel/svm/bsdf.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __OSL_BSDF_H__ #define __OSL_BSDF_H__ diff --git a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h index 2e9343647b8..40249dbe9c6 100644 --- a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h @@ -28,7 +28,7 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ #ifndef __BSDF_ASHIKHMIN_VELVET_H__ #define __BSDF_ASHIKHMIN_VELVET_H__ diff --git a/intern/cycles/kernel/svm/bsdf_diffuse.h b/intern/cycles/kernel/svm/bsdf_diffuse.h index e8a002cb84c..45e82a566c0 100644 --- a/intern/cycles/kernel/svm/bsdf_diffuse.h +++ b/intern/cycles/kernel/svm/bsdf_diffuse.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_DIFFUSE_H__ #define __BSDF_DIFFUSE_H__ diff --git a/intern/cycles/kernel/svm/bsdf_microfacet.h b/intern/cycles/kernel/svm/bsdf_microfacet.h index 8771578a2fd..01e3acb76e8 100644 --- a/intern/cycles/kernel/svm/bsdf_microfacet.h +++ b/intern/cycles/kernel/svm/bsdf_microfacet.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_MICROFACET_H__ #define __BSDF_MICROFACET_H__ diff --git a/intern/cycles/kernel/svm/bsdf_reflection.h b/intern/cycles/kernel/svm/bsdf_reflection.h index f00b72c4869..09b4e0e48f0 100644 --- a/intern/cycles/kernel/svm/bsdf_reflection.h +++ b/intern/cycles/kernel/svm/bsdf_reflection.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_REFLECTION_H__ #define __BSDF_REFLECTION_H__ diff --git a/intern/cycles/kernel/svm/bsdf_refraction.h b/intern/cycles/kernel/svm/bsdf_refraction.h index 07ef8633e0d..c9c268999c0 100644 --- a/intern/cycles/kernel/svm/bsdf_refraction.h +++ b/intern/cycles/kernel/svm/bsdf_refraction.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_REFRACTION_H__ #define __BSDF_REFRACTION_H__ diff --git a/intern/cycles/kernel/svm/bsdf_transparent.h b/intern/cycles/kernel/svm/bsdf_transparent.h index 4425c4bf104..511836cdfa2 100644 --- a/intern/cycles/kernel/svm/bsdf_transparent.h +++ b/intern/cycles/kernel/svm/bsdf_transparent.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_TRANSPARENT_H__ #define __BSDF_TRANSPARENT_H__ diff --git a/intern/cycles/kernel/svm/bsdf_ward.h b/intern/cycles/kernel/svm/bsdf_ward.h index d46baf099a6..86bca69425d 100644 --- a/intern/cycles/kernel/svm/bsdf_ward.h +++ b/intern/cycles/kernel/svm/bsdf_ward.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_WARD_H__ #define __BSDF_WARD_H__ diff --git a/intern/cycles/kernel/svm/bsdf_westin.h b/intern/cycles/kernel/svm/bsdf_westin.h index 21e5018c489..6193d81c244 100644 --- a/intern/cycles/kernel/svm/bsdf_westin.h +++ b/intern/cycles/kernel/svm/bsdf_westin.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __BSDF_WESTIN_H__ #define __BSDF_WESTIN_H__ diff --git a/intern/cycles/kernel/svm/emissive.h b/intern/cycles/kernel/svm/emissive.h index 0b0218674b8..9a906f82963 100644 --- a/intern/cycles/kernel/svm/emissive.h +++ b/intern/cycles/kernel/svm/emissive.h @@ -1,34 +1,34 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 8409e83d94e..935504026ef 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -374,7 +374,7 @@ __device void svm_node_mix_closure(ShaderData *sd, float *stack, { #ifdef __MULTI_CLOSURE__ /* fetch weight from blend input, previous mix closures, - and write to stack to be used by closure nodes later */ + * and write to stack to be used by closure nodes later */ uint weight_offset, in_weight_offset, weight1_offset, weight2_offset; decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset); @@ -387,8 +387,8 @@ __device void svm_node_mix_closure(ShaderData *sd, float *stack, stack_store_float(stack, weight2_offset, in_weight*weight); #else /* pick a closure and make the random number uniform over 0..1 again. - closure 1 starts on the next node, for closure 2 the start is at an - offset from the current node, so we jump */ + * closure 1 starts on the next node, for closure 2 the start is at an + * offset from the current node, so we jump */ uint weight_offset = node.y; uint node_jump = node.z; float weight = stack_load_float(stack, weight_offset); @@ -410,8 +410,8 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused, /* nothing to do, handled in compiler */ #else /* pick one of the two closures with probability 0.5. sampling quality - is not going to be great, for that we'd need to evaluate the weights - of the two closures being added */ + * is not going to be great, for that we'd need to evaluate the weights + * of the two closures being added */ float weight = 0.5f; if(*randb < weight) { diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 388f006c40f..3b2b9204d86 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -92,13 +92,13 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y) float4 r; /* not particularly proud of this massive switch, what are the - alternatives? - - use a single big 1D texture, and do our own lookup/filtering - - group by size and use a 3d texture, performance impact - - group into larger texture with some padding for correct lerp - - also note that cuda has 128 textures limit, we use 100 now, since - we still need some for other storage */ + * alternatives? + * - use a single big 1D texture, and do our own lookup/filtering + * - group by size and use a 3d texture, performance impact + * - group into larger texture with some padding for correct lerp + * + * also note that cuda has 128 textures limit, we use 100 now, since + * we still need some for other storage */ switch(id) { case 0: r = kernel_tex_image_interp(__tex_image_000, x, y); break; diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h index 1d3ace061ab..22f3187943c 100644 --- a/intern/cycles/kernel/svm/svm_noise.h +++ b/intern/cycles/kernel/svm/svm_noise.h @@ -28,7 +28,7 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index da74654f25e..d8582621132 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -152,7 +152,7 @@ __device float voronoi_CrS(float3 p) { return 2.0f*voronoi_Cr(p) - 1.0f; } __device float noise_basis(float3 p, NodeNoiseBasis basis) { /* Only Perlin enabled for now, others break CUDA compile by making kernel - too big, with compile using > 4GB, due to everything being inlined. */ + * too big, with compile using > 4GB, due to everything being inlined. */ #if 0 if(basis == NODE_NOISE_PERLIN) diff --git a/intern/cycles/kernel/svm/volume.h b/intern/cycles/kernel/svm/volume.h index 86cb2dcc24e..10e9c5de352 100644 --- a/intern/cycles/kernel/svm/volume.h +++ b/intern/cycles/kernel/svm/volume.h @@ -19,7 +19,7 @@ CCL_NAMESPACE_BEGIN /* note: the interfaces here are just as an example, need to figure - out the right functions and parameters to use */ + * out the right functions and parameters to use */ /* ISOTROPIC VOLUME CLOSURE */ diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index 77ad4a5a4b0..78712ed89ef 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -35,7 +35,7 @@ class Device; struct float4; /* Buffer Parameters - Size of render buffer and how it fits in the full image (border render). */ + * Size of render buffer and how it fits in the full image (border render). */ class BufferParams { public: @@ -98,8 +98,8 @@ public: /* buffer parameters */ BufferParams params; /* dimensions for how much of the buffer is actually ready for display. - with progressive render we can be using only a subset of the buffer. - if these are zero, it means nothing can be drawn yet */ + * with progressive render we can be using only a subset of the buffer. + * if these are zero, it means nothing can be drawn yet */ int draw_width, draw_height; /* draw alpha channel? */ bool transparent; diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 878aa87510e..035821fadde 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -142,7 +142,7 @@ void Pass::add(PassType type, vector& passes) passes.push_back(pass); /* order from by components, to ensure alignment so passes with size 4 - come first and then passes with size 1 */ + * come first and then passes with size 1 */ sort(passes.begin(), passes.end(), compare_pass_order); if(pass.divide_type != PASS_NONE) diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index a0e7af66100..34c8879aa1f 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -375,8 +375,8 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector& visited, vector removed(nodes.size(), false); vector visited(nodes.size(), false); @@ -495,7 +495,7 @@ void ShaderGraph::bump_from_displacement() copy_nodes(nodes_displace, nodes_dy); /* mark nodes to indicate they are use for bump computation, so - that any texture coordinates are shifted by dx/dy when sampling */ + * that any texture coordinates are shifted by dx/dy when sampling */ foreach(NodePair& pair, nodes_center) pair.second->bump = SHADER_BUMP_CENTER; foreach(NodePair& pair, nodes_dx) @@ -516,15 +516,15 @@ void ShaderGraph::bump_from_displacement() connect(out_dy, bump->input("SampleY")); /* connect bump output to normal input nodes that aren't set yet. actually - this will only set the normal input to the geometry node that we created - and connected to all other normal inputs already. */ + * this will only set the normal input to the geometry node that we created + * and connected to all other normal inputs already. */ foreach(ShaderNode *node, nodes) foreach(ShaderInput *input, node->inputs) if(!input->link && input->default_value == ShaderInput::NORMAL) connect(bump->output("Normal"), input); /* finally, add the copied nodes to the graph. we can't do this earlier - because we would create dependency cycles in the above loop */ + * because we would create dependency cycles in the above loop */ foreach(NodePair& pair, nodes_center) add(pair.second); foreach(NodePair& pair, nodes_dx) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 6417d0e2103..dc20dbdbea2 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -66,7 +66,7 @@ static bool is_float_image(const string& filename) if(in->open(filename, spec)) { /* check the main format, and channel formats; - if any take up more than one byte, we'll need a float texture slot */ + * if any take up more than one byte, we'll need a float texture slot */ if(spec.format.basesize() > 1) is_float = true; @@ -171,8 +171,8 @@ void ImageManager::remove_image(const string& filename) assert(images[slot]->users >= 0); /* don't remove immediately, rather do it all together later on. one of - the reasons for this is that on shader changes we add and remove nodes - that use them, but we do not want to reload the image all the time. */ + * the reasons for this is that on shader changes we add and remove nodes + * that use them, but we do not want to reload the image all the time. */ if(images[slot]->users == 0) need_update = true; @@ -189,8 +189,8 @@ void ImageManager::remove_image(const string& filename) assert(float_images[slot]->users >= 0); /* don't remove immediately, rather do it all together later on. one of - the reasons for this is that on shader changes we add and remove nodes - that use them, but we do not want to reload the image all the time. */ + * the reasons for this is that on shader changes we add and remove nodes + * that use them, but we do not want to reload the image all the time. */ if(float_images[slot]->users == 0) need_update = true; @@ -483,7 +483,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progress& progess) { /* for OpenCL, we pack all image textures inside a single big texture, and - will do our own interpolation in the kernel */ + * will do our own interpolation in the kernel */ size_t size = 0; for(size_t slot = 0; slot < images.size(); slot++) { diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 1bf1cde4a1c..e918de990c2 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -362,7 +362,7 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene, float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res; /* stuff the total into the brightness value for the last entry, because - we are going to normalize the CDFs to 0.0 to 1.0 afterwards */ + * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */ cond_cdf[i * cdf_count + res].x = cdf_total; if(cdf_total > 0.0f) diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index cabbd5760c2..8f5f2647ebf 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -474,7 +474,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, AttributeRequestSet& attributes = mesh_attributes[i]; /* todo: we now store std and name attributes from requests even if - they actually refer to the same mesh attributes, optimize */ + * they actually refer to the same mesh attributes, optimize */ foreach(AttributeRequest& req, attributes.requests) { Attribute *mattr = mesh->attributes.find(req); @@ -493,7 +493,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, } /* we abuse AttributeRequest to pass on info like element and - offset, it doesn't really make sense but is convenient */ + * offset, it doesn't really make sense but is convenient */ /* store element and type */ if(mattr->element == Attribute::VERTEX) @@ -528,7 +528,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, } /* mesh vertex/triangle index is global, not per object, so we sneak - a correction for that in here */ + * a correction for that in here */ if(req.element == ATTR_ELEMENT_VERTEX) req.offset -= mesh->vert_offset; else if(mattr->element == Attribute::FACE) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 259a0d25bcc..376a7911fc9 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -89,7 +89,7 @@ void Object::apply_transform() Transform ntfm = transform_transpose(transform_inverse(tfm)); /* we keep normals pointing in same direction on negative scale, notify - mesh about this in it (re)calculates normals */ + * mesh about this in it (re)calculates normals */ if(transform_negative_scale(tfm)) mesh->transform_negative_scaled = true; @@ -161,7 +161,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene Transform itfm = transform_inverse(tfm); /* compute surface area. for uniform scale we can do avoid the many - transform calls and share computation for instances */ + * transform calls and share computation for instances */ /* todo: correct for displacement, and move to a better place */ float uniform_scale; float surface_area = 0.0f; @@ -206,8 +206,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene if(need_motion == Scene::MOTION_PASS) { /* motion transformations, is world/object space depending if mesh - comes with deformed position in object space, or if we transform - the shading point in world space */ + * comes with deformed position in object space, or if we transform + * the shading point in world space */ Transform mtfm_pre = ob->motion.pre; Transform mtfm_post = ob->motion.post; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index b0173334c76..04af9b48280 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -167,7 +167,7 @@ string OSLCompiler::compatible_name(const char *name) bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) { /* exception for output node, only one input is actually used - depending on the current shader type */ + * depending on the current shader type */ if(node->name == ustring("output")) { if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 173d73ea2c7..a9f7e5beb56 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -116,8 +116,8 @@ bool Session::ready_to_reset() void Session::reset_gpu(BufferParams& buffer_params, int samples) { /* block for buffer acces and reset immediately. we can't do this - in the thread, because we need to allocate an OpenGL buffer, and - that only works in the main thread */ + * in the thread, because we need to allocate an OpenGL buffer, and + * that only works in the main thread */ thread_scoped_lock display_lock(display->mutex); thread_scoped_lock buffers_lock(buffers->mutex); @@ -140,10 +140,10 @@ bool Session::draw_gpu(BufferParams& buffer_params) /* first check we already rendered something */ if(gpu_draw_ready) { /* then verify the buffers have the expected size, so we don't - draw previous results in a resized window */ + * draw previous results in a resized window */ if(!buffer_params.modified(display->params)) { /* for CUDA we need to do tonemapping still, since we can - only access GL buffers from the main thread */ + * only access GL buffers from the main thread */ if(gpu_need_tonemap) { thread_scoped_lock buffers_lock(buffers->mutex); tonemap(); @@ -185,7 +185,7 @@ void Session::run_gpu() } else { /* if in interactive mode, and we are either paused or done for now, - wait for pause condition notify to wake up again */ + * wait for pause condition notify to wake up again */ thread_scoped_lock pause_lock(pause_mutex); if(pause || no_tiles) { @@ -224,8 +224,8 @@ void Session::run_gpu() if(!no_tiles) { /* buffers mutex is locked entirely while rendering each - sample, and released/reacquired on each iteration to allow - reset and draw in between */ + * sample, and released/reacquired on each iteration to allow + * reset and draw in between */ thread_scoped_lock buffers_lock(buffers->mutex); /* update status and timing */ @@ -294,7 +294,7 @@ bool Session::draw_cpu(BufferParams& buffer_params) /* first check we already rendered something */ if(display->draw_ready()) { /* then verify the buffers have the expected size, so we don't - draw previous results in a resized window */ + * draw previous results in a resized window */ if(!buffer_params.modified(display->params)) { display->draw(device); @@ -334,7 +334,7 @@ void Session::run_cpu() } else { /* if in interactive mode, and we are either paused or done for now, - wait for pause condition notify to wake up again */ + * wait for pause condition notify to wake up again */ thread_scoped_lock pause_lock(pause_mutex); if(pause || no_tiles) { @@ -362,8 +362,8 @@ void Session::run_cpu() if(!no_tiles) { /* buffers mutex is locked entirely while rendering each - sample, and released/reacquired on each iteration to allow - reset and draw in between */ + * sample, and released/reacquired on each iteration to allow + * reset and draw in between */ thread_scoped_lock buffers_lock(buffers->mutex); /* update scene */ @@ -406,7 +406,7 @@ void Session::run_cpu() } else if(need_tonemap) { /* tonemap only if we do not reset, we don't we don't - want to show the result of an incomplete sample*/ + * wan't to show the result of an incomplete sample*/ tonemap(); } @@ -535,8 +535,8 @@ void Session::update_scene() progress.set_status("Updating Scene"); /* update camera if dimensions changed for progressive render. the camera - knows nothing about progressive or cropped rendering, it just gets the - image dimensions passed in */ + * knows nothing about progressive or cropped rendering, it just gets the + * image dimensions passed in */ Camera *cam = scene->camera; int width = tile_manager.state.buffer.full_width; int height = tile_manager.state.buffer.full_height; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index f50709146ef..fae1d6bd81c 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -81,9 +81,9 @@ void Shader::tag_update(Scene *scene) scene->light_manager->need_update = true; /* get requested attributes. this could be optimized by pruning unused - nodes here already, but that's the job of the shader manager currently, - and may not be so great for interactive rendering where you temporarily - disconnect a node */ + * nodes here already, but that's the job of the shader manager currently, + * and may not be so great for interactive rendering where you temporarily + * disconnect a node */ AttributeRequestSet prev_attributes = attributes; attributes.clear(); @@ -91,7 +91,7 @@ void Shader::tag_update(Scene *scene) node->attributes(&attributes); /* compare if the attributes changed, mesh manager will check - need_update_attributes, update the relevant meshes and clear it. */ + * need_update_attributes, update the relevant meshes and clear it. */ if(attributes.modified(prev_attributes)) { need_update_attributes = true; scene->mesh_manager->need_update = true; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 48d517ce21a..02788008060 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -53,8 +53,8 @@ public: ShaderGraph *graph; /* shader graph with auto bump mapping included, we compile two shaders, - with and without bump, because the displacement method is a mesh - level setting, so we need to handle both */ + * with and without bump, because the displacement method is a mesh + * level setting, so we need to handle both */ ShaderGraph *graph_bump; /* sampling */ @@ -109,7 +109,7 @@ public: int get_shader_id(uint shader, Mesh *mesh = NULL, bool smooth = false); /* add default shaders to scene, to use as default for things that don't - have any shader assigned explicitly */ + * have any shader assigned explicitly */ static void add_default(Scene *scene); protected: diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 1ff3ac20d50..e160f1c93af 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -251,11 +251,11 @@ void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output) void SVMCompiler::stack_clear_users(ShaderNode *node, set& done) { /* optimization we should add: - find and lower user counts for outputs for which all inputs are done. - this is done before the node is compiled, under the assumption that the - node will first load all inputs from the stack and then writes its - outputs. this used to work, but was disabled because it gave trouble - with inputs getting stack positions assigned */ + * find and lower user counts for outputs for which all inputs are done. + * this is done before the node is compiled, under the assumption that the + * node will first load all inputs from the stack and then writes its + * outputs. this used to work, but was disabled because it gave trouble + * with inputs getting stack positions assigned */ foreach(ShaderInput *input, node->inputs) { ShaderOutput *output = input->link; @@ -418,8 +418,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set& done) add_node(NODE_ADD_CLOSURE, 0, 0, 0); /* generate code for closure 1 - note we backup all compiler state and restore it afterwards, so one - closure choice doesn't influence the other*/ + * note we backup all compiler state and restore it afterwards, so one + * closure choice doesn't influence the other*/ if(cl1in->link) { StackBackup backup; stack_backup(backup, done); @@ -448,7 +448,7 @@ void SVMCompiler::generate_closure(ShaderNode *node, set& done) add_node(NODE_END, 0, 0, 0); /* set jump for mix node, -1 because offset is already - incremented when this jump is added to it */ + * incremented when this jump is added to it */ svm_nodes[mix_offset].z = cl2_offset - mix_offset - 1; done.insert(node); @@ -482,9 +482,9 @@ void SVMCompiler::generate_closure(ShaderNode *node, set& done) void SVMCompiler::generate_multi_closure(ShaderNode *node, set& done, uint in_offset) { /* todo: the weaks point here is that unlike the single closure sampling - we will evaluate all nodes even if they are used as input for closures - that are unused. it's not clear what would be the best way to skip such - nodes at runtime, especially if they are tangled up */ + * we will evaluate all nodes even if they are used as input for closures + * that are unused. it's not clear what would be the best way to skip such + * nodes at runtime, especially if they are tangled up */ if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { ShaderInput *fin = node->input("Fac"); diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp index 640c30eba9d..07f89b2a371 100644 --- a/intern/cycles/subd/subd_build.cpp +++ b/intern/cycles/subd/subd_build.cpp @@ -82,7 +82,7 @@ static float pseudoValence(SubdVert *vert) if(vert->is_boundary()) { /* we treat boundary verts as being half a closed mesh. corners are - special case. n = 4 for corners and n = 2*(n-1) for boundaries. */ + * special case. n = 4 for corners and n = 2*(n-1) for boundaries. */ if(valence == 2) return 4; return (valence - 1)*2; } @@ -481,10 +481,11 @@ void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStenci } /* this change makes the triangle boundaries smoother, but distorts the quads next to them */ - /*if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) - { +#if 0 + if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) { y *= 4.0f / 3.0f; - }*/ + } +#endif stencil->get(interior1Indices[primitiveOffset+v]) = stencil->get(edge1Indices[primitiveOffset+v]); stencil->get(interior1Indices[primitiveOffset+v]) += x; @@ -539,8 +540,10 @@ void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStenci } /* this change makes the triangle boundaries smoother, but distorts the quads next to them. */ - /*if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) - y *= 4.0f / 3.0f;*/ +#if 0 + if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) + y *= 4.0f / 3.0f; +#endif stencil->get(interior2Indices[primitiveOffset+v]) = stencil->get(edge2Indices[primitiveOffset+v]); stencil->get(interior2Indices[primitiveOffset+v]) += x; diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 6e24bb410b5..583abb2b58a 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -81,9 +81,9 @@ void EdgeDice::stitch_triangles(vector& outer, vector& inner) return; // XXX avoid crashes for Mu or Mv == 1, missing polygons /* stitch together two arrays of verts with triangles. at each step, - we compare using the next verts on both sides, to find the split - direction with the smallest diagonal, and use that in order to keep - the triangle shape reasonable. */ + * we compare using the next verts on both sides, to find the split + * direction with the smallest diagonal, and use that in order to keep + * the triangle shape reasonable. */ for(size_t i = 0, j = 0; i+1 < inner.size() || j+1 < outer.size();) { int v0, v1, v2; @@ -354,8 +354,8 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) // XXX normals are flipped, why? /* grid is constructed starting from the outside edges, and adding - progressively smaller inner triangles that connected to the outer - one, until M = 1 or 2, the we fill up the last part. */ + * progressively smaller inner triangles that connected to the outer + * one, until M = 1 or 2, the we fill up the last part. */ vector outer_u, outer_v, outer_w; int m; diff --git a/intern/cycles/subd/subd_ring.cpp b/intern/cycles/subd/subd_ring.cpp index cbd12e60da0..66eab02231c 100644 --- a/intern/cycles/subd/subd_ring.cpp +++ b/intern/cycles/subd/subd_ring.cpp @@ -82,8 +82,8 @@ int SubdFaceRing::vert_index(SubdVert *vertex) void SubdFaceRing::evaluate_stencils(float3 *P, StencilMask *mask, int num) { /* first we sort verts by id. this way verts will always be added - in the same order to ensure the exact same float ops happen for control - points of other patches, so we get water-tight patches */ + * in the same order to ensure the exact same float ops happen for control + * points of other patches, so we get water-tight patches */ int num_verts = m_verts.size(); vector vmap(num_verts); @@ -161,8 +161,8 @@ bool SubdFaceRing::is_quad(SubdFace *face) bool SubdFaceRing::is_boundary(SubdFace *face) { /* note that face->is_boundary() returns a different result. That function - returns true when any of the *edges* are on the boundary. however, this - function returns true if any of the face *verts* are on the boundary. */ + * returns true when any of the *edges* are on the boundary. however, this + * function returns true if any of the face *verts* are on the boundary. */ for(SubdFace::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) { SubdEdge *edge = it.current(); diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp index f81a11ba9da..2960022fd8d 100644 --- a/intern/cycles/util/util_cuda.cpp +++ b/intern/cycles/util/util_cuda.cpp @@ -326,8 +326,8 @@ bool cuLibraryInit() CUDA_LIBRARY_FIND(cuCtxGetLimit); /* functions which changed 3.1 -> 3.2 for 64 bit stuff, the cuda library - has both the old ones for compatibility and new ones with _v2 postfix, - we load the _v2 ones here. */ + * has both the old ones for compatibility and new ones with _v2 postfix, + * we load the _v2 ones here. */ CUDA_LIBRARY_FIND_V2(cuDeviceTotalMem); CUDA_LIBRARY_FIND_V2(cuCtxCreate); CUDA_LIBRARY_FIND_V2(cuModuleGetGlobal); diff --git a/intern/cycles/util/util_md5.cpp b/intern/cycles/util/util_md5.cpp index 25a77f18d02..749b777efdc 100644 --- a/intern/cycles/util/util_md5.cpp +++ b/intern/cycles/util/util_md5.cpp @@ -148,7 +148,7 @@ void MD5Hash::process(const uint8_t *data /*[64]*/) /* Round 1. */ /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ + * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ @@ -172,9 +172,9 @@ void MD5Hash::process(const uint8_t *data /*[64]*/) SET(b, c, d, a, 15, 22, T16); #undef SET - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ + /* Round 2. */ + /* Let [abcd k s i] denote the operation + * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ @@ -198,9 +198,9 @@ void MD5Hash::process(const uint8_t *data /*[64]*/) SET(b, c, d, a, 12, 20, T32); #undef SET - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ + /* Round 3. */ + /* Let [abcd k s t] denote the operation + * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ @@ -224,9 +224,9 @@ void MD5Hash::process(const uint8_t *data /*[64]*/) SET(b, c, d, a, 2, 23, T48); #undef SET - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ + /* Round 4. */ + /* Let [abcd k s t] denote the operation + * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ @@ -250,9 +250,9 @@ void MD5Hash::process(const uint8_t *data /*[64]*/) SET(b, c, d, a, 9, 21, T64); #undef SET - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ + /* Then perform the following additions. (That is increment each + * of the four registers by the value it had before this block + * was started.) */ abcd[0] += a; abcd[1] += b; abcd[2] += c; diff --git a/intern/cycles/util/util_opencl.h b/intern/cycles/util/util_opencl.h index 2e97097ef36..907d372d3ce 100644 --- a/intern/cycles/util/util_opencl.h +++ b/intern/cycles/util/util_opencl.h @@ -36,27 +36,27 @@ CCL_NAMESPACE_BEGIN #endif // CLCC_GENERATE_DOCUMENTATION /******************************************************************************* -* Copyright (c) 2008-2009 The Khronos Group Inc. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and/or associated documentation files (the -* "Materials"), to deal in the Materials without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Materials, and to -* permit persons to whom the Materials are furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Materials. -* -* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -******************************************************************************/ + * Copyright (c) 2008-2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ #ifndef CLCC_GENERATE_DOCUMENTATION @@ -88,20 +88,20 @@ typedef double cl_double; /* -* Vector types -* -* Note: OpenCL requires that all types be naturally aligned. -* This means that vector types must be naturally aligned. -* For example, a vector of four floats must be aligned to -* a 16 byte boundary (calculated as 4 * the natural 4-byte -* alignment of the float). The alignment qualifiers here -* will only function properly if your compiler supports them -* and if you don't actively work to defeat them. For example, -* in order for a cl_float4 to be 16 byte aligned in a struct, -* the start of the struct must itself be 16-byte aligned. -* -* Maintaining proper alignment is the user's responsibility. -*/ + * Vector types + * + * Note: OpenCL requires that all types be naturally aligned. + * This means that vector types must be naturally aligned. + * For example, a vector of four floats must be aligned to + * a 16 byte boundary (calculated as 4 * the natural 4-byte + * alignment of the float). The alignment qualifiers here + * will only function properly if your compiler supports them + * and if you don't actively work to defeat them. For example, + * in order for a cl_float4 to be 16 byte aligned in a struct, + * the start of the struct must itself be 16-byte aligned. + * + * Maintaining proper alignment is the user's responsibility. + */ typedef signed __int8 cl_char2[2]; typedef signed __int8 cl_char4[4]; typedef signed __int8 cl_char8[8]; @@ -168,20 +168,20 @@ typedef float cl_float __attribute__((aligned(4))); typedef double cl_double __attribute__((aligned(8))); /* -* Vector types -* -* Note: OpenCL requires that all types be naturally aligned. -* This means that vector types must be naturally aligned. -* For example, a vector of four floats must be aligned to -* a 16 byte boundary (calculated as 4 * the natural 4-byte -* alignment of the float). The alignment qualifiers here -* will only function properly if your compiler supports them -* and if you don't actively work to defeat them. For example, -* in order for a cl_float4 to be 16 byte aligned in a struct, -* the start of the struct must itself be 16-byte aligned. -* -* Maintaining proper alignment is the user's responsibility. -*/ + * Vector types + * + * Note: OpenCL requires that all types be naturally aligned. + * This means that vector types must be naturally aligned. + * For example, a vector of four floats must be aligned to + * a 16 byte boundary (calculated as 4 * the natural 4-byte + * alignment of the float). The alignment qualifiers here + * will only function properly if your compiler supports them + * and if you don't actively work to defeat them. For example, + * in order for a cl_float4 to be 16 byte aligned in a struct, + * the start of the struct must itself be 16-byte aligned. + * + * Maintaining proper alignment is the user's responsibility. + */ typedef int8_t cl_char2[2] __attribute__((aligned(2))); typedef int8_t cl_char4[4] __attribute__((aligned(4))); typedef int8_t cl_char8[8] __attribute__((aligned(8))); diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp index 69069a3bbce..717aa34c426 100644 --- a/intern/cycles/util/util_path.cpp +++ b/intern/cycles/util/util_path.cpp @@ -179,8 +179,8 @@ static bool path_read_text(const string& path, string& text) string path_source_replace_includes(const string& source_, const string& path) { /* our own little c preprocessor that replaces #includes with the file - contents, to work around issue of opencl drivers not supporting - include paths with spaces in them */ + * contents, to work around issue of opencl drivers not supporting + * include paths with spaces in them */ string source = source_; const string include = "#include \""; size_t n, pos = 0; diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp index ad7f3347cee..2d9f0fffae6 100644 --- a/intern/cycles/util/util_system.cpp +++ b/intern/cycles/util/util_system.cpp @@ -149,8 +149,10 @@ bool system_cpu_support_optimized() __cpuid(result, 0); num = result[0]; - /*__cpuid(result, 0x80000000); - num_ex = result[0];*/ +#if 0 + __cpuid(result, 0x80000000); + num_ex = result[0]; +#endif if(num >= 1) { __cpuid(result, 0x00000001); @@ -167,13 +169,15 @@ bool system_cpu_support_optimized() caps.fma3 = (result[2] & ((int)1 << 12)) != 0; } - /*if(num_ex >= 0x80000001) { +#if 0 + if(num_ex >= 0x80000001) { __cpuid(result, 0x80000001); caps.x64 = (result[3] & ((int)1 << 29)) != 0; caps.sse4a = (result[2] & ((int)1 << 6)) != 0; caps.fma4 = (result[2] & ((int)1 << 16)) != 0; caps.xop = (result[2] & ((int)1 << 11)) != 0; - }*/ + } +#endif caps_init = true; } diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 023630e8fae..ea0abd6f54f 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -164,7 +164,7 @@ void TaskScheduler::init(int num_threads) thread_scoped_lock lock(mutex); /* multiple cycles instances can use this task scheduler, sharing the same - threads, so we keep track of the number of users. */ + * threads, so we keep track of the number of users. */ if(users == 0) { do_exit = false; diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 008f68e69e8..9bea4e7808a 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -34,7 +34,7 @@ typedef boost::mutex::scoped_lock thread_scoped_lock; typedef boost::condition_variable thread_condition_variable; /* own pthread based implementation, to avoid boost version conflicts with - dynamically loaded blender plugins */ + * dynamically loaded blender plugins */ class thread { public: diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 1780994da27..860f2d4d888 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -139,7 +139,7 @@ Transform transform_inverse(const Transform& tfm) if(!transform_matrix4_gj_inverse(R, M)) { /* matrix is degenerate (e.g. 0 scale on some axis), ideally we should - never be in this situation, but try to invert it anyway with tweak */ + * never be in this situation, but try to invert it anyway with tweak */ M[0][0] += 1e-8f; M[1][1] += 1e-8f; M[2][2] += 1e-8f; diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index b460c4c87a2..d93bbff5415 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -255,7 +255,7 @@ Transform transform_inverse(const Transform& a); __device_inline bool transform_uniform_scale(const Transform& tfm, float& scale) { /* the epsilon here is quite arbitrary, but this function is only used for - surface area and bump, where we except it to not be so sensitive */ + * surface area and bump, where we except it to not be so sensitive */ Transform ttfm = transform_transpose(tfm); float eps = 1e-6f; -- cgit v1.2.3 From 43361487bad926a9b32ce879f5b6961154507dfc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 Jun 2012 17:45:22 +0000 Subject: code cleanup: quiet all warnings about double promotion (either by changing the type or explicitly casting). --- intern/cycles/blender/blender_camera.cpp | 4 ++-- intern/cycles/blender/blender_session.cpp | 2 +- intern/cycles/bvh/bvh_build.cpp | 4 ++-- intern/cycles/kernel/kernel_random.h | 2 +- intern/cycles/kernel/svm/svm_gradient.h | 2 +- intern/cycles/kernel/svm/svm_musgrave.h | 8 ++++---- intern/cycles/kernel/svm/svm_texture.h | 4 ++-- intern/cycles/render/nodes.cpp | 2 +- intern/cycles/util/util_color.h | 6 +++--- intern/cycles/util/util_math.h | 6 +++--- intern/cycles/util/util_transform.cpp | 16 ++++++++-------- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 3bc1fa34a98..cffc533f87b 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -297,7 +297,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->fisheye_lens = bcam->fisheye_lens; /* perspective */ - cam->fov = 2.0f*atan((0.5f*sensor_size)/bcam->lens/aspectratio); + cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio); cam->focaldistance = bcam->focaldistance; cam->aperturesize = bcam->aperturesize; cam->blades = bcam->apertureblades; @@ -405,7 +405,7 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: } else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) { /* orthographic view */ - bcam->farclip *= 0.5; + bcam->farclip *= 0.5f; bcam->nearclip = -bcam->farclip; bcam->type = CAMERA_ORTHOGRAPHIC; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index aeda40ae40e..be0c2686713 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -433,7 +433,7 @@ void BlenderSession::tag_redraw() update_status_progress(); /* offline render, redraw if timeout passed */ - if(time_dt() - last_redraw_time > 1.0f) { + if(time_dt() - last_redraw_time > 1.0) { write_render_result(); engine_tag_redraw((RenderEngine*)b_engine.ptr.data); last_redraw_time = time_dt(); diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 28237aea611..705b805a3a9 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -196,14 +196,14 @@ BVHNode* BVHBuild::run() void BVHBuild::progress_update() { - if(time_dt() - progress_start_time < 0.25f) + if(time_dt() - progress_start_time < 0.25) return; double progress_start = (double)progress_count/(double)progress_total; double duplicates = (double)(progress_total - progress_original_total)/(double)progress_total; string msg = string_printf("Building BVH %.0f%%, duplicates %.0f%%", - progress_start*100.0f, duplicates*100.0f); + progress_start * 100.0, duplicates * 100.0); progress.set_substatus(msg); progress_start_time = time_dt(); diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 008ef2061a2..9083b7cbfd7 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -119,7 +119,7 @@ __device_inline float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dime else shift = (*rng & 0xFFFF)/((float)0xFFFF); - return r + shift - floor(r + shift); + return r + shift - floorf(r + shift); #endif } diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h index ce551a680b8..b29abed4edc 100644 --- a/intern/cycles/kernel/svm/svm_gradient.h +++ b/intern/cycles/kernel/svm/svm_gradient.h @@ -45,7 +45,7 @@ __device float svm_gradient(float3 p, NodeGradientType type) return (x + y)/2.0f; } else if(type == NODE_BLEND_RADIAL) { - return atan2(y, x)/(2.0f*M_PI_F) + 0.5f; + return atan2f(y, x) / (2.0f * M_PI_F) + 0.5f; } else { float r = fmaxf(1.0f - sqrtf(x*x + y*y + z*z), 0.0f); diff --git a/intern/cycles/kernel/svm/svm_musgrave.h b/intern/cycles/kernel/svm/svm_musgrave.h index 9444dc20e6e..425909e59f1 100644 --- a/intern/cycles/kernel/svm/svm_musgrave.h +++ b/intern/cycles/kernel/svm/svm_musgrave.h @@ -41,7 +41,7 @@ __device_noinline float noise_musgrave_fBm(float3 p, NodeNoiseBasis basis, float p *= lacunarity; } - rmd = octaves - floor(octaves); + rmd = octaves - floorf(octaves); if(rmd != 0.0f) value += rmd * snoise(p) * pwr; @@ -69,7 +69,7 @@ __device_noinline float noise_musgrave_multi_fractal(float3 p, NodeNoiseBasis ba p *= lacunarity; } - rmd = octaves - floor(octaves); + rmd = octaves - floorf(octaves); if(rmd != 0.0f) value *= (rmd * pwr * snoise(p) + 1.0f); /* correct? */ @@ -102,7 +102,7 @@ __device_noinline float noise_musgrave_hetero_terrain(float3 p, NodeNoiseBasis b p *= lacunarity; } - rmd = octaves - floor(octaves); + rmd = octaves - floorf(octaves); if(rmd != 0.0f) { increment = (snoise(p) + offset) * pwr * value; value += rmd * increment; @@ -141,7 +141,7 @@ __device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, NodeNoiseB p *= lacunarity; } - rmd = octaves - floor(octaves); + rmd = octaves - floorf(octaves); if(rmd != 0.0f) result += rmd * ((snoise(p) + offset) * pwr); diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index d8582621132..d12a85a5402 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -191,7 +191,7 @@ __device float noise_basis_hard(float3 p, NodeNoiseBasis basis, int hard) __device float noise_wave(NodeWaveBasis wave, float a) { if(wave == NODE_WAVE_SINE) { - return 0.5f + 0.5f*sin(a); + return 0.5f + 0.5f * sinf(a); } else if(wave == NODE_WAVE_SAW) { float b = 2.0f*M_PI_F; @@ -234,7 +234,7 @@ __device_noinline float noise_turbulence(float3 p, NodeNoiseBasis basis, float o fscale *= 2.0f; } - float rmd = octaves - floor(octaves); + float rmd = octaves - floorf(octaves); if(rmd != 0.0f) { float t = noise_basis(fscale*p, basis); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 8fb92d2476e..0f64d858de0 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -332,7 +332,7 @@ static void sky_texture_precompute(KernelSunSky *ksunsky, float3 dir, float turb float T2 = T * T; float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta); - ksunsky->zenith_Y = (4.0453f * T - 4.9710f) * tan(chi) - 0.2155f * T + 2.4192f; + ksunsky->zenith_Y = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f; ksunsky->zenith_Y *= 0.06f; ksunsky->zenith_x = diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index 8b4a175f498..5136ea5c5db 100644 --- a/intern/cycles/util/util_color.h +++ b/intern/cycles/util/util_color.h @@ -29,15 +29,15 @@ __device float color_srgb_to_scene_linear(float c) if(c < 0.04045f) return (c < 0.0f)? 0.0f: c * (1.0f/12.92f); else - return pow((c + 0.055f)*(1.0f/1.055f), 2.4f); + return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f); } __device float color_scene_linear_to_srgb(float c) { if(c < 0.0031308f) return (c < 0.0f)? 0.0f: c * 12.92f; - else - return 1.055f * pow(c, 1.0f/2.4f) - 0.055f; + else + return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f; } #ifndef __KERNEL_OPENCL__ diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index cd44b7e8cda..a6bc478ee64 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -334,7 +334,7 @@ __device_inline float2 as_float2(const float4 a) __device_inline void print_float2(const char *label, const float2& a) { - printf("%s: %.8f %.8f\n", label, a.x, a.y); + printf("%s: %.8f %.8f\n", label, (double)a.x, (double)a.y); } #endif @@ -532,7 +532,7 @@ __device_inline float4 float3_to_float4(const float3 a) __device_inline void print_float3(const char *label, const float3& a) { - printf("%s: %.8f %.8f %.8f\n", label, a.x, a.y, a.z); + printf("%s: %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z); } __device_inline float3 rcp(const float3& a) @@ -844,7 +844,7 @@ __device_inline float4 reduce_add(const float4& a) __device_inline void print_float4(const char *label, const float4& a) { - printf("%s: %.8f %.8f %.8f %.8f\n", label, a.x, a.y, a.z, a.w); + printf("%s: %.8f %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z, (double)a.w); } #endif diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 860f2d4d888..b3c6506dfa0 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -160,15 +160,15 @@ static float4 transform_to_quat(const Transform& tfm) double trace = tfm[0][0] + tfm[1][1] + tfm[2][2]; float4 qt; - if(trace > 0.0f) { + if(trace > 0.0) { double s = sqrt(trace + 1.0); qt.w = (float)(s/2.0); s = 0.5/s; - qt.x = (float)((tfm[2][1] - tfm[1][2]) * s); - qt.y = (float)((tfm[0][2] - tfm[2][0]) * s); - qt.z = (float)((tfm[1][0] - tfm[0][1]) * s); + qt.x = (float)((double)(tfm[2][1] - tfm[1][2]) * s); + qt.y = (float)((double)(tfm[0][2] - tfm[2][0]) * s); + qt.z = (float)((double)(tfm[1][0] - tfm[0][1]) * s); } else { int i = 0; @@ -181,16 +181,16 @@ static float4 transform_to_quat(const Transform& tfm) int j = (i + 1)%3; int k = (j + 1)%3; - double s = sqrt((tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0); + double s = sqrt((double)(tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0); double q[3]; q[i] = s * 0.5; if(s != 0.0) s = 0.5/s; - double w = (tfm[k][j] - tfm[j][k]) * s; - q[j] = (tfm[j][i] + tfm[i][j]) * s; - q[k] = (tfm[k][i] + tfm[i][k]) * s; + double w = (double)(tfm[k][j] - tfm[j][k]) * s; + q[j] = (double)(tfm[j][i] + tfm[i][j]) * s; + q[k] = (double)(tfm[k][i] + tfm[i][k]) * s; qt.x = (float)q[0]; qt.y = (float)q[1]; -- cgit v1.2.3 From c6cffe98fa5eb6108956d484596153d214687e67 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 Jun 2012 18:20:40 +0000 Subject: code cleanup: removed/renamed shadow & duplicate variable definitions. --- intern/cycles/blender/blender_mesh.cpp | 5 +--- intern/cycles/bvh/bvh_params.h | 6 ++--- intern/cycles/device/device_opencl.cpp | 2 -- intern/cycles/render/nodes.h | 2 +- intern/cycles/render/svm.cpp | 6 ++--- intern/cycles/subd/subd_build.cpp | 6 ++--- intern/cycles/subd/subd_dice.cpp | 16 +++++------ intern/cycles/subd/subd_split.cpp | 44 +++++++++++++++---------------- source/blender/makesrna/intern/makesrna.c | 4 +-- 9 files changed, 43 insertions(+), 48 deletions(-) diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index f9d26c40a74..f3266435040 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -82,7 +82,6 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< loc = loc*size - make_float3(0.5f, 0.5f, 0.5f); float3 *fdata = attr->data_float3(); - BL::Mesh::vertices_iterator v; size_t i = 0; for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) @@ -212,8 +211,6 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated) BL::Object::material_slots_iterator slot; for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { - BL::Material material_override = render_layer.material_override; - if(material_override) find_shader(material_override, used_shaders, scene->default_surface); else @@ -321,7 +318,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion) AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST; Attribute *attr_M = mesh->attributes.add(std); float3 *M = attr_M->data_float3(); - size_t i = 0, size = mesh->verts.size(); + size_t i = 0; for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < size; ++v, M++, i++) *M = get_float3(v->co()); diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 0cf5e905fea..a78496d841d 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -98,11 +98,11 @@ class BVHReference public: __forceinline BVHReference() {} - __forceinline BVHReference(const BoundBox& bounds_, int prim_index, int prim_object) + __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_) : rbounds(bounds_) { - rbounds.min.w = __int_as_float(prim_index); - rbounds.max.w = __int_as_float(prim_object); + rbounds.min.w = __int_as_float(prim_index_); + rbounds.max.w = __int_as_float(prim_object_); } __forceinline const BoundBox& bounds() const { return rbounds; } diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index c979065d23a..13ebeff70d2 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -680,8 +680,6 @@ public: else tasks.push_back(maintask); - DeviceTask task; - foreach(DeviceTask& task, tasks) { if(task.type == DeviceTask::TONEMAP) tonemap(task); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 650758a6113..eb9effc2658 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -55,7 +55,7 @@ public: class TextureNode : public ShaderNode { public: - TextureNode(const char *name) : ShaderNode(name) {} + TextureNode(const char *name_) : ShaderNode(name_) {} TextureMapping tex_mapping; }; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index e160f1c93af..844ce01569f 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -597,10 +597,10 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty memset(&active_stack, 0, sizeof(active_stack)); svm_nodes.clear(); - foreach(ShaderNode *node, graph->nodes) { - foreach(ShaderInput *input, node->inputs) + foreach(ShaderNode *node_iter, graph->nodes) { + foreach(ShaderInput *input, node_iter->inputs) input->stack_offset = SVM_STACK_INVALID; - foreach(ShaderOutput *output, node->outputs) + foreach(ShaderOutput *output, node_iter->outputs) output->stack_offset = SVM_STACK_INVALID; } diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp index 07f89b2a371..c8181838ec3 100644 --- a/intern/cycles/subd/subd_build.cpp +++ b/intern/cycles/subd/subd_build.cpp @@ -314,7 +314,7 @@ void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *s stencil->get(eid1) = stencil->get(cid); stencil->get(eid2) = stencil->get(cid); - int j = 0; + j = 0; for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), j++) { SubdEdge *edge = eit.current(); assert(vert->co == edge->from()->co); @@ -402,8 +402,8 @@ void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStenci int idx2 = interior2Indices[primitiveOffset+v]; int i = 0; - for(SubdFace::EdgeIterator it(face->edges(edge)); !it.isDone(); it.advance(), i++) { - SubdVert *vert = it.current()->from(); + for(SubdFace::EdgeIterator it_sub(face->edges(edge)); !it_sub.isDone(); it_sub.advance(), i++) { + SubdVert *vert = it_sub.current()->from(); stencil->get(idx1, vert) += weights1[i]; stencil->get(idx2, vert) += weights2[i]; } diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp index 583abb2b58a..6920df9954c 100644 --- a/intern/cycles/subd/subd_dice.cpp +++ b/intern/cycles/subd/subd_dice.cpp @@ -388,13 +388,13 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) for(m = M-2; m > 0; m -= 2) { vector inner_u, inner_v, inner_w; - float t = m/(float)M; + const float t0 = m / (float)M; float2 center = make_float2(1.0f/3.0f, 1.0f/3.0f); /* 3 corner vertices */ - float2 p_u = interp(center, make_float2(1.0f, 0.0f), t); - float2 p_v = interp(center, make_float2(0.0f, 1.0f), t); - float2 p_w = interp(center, make_float2(0.0f, 0.0f), t); + float2 p_u = interp(center, make_float2(1.0f, 0.0f), t0); + float2 p_v = interp(center, make_float2(0.0f, 1.0f), t0); + float2 p_w = interp(center, make_float2(0.0f, 0.0f), t0); int corner_u = add_vert(sub, p_u); int corner_v = add_vert(sub, p_v); @@ -407,11 +407,11 @@ void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) for(int i = 1; i < m; i++) { /* add vertices between corners */ - float t = i/(float)m; + const float t1 = i / (float)m; - inner_u.push_back(add_vert(sub, interp(p_v, p_w, t))); - inner_v.push_back(add_vert(sub, interp(p_w, p_u, t))); - inner_w.push_back(add_vert(sub, interp(p_u, p_v, t))); + inner_u.push_back(add_vert(sub, interp(p_v, p_w, t1))); + inner_v.push_back(add_vert(sub, interp(p_w, p_u, t1))); + inner_w.push_back(add_vert(sub, interp(p_u, p_v, t1))); } inner_u.push_back(corner_w); diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index f0b87200f08..074c82a2348 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -248,19 +248,19 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth) { - TriangleDice::SubPatch sub; - TriangleDice::EdgeFactors ef; + TriangleDice::SubPatch sub_split; + TriangleDice::EdgeFactors ef_split; - sub.patch = patch; - sub.Pu = make_float2(1.0f, 0.0f); - sub.Pv = make_float2(0.0f, 1.0f); - sub.Pw = make_float2(0.0f, 0.0f); + sub_split.patch = patch; + sub_split.Pu = make_float2(1.0f, 0.0f); + sub_split.Pv = make_float2(0.0f, 1.0f); + sub_split.Pw = make_float2(0.0f, 0.0f); - ef.tu = T(patch, sub.Pv, sub.Pw); - ef.tv = T(patch, sub.Pw, sub.Pu); - ef.tw = T(patch, sub.Pu, sub.Pv); + ef_split.tu = T(patch, sub_split.Pv, sub_split.Pw); + ef_split.tv = T(patch, sub_split.Pw, sub_split.Pu); + ef_split.tw = T(patch, sub_split.Pu, sub_split.Pv); - split(sub, ef); + split(sub_split, ef_split); TriangleDice dice(mesh, shader, smooth, dicing_rate); dice.camera = camera; @@ -286,21 +286,21 @@ void DiagSplit::split_triangle(Mesh *mesh, Patch *patch, int shader, bool smooth void DiagSplit::split_quad(Mesh *mesh, Patch *patch, int shader, bool smooth) { - QuadDice::SubPatch sub; - QuadDice::EdgeFactors ef; + QuadDice::SubPatch sub_split; + QuadDice::EdgeFactors ef_split; - sub.patch = patch; - sub.P00 = make_float2(0.0f, 0.0f); - sub.P10 = make_float2(1.0f, 0.0f); - sub.P01 = make_float2(0.0f, 1.0f); - sub.P11 = make_float2(1.0f, 1.0f); + sub_split.patch = patch; + sub_split.P00 = make_float2(0.0f, 0.0f); + sub_split.P10 = make_float2(1.0f, 0.0f); + sub_split.P01 = make_float2(0.0f, 1.0f); + sub_split.P11 = make_float2(1.0f, 1.0f); - ef.tu0 = T(patch, sub.P00, sub.P10); - ef.tu1 = T(patch, sub.P01, sub.P11); - ef.tv0 = T(patch, sub.P00, sub.P01); - ef.tv1 = T(patch, sub.P10, sub.P11); + ef_split.tu0 = T(patch, sub_split.P00, sub_split.P10); + ef_split.tu1 = T(patch, sub_split.P01, sub_split.P11); + ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01); + ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11); - split(sub, ef); + split(sub_split, ef_split); QuadDice dice(mesh, shader, smooth, dicing_rate); dice.camera = camera; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 3741d53c378..9cab08cbc34 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2961,12 +2961,12 @@ static void rna_generate_header_cpp(BlenderRNA *brna, FILE *f) fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); fprintf(f, "public:\n"); - fprintf(f, "\t%s(const PointerRNA& ptr) :\n\t\t%s(ptr)", srna->identifier, + fprintf(f, "\t%s(const PointerRNA& ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); for (dp = ds->cont.properties.first; dp; dp = dp->next) if (!(dp->prop->flag & (PROP_IDPROPERTY | PROP_BUILTIN))) if (dp->prop->type == PROP_COLLECTION) - fprintf(f, ",\n\t\t%s(ptr)", dp->prop->identifier); + fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); fprintf(f, "\n\t\t{}\n\n"); for (dp = ds->cont.properties.first; dp; dp = dp->next) -- cgit v1.2.3 From 2c1abe1f5861330315a1fc58e7dfe298b8356449 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 Jun 2012 18:56:12 +0000 Subject: style cleanup: assignment & indentation. --- intern/cycles/app/cycles_test.cpp | 8 +- intern/cycles/blender/blender_camera.cpp | 12 +- intern/cycles/blender/blender_mesh.cpp | 4 +- intern/cycles/blender/blender_particles.cpp | 2 +- intern/cycles/blender/blender_python.cpp | 5 +- intern/cycles/blender/blender_session.cpp | 7 +- intern/cycles/blender/blender_shader.cpp | 2 + intern/cycles/blender/blender_sync.cpp | 7 +- intern/cycles/bvh/bvh_node.cpp | 6 +- intern/cycles/kernel/kernel_differential.h | 6 +- intern/cycles/kernel/kernel_path.h | 5 +- intern/cycles/kernel/svm/bsdf.h | 28 +- intern/cycles/kernel/svm/svm_gradient.h | 6 +- intern/cycles/kernel/svm/svm_magic.h | 18 +- intern/cycles/kernel/svm/svm_mix.h | 16 +- intern/cycles/kernel/svm/svm_noise.h | 8 +- intern/cycles/kernel/svm/svm_texture.h | 2 +- intern/cycles/kernel/svm/svm_voronoi.h | 2 +- intern/cycles/kernel/svm/svm_wave.h | 4 +- intern/cycles/render/attribute.cpp | 10 +- intern/cycles/render/buffers.cpp | 4 +- intern/cycles/render/camera.cpp | 2 +- intern/cycles/render/camera.h | 2 +- intern/cycles/render/filter.cpp | 6 +- intern/cycles/render/nodes.h | 2 +- intern/cycles/util/util_cuda.h | 428 ++++++++++++++-------------- intern/cycles/util/util_hash.h | 16 +- intern/cycles/util/util_md5.cpp | 2 +- intern/cycles/util/util_md5.h | 8 +- intern/cycles/util/util_opencl.cpp | 364 +++++++++++------------ intern/cycles/util/util_opencl.h | 4 +- intern/cycles/util/util_view.cpp | 2 +- 32 files changed, 507 insertions(+), 491 deletions(-) diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index 0b8853d7036..f5890998adc 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -172,8 +172,8 @@ static void display() static void resize(int width, int height) { - options.width= width; - options.height= height; + options.width = width; + options.height = height; if(options.session) options.session->reset(session_buffer_params(), options.session_params.samples); @@ -197,8 +197,8 @@ static int files_parse(int argc, const char *argv[]) static void options_parse(int argc, const char **argv) { - options.width= 0; - options.height= 0; + options.width = 0; + options.height = 0; options.filepath = ""; options.session = NULL; options.quiet = false; diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index cffc533f87b..122d0bd7c17 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -222,14 +222,14 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, } if(horizontal_fit) { - *aspectratio= xratio/yratio; - xaspect= *aspectratio; - yaspect= 1.0f; + *aspectratio = xratio/yratio; + xaspect = *aspectratio; + yaspect = 1.0f; } else { - *aspectratio= yratio/xratio; - xaspect= 1.0f; - yaspect= *aspectratio; + *aspectratio = yratio/xratio; + xaspect = 1.0f; + yaspect = *aspectratio; } /* modify aspect for orthographic scale */ diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index f3266435040..16e4ceded89 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -46,7 +46,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< float3 *N = attr_N->data_float3(); for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N) - *N= get_float3(v->normal()); + *N = get_float3(v->normal()); /* create faces */ BL::Mesh::tessfaces_iterator f; @@ -175,7 +175,7 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) { int4 vi = get_int4(f->vertices_raw()); - int n= (vi[3] == 0)? 3: 4; + int n = (vi[3] == 0) ? 3: 4; //int shader = used_shaders[f->material_index()]; if(n == 4) diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index 2b19009989a..f591aaa6d83 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -145,7 +145,7 @@ void BlenderSync::sync_particles(Object *ob, BL::Object b_ob) for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { if (use_particle_system(*b_psys)) { BL::ParticleSystem::particles_iterator b_pa; - for(b_psys->particles.begin(b_pa), index=0; b_pa != b_psys->particles.end(); ++b_pa, ++index) { + for(b_psys->particles.begin(b_pa), index = 0; b_pa != b_psys->particles.end(); ++b_pa, ++index) { if(use_particle(*b_pa)) { Particle pa; diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 6e892095387..4560c2f8543 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -193,7 +193,8 @@ CCLDeviceInfo *compute_device_list(DeviceType type) foreach(DeviceInfo& info, devices) { if(info.type == type || - (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) { + (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) + { CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++}; device_list.push_back(cinfo); } @@ -214,7 +215,7 @@ CCL_NAMESPACE_END void *CCL_python_module_init() { - PyObject *mod= PyModule_Create(&ccl::module); + PyObject *mod = PyModule_Create(&ccl::module); #ifdef WITH_OSL PyModule_AddObject(mod, "with_osl", Py_True); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index be0c2686713..12d7d00fb61 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -83,8 +83,8 @@ void BlenderSession::create_session() SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); /* reset status/progress */ - last_status= ""; - last_progress= -1.0f; + last_status = ""; + last_progress = -1.0f; /* create scene */ scene = new Scene(scene_params); @@ -292,7 +292,8 @@ void BlenderSession::synchronize() SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); if(session->params.modified(session_params) || - scene->params.modified(scene_params)) { + scene->params.modified(scene_params)) + { free_session(); create_session(); session->start(); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index f9331fc1b14..35fe4c67673 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -784,7 +784,9 @@ void BlenderSync::sync_lamps() if(b_lamp->type() == BL::Lamp::type_POINT || b_lamp->type() == BL::Lamp::type_SPOT || b_lamp->type() == BL::Lamp::type_AREA) + { strength = 100.0f; + } closure = graph->add(new EmissionNode()); closure->input("Color")->value = get_float3(b_lamp->color()); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index a9714d6d72f..13040e551bd 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -105,10 +105,13 @@ bool BlenderSync::sync_recalc() BL::BlendData::worlds_iterator b_world; - for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) + for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) { if(world_map == b_world->ptr.data && - (b_world->is_updated() || (b_world->node_tree() && b_world->node_tree().is_updated()))) + (b_world->is_updated() || (b_world->node_tree() && b_world->node_tree().is_updated()))) + { world_recalc = true; + } + } bool recalc = shader_map.has_recalc() || diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp index 4edfb4b70a4..7cc9bd333b0 100644 --- a/intern/cycles/bvh/bvh_node.cpp +++ b/intern/cycles/bvh/bvh_node.cpp @@ -52,7 +52,7 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const } if(!is_leaf()) - for(int i=0;igetSubtreeSize(stat); return cnt; @@ -60,7 +60,7 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const void BVHNode::deleteSubtree() { - for(int i=0;ideleteSubtree(); @@ -71,7 +71,7 @@ float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) cons { float SAH = probability * p.cost(num_children(), num_triangles()); - for(int i=0;icomputeSubtreeSAHCost(p, probability * child->m_bounds.safe_area()/m_bounds.safe_area()); } diff --git a/intern/cycles/kernel/kernel_differential.h b/intern/cycles/kernel/kernel_differential.h index 5b4290a7722..04027523ea5 100644 --- a/intern/cycles/kernel/kernel_differential.h +++ b/intern/cycles/kernel/kernel_differential.h @@ -49,9 +49,9 @@ __device void differential_dudv(differential *du, differential *dv, float3 dPdu, * mainly used for differentials of arbitrary mesh attributes. */ /* find most stable axis to project to 2D */ - float xn= fabsf(Ng.x); - float yn= fabsf(Ng.y); - float zn= fabsf(Ng.z); + float xn = fabsf(Ng.x); + float yn = fabsf(Ng.y); + float zn = fabsf(Ng.z); if(zn < xn || zn < yn) { if(yn < xn || yn < zn) { diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 16fd0499b00..8dbf66c108c 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -137,9 +137,12 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) || (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) || (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce)) + { return 0.0f; - else if(state->bounce <= kernel_data.integrator.min_bounce) + } + else if(state->bounce <= kernel_data.integrator.min_bounce) { return 1.0f; + } } /* probalistic termination */ diff --git a/intern/cycles/kernel/svm/bsdf.h b/intern/cycles/kernel/svm/bsdf.h index ba78a93f54f..1a90eab0cd1 100644 --- a/intern/cycles/kernel/svm/bsdf.h +++ b/intern/cycles/kernel/svm/bsdf.h @@ -47,7 +47,7 @@ __device float fresnel_dielectric(float eta, const float3 N, float cos = dot(N, I), neta; float3 Nn; // compute reflection - *R =(2 * cos)* N - I; + *R = (2 * cos)* N - I; #ifdef __RAY_DIFFERENTIALS__ *dRdx = (2 * dot(N, dIdx)) * N - dIdx; *dRdy = (2 * dot(N, dIdy)) * N - dIdy; @@ -65,18 +65,18 @@ __device float fresnel_dielectric(float eta, const float3 N, Nn = -N; *is_inside = true; } - *R =(2 * cos)* Nn - I; + *R = (2 * cos)* Nn - I; float arg = 1 -(neta * neta *(1 -(cos * cos))); if(arg < 0) { - *T= make_float3(0.0f, 0.0f, 0.0f); + *T = make_float3(0.0f, 0.0f, 0.0f); #ifdef __RAY_DIFFERENTIALS__ - *dTdx= make_float3(0.0f, 0.0f, 0.0f); - *dTdy= make_float3(0.0f, 0.0f, 0.0f); + *dTdx = make_float3(0.0f, 0.0f, 0.0f); + *dTdy = make_float3(0.0f, 0.0f, 0.0f); #endif return 1; // total internal reflection } else { float dnp = sqrtf(arg); - float nK =(neta * cos)- dnp; + float nK = (neta * cos)- dnp; *T = -(neta * I)+(nK * Nn); #ifdef __RAY_DIFFERENTIALS__ *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn; @@ -85,8 +85,8 @@ __device float fresnel_dielectric(float eta, const float3 N, // compute Fresnel terms float cosTheta1 = cos; // N.R float cosTheta2 = -dot(Nn, *T); - float pPara =(cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2); - float pPerp =(eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2); + float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2); + float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2); return 0.5f * (pPara * pPara + pPerp * pPerp); } } @@ -99,8 +99,8 @@ __device float fresnel_dielectric_cos(float cosi, float eta) float g = eta * eta - 1 + c * c; if(g > 0) { g = sqrtf(g); - float A =(g - c)/(g + c); - float B =(c *(g + c)- 1)/(c *(g - c)+ 1); + float A = (g - c)/(g + c); + float B = (c *(g + c)- 1)/(c *(g - c)+ 1); return 0.5f * A * A *(1 + B * B); } return 1.0f; // TIR(no refracted component) @@ -110,10 +110,10 @@ __device float fresnel_conductor(float cosi, float eta, float k) { float tmp_f = eta * eta + k * k; float tmp = tmp_f * cosi * cosi; - float Rparl2 =(tmp -(2.0f * eta * cosi)+ 1)/ - (tmp +(2.0f * eta * cosi)+ 1); - float Rperp2 =(tmp_f -(2.0f * eta * cosi)+ cosi * cosi)/ - (tmp_f +(2.0f * eta * cosi)+ cosi * cosi); + float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/ + (tmp + (2.0f * eta * cosi) + 1); + float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/ + (tmp_f + (2.0f * eta * cosi) + cosi * cosi); return(Rparl2 + Rperp2) * 0.5f; } diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h index b29abed4edc..7fad1175c49 100644 --- a/intern/cycles/kernel/svm/svm_gradient.h +++ b/intern/cycles/kernel/svm/svm_gradient.h @@ -24,9 +24,9 @@ __device float svm_gradient(float3 p, NodeGradientType type) { float x, y, z; - x= p.x; - y= p.y; - z= p.z; + x = p.x; + y = p.y; + z = p.z; if(type == NODE_BLEND_LINEAR) { return x; diff --git a/intern/cycles/kernel/svm/svm_magic.h b/intern/cycles/kernel/svm/svm_magic.h index 65d37937e1e..fdded813784 100644 --- a/intern/cycles/kernel/svm/svm_magic.h +++ b/intern/cycles/kernel/svm/svm_magic.h @@ -34,39 +34,39 @@ __device_noinline float3 svm_magic(float3 p, int n, float distortion) y *= distortion; if(n > 1) { - x= cosf(x-y-z); + x = cosf(x-y-z); x *= distortion; if(n > 2) { - z= sinf(-x-y-z); + z = sinf(-x-y-z); z *= distortion; if(n > 3) { - x= -cosf(-x+y-z); + x = -cosf(-x+y-z); x *= distortion; if(n > 4) { - y= -sinf(-x+y+z); + y = -sinf(-x+y+z); y *= distortion; if(n > 5) { - y= -cosf(-x+y+z); + y = -cosf(-x+y+z); y *= distortion; if(n > 6) { - x= cosf(x+y+z); + x = cosf(x+y+z); x *= distortion; if(n > 7) { - z= sinf(x+y-z); + z = sinf(x+y-z); z *= distortion; if(n > 8) { - x= -cosf(-x-y+z); + x = -cosf(-x-y+z); x *= distortion; if(n > 9) { - y= -sinf(x-y+z); + y = -sinf(x-y+z); y *= distortion; } } diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h index e2274a2e691..6b455e713c2 100644 --- a/intern/cycles/kernel/svm/svm_mix.h +++ b/intern/cycles/kernel/svm/svm_mix.h @@ -248,8 +248,8 @@ __device float3 svm_mix_soft(float t, float3 col1, float3 col2) { float tm = 1.0f - t; - float3 one= make_float3(1.0f, 1.0f, 1.0f); - float3 scr= one - (one - col2)*(one - col1); + float3 one = make_float3(1.0f, 1.0f, 1.0f); + float3 scr = one - (one - col2)*(one - col1); return tm*col1 + t*((one - col1)*col2*col1 + col1*scr); } @@ -259,19 +259,19 @@ __device float3 svm_mix_linear(float t, float3 col1, float3 col2) float3 outcol = col1; if(col2.x > 0.5f) - outcol.x= col1.x + t*(2.0f*(col2.x - 0.5f)); + outcol.x = col1.x + t*(2.0f*(col2.x - 0.5f)); else - outcol.x= col1.x + t*(2.0f*(col2.x) - 1.0f); + outcol.x = col1.x + t*(2.0f*(col2.x) - 1.0f); if(col2.y > 0.5f) - outcol.y= col1.y + t*(2.0f*(col2.y - 0.5f)); + outcol.y = col1.y + t*(2.0f*(col2.y - 0.5f)); else - outcol.y= col1.y + t*(2.0f*(col2.y) - 1.0f); + outcol.y = col1.y + t*(2.0f*(col2.y) - 1.0f); if(col2.z > 0.5f) - outcol.z= col1.z + t*(2.0f*(col2.z - 0.5f)); + outcol.z = col1.z + t*(2.0f*(col2.z - 0.5f)); else - outcol.z= col1.z + t*(2.0f*(col2.z) - 1.0f); + outcol.z = col1.z + t*(2.0f*(col2.z) - 1.0f); return outcol; } diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h index 22f3187943c..dfaf43acbd4 100644 --- a/intern/cycles/kernel/svm/svm_noise.h +++ b/intern/cycles/kernel/svm/svm_noise.h @@ -84,9 +84,9 @@ __device uint phash(int kx, int ky, int kz, int3 p) __device float floorfrac(float x, int* i) { - float f = floorf(x); - *i = (int)f; - return x - f; + float f = floorf(x); + *i = (int)f; + return x - f; } __device float fade(float t) @@ -96,7 +96,7 @@ __device float fade(float t) __device float nerp(float t, float a, float b) { - return (1.0f - t) * a + t * b; + return (1.0f - t) * a + t * b; } __device float grad(int hash, float x, float y, float z) diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index d12a85a5402..6c22d98e0df 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -221,7 +221,7 @@ __device_noinline float noise_turbulence(float3 p, NodeNoiseBasis basis, float o int i, n; octaves = clamp(octaves, 0.0f, 16.0f); - n= (int)octaves; + n = (int)octaves; for(i = 0; i <= n; i++) { float t = noise_basis(fscale*p, basis); diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h index f5ee7851a51..7e7bd970320 100644 --- a/intern/cycles/kernel/svm/svm_voronoi.h +++ b/intern/cycles/kernel/svm/svm_voronoi.h @@ -38,7 +38,7 @@ __device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float scale, } else { color = cellnoise_color(pa[0]); - fac= average(color); + fac = average(color); } return make_float4(color.x, color.y, color.z, fac); diff --git a/intern/cycles/kernel/svm/svm_wave.h b/intern/cycles/kernel/svm/svm_wave.h index 7050bbe7f00..d2d808e4063 100644 --- a/intern/cycles/kernel/svm/svm_wave.h +++ b/intern/cycles/kernel/svm/svm_wave.h @@ -27,9 +27,9 @@ __device_noinline float svm_wave(NodeWaveType type, float3 p, float scale, float p *= scale; if(type == NODE_WAVE_BANDS) - n= (p.x + p.y + p.z)*10.0f; + n = (p.x + p.y + p.z) * 10.0f; else /* if(type == NODE_WAVE_RINGS) */ - n= len(p)*20.0f; + n = len(p) * 20.0f; if(distortion != 0.0f) n += distortion * noise_turbulence(p*dscale, NODE_NOISE_PERLIN, detail, 0); diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index c1a089cc872..5c7966d6d96 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -74,10 +74,13 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b) if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal) + { if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal) + { return true; - + } + } return false; } @@ -286,10 +289,13 @@ bool AttributeRequestSet::modified(const AttributeRequestSet& other) for(size_t j = 0; j < requests.size() && !found; j++) if(requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) + { found = true; + } - if(!found) + if(!found) { return true; + } } return false; diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index a7fd47c94cf..a79a3591e0f 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -117,8 +117,8 @@ void RenderBuffers::reset(Device *device, BufferParams& params_) uint *init_state = rng_state.resize(params.width, params.height); int x, y, width = params.width, height = params.height; - for(x=0; xmem_alloc(rng_state, MEM_READ_WRITE); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index ed239074cd4..55a0f23f8d0 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -199,7 +199,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->bladesrotation = bladesrotation; /* motion blur */ - kcam->shuttertime= (need_motion == Scene::MOTION_BLUR)? shuttertime: 0.0f; + kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f; /* type */ kcam->type = type; diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 647423d88ba..d2a3cce1817 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -78,7 +78,7 @@ public: bool use_motion; /* computed camera parameters */ - Transform screentoworld; + Transform screentoworld; Transform rastertoworld; Transform ndctoworld; Transform rastertocamera; diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp index 9bcf57b5a27..0bd4fb4d579 100644 --- a/intern/cycles/render/filter.cpp +++ b/intern/cycles/render/filter.cpp @@ -73,17 +73,17 @@ static vector filter_table(FilterType type, float width) /* compute cumulative distribution function */ filter_table_cdf[0] = 0.0f; - for(i=0; i +# define WIN32_LEAN_AND_MEAN +# define VC_EXTRALEAN +# include - typedef HMODULE CLCC_DYNLIB_HANDLE; + typedef HMODULE CLCC_DYNLIB_HANDLE; - #define CLCC_DYNLIB_OPEN LoadLibrary - #define CLCC_DYNLIB_CLOSE FreeLibrary - #define CLCC_DYNLIB_IMPORT GetProcAddress +# define CLCC_DYNLIB_OPEN LoadLibrary +# define CLCC_DYNLIB_CLOSE FreeLibrary +# define CLCC_DYNLIB_IMPORT GetProcAddress #else - #include - - typedef void* CLCC_DYNLIB_HANDLE; +# include - #define CLCC_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL) - #define CLCC_DYNLIB_CLOSE dlclose - #define CLCC_DYNLIB_IMPORT dlsym + typedef void* CLCC_DYNLIB_HANDLE; + +# define CLCC_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL) +# define CLCC_DYNLIB_CLOSE dlclose +# define CLCC_DYNLIB_IMPORT dlsym #endif #else - //typedef implementation_defined CLCC_DYNLIB_HANDLE; - //#define CLCC_DYNLIB_OPEN(path) implementation_defined - //#define CLCC_DYNLIB_CLOSE implementation_defined - //#define CLCC_DYNLIB_IMPORT implementation_defined +// typedef implementation_defined CLCC_DYNLIB_HANDLE; +//# define CLCC_DYNLIB_OPEN(path) implementation_defined +//# define CLCC_DYNLIB_CLOSE implementation_defined +//# define CLCC_DYNLIB_IMPORT implementation_defined #endif CCL_NAMESPACE_BEGIN @@ -117,12 +117,12 @@ PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL; //! \brief Unloads OpenCL dynamic library, should not be called directly static void clewExit(void) { - if (module != NULL) - { - // Ignore errors - CLCC_DYNLIB_CLOSE(module); - module = NULL; - } + if (module != NULL) + { + // Ignore errors + CLCC_DYNLIB_CLOSE(module); + module = NULL; + } } //! \param path path to dynamic library to load @@ -138,186 +138,186 @@ int clLibraryInit() #else const char *path = "libOpenCL.so"; #endif - int error = 0; + int error = 0; - // Check if already initialized - if (module != NULL) - { - return 1; - } + // Check if already initialized + if (module != NULL) + { + return 1; + } - // Load library - module = CLCC_DYNLIB_OPEN(path); + // Load library + module = CLCC_DYNLIB_OPEN(path); - // Check for errors - if (module == NULL) - { - return 0; - } + // Check for errors + if (module == NULL) + { + return 0; + } - // Set unloading - error = atexit(clewExit); + // Set unloading + error = atexit(clewExit); - if (error) - { - // Failure queing atexit, shutdown with error - CLCC_DYNLIB_CLOSE(module); - module = NULL; + if (error) + { + // Failure queing atexit, shutdown with error + CLCC_DYNLIB_CLOSE(module); + module = NULL; - return 0; - } + return 0; + } - // Determine function entry-points - __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs"); - __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo"); - __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs"); - __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo"); - __clewCreateContext = (PFNCLCREATECONTEXT )CLCC_DYNLIB_IMPORT(module, "clCreateContext"); - __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType"); - __clewRetainContext = (PFNCLRETAINCONTEXT )CLCC_DYNLIB_IMPORT(module, "clRetainContext"); - __clewReleaseContext = (PFNCLRELEASECONTEXT )CLCC_DYNLIB_IMPORT(module, "clReleaseContext"); - __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo"); - __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue"); - __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue"); - __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue"); - __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo"); - __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty"); - __clewCreateBuffer = (PFNCLCREATEBUFFER )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer"); - __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D"); - __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D"); - __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject"); - __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject"); - __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats"); - __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo"); - __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo"); - __clewCreateSampler = (PFNCLCREATESAMPLER )CLCC_DYNLIB_IMPORT(module, "clCreateSampler"); - __clewRetainSampler = (PFNCLRETAINSAMPLER )CLCC_DYNLIB_IMPORT(module, "clRetainSampler"); - __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler"); - __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo"); - __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource"); - __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary"); - __clewRetainProgram = (PFNCLRETAINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clRetainProgram"); - __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram"); - __clewBuildProgram = (PFNCLBUILDPROGRAM )CLCC_DYNLIB_IMPORT(module, "clBuildProgram"); - __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler"); - __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo"); - __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo"); - __clewCreateKernel = (PFNCLCREATEKERNEL )CLCC_DYNLIB_IMPORT(module, "clCreateKernel"); - __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram"); - __clewRetainKernel = (PFNCLRETAINKERNEL )CLCC_DYNLIB_IMPORT(module, "clRetainKernel"); - __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel"); - __clewSetKernelArg = (PFNCLSETKERNELARG )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg"); - __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo"); - __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo"); - __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents"); - __clewGetEventInfo = (PFNCLGETEVENTINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo"); - __clewRetainEvent = (PFNCLRETAINEVENT )CLCC_DYNLIB_IMPORT(module, "clRetainEvent"); - __clewReleaseEvent = (PFNCLRELEASEEVENT )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent"); - __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo"); - __clewFlush = (PFNCLFLUSH )CLCC_DYNLIB_IMPORT(module, "clFlush"); - __clewFinish = (PFNCLFINISH )CLCC_DYNLIB_IMPORT(module, "clFinish"); - __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer"); - __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer"); - __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer"); - __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage"); - __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage"); - __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage"); - __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer"); - __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage"); - __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer"); - __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage"); - __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject"); - __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel"); - __clewEnqueueTask = (PFNCLENQUEUETASK )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask"); - __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel"); - __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker"); - __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents"); - __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier"); - __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress"); + // Determine function entry-points + __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs"); + __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo"); + __clewGetDeviceIDs = (PFNCLGETDEVICEIDS )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs"); + __clewGetDeviceInfo = (PFNCLGETDEVICEINFO )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo"); + __clewCreateContext = (PFNCLCREATECONTEXT )CLCC_DYNLIB_IMPORT(module, "clCreateContext"); + __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType"); + __clewRetainContext = (PFNCLRETAINCONTEXT )CLCC_DYNLIB_IMPORT(module, "clRetainContext"); + __clewReleaseContext = (PFNCLRELEASECONTEXT )CLCC_DYNLIB_IMPORT(module, "clReleaseContext"); + __clewGetContextInfo = (PFNCLGETCONTEXTINFO )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo"); + __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue"); + __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue"); + __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue"); + __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo"); + __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty"); + __clewCreateBuffer = (PFNCLCREATEBUFFER )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer"); + __clewCreateImage2D = (PFNCLCREATEIMAGE2D )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D"); + __clewCreateImage3D = (PFNCLCREATEIMAGE3D )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D"); + __clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject"); + __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject"); + __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats"); + __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo"); + __clewGetImageInfo = (PFNCLGETIMAGEINFO )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo"); + __clewCreateSampler = (PFNCLCREATESAMPLER )CLCC_DYNLIB_IMPORT(module, "clCreateSampler"); + __clewRetainSampler = (PFNCLRETAINSAMPLER )CLCC_DYNLIB_IMPORT(module, "clRetainSampler"); + __clewReleaseSampler = (PFNCLRELEASESAMPLER )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler"); + __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo"); + __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource"); + __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary"); + __clewRetainProgram = (PFNCLRETAINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clRetainProgram"); + __clewReleaseProgram = (PFNCLRELEASEPROGRAM )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram"); + __clewBuildProgram = (PFNCLBUILDPROGRAM )CLCC_DYNLIB_IMPORT(module, "clBuildProgram"); + __clewUnloadCompiler = (PFNCLUNLOADCOMPILER )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler"); + __clewGetProgramInfo = (PFNCLGETPROGRAMINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo"); + __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo"); + __clewCreateKernel = (PFNCLCREATEKERNEL )CLCC_DYNLIB_IMPORT(module, "clCreateKernel"); + __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram"); + __clewRetainKernel = (PFNCLRETAINKERNEL )CLCC_DYNLIB_IMPORT(module, "clRetainKernel"); + __clewReleaseKernel = (PFNCLRELEASEKERNEL )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel"); + __clewSetKernelArg = (PFNCLSETKERNELARG )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg"); + __clewGetKernelInfo = (PFNCLGETKERNELINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo"); + __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo"); + __clewWaitForEvents = (PFNCLWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents"); + __clewGetEventInfo = (PFNCLGETEVENTINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo"); + __clewRetainEvent = (PFNCLRETAINEVENT )CLCC_DYNLIB_IMPORT(module, "clRetainEvent"); + __clewReleaseEvent = (PFNCLRELEASEEVENT )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent"); + __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo"); + __clewFlush = (PFNCLFLUSH )CLCC_DYNLIB_IMPORT(module, "clFlush"); + __clewFinish = (PFNCLFINISH )CLCC_DYNLIB_IMPORT(module, "clFinish"); + __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer"); + __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer"); + __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer"); + __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage"); + __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage"); + __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage"); + __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer"); + __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage"); + __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer"); + __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage"); + __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject"); + __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel"); + __clewEnqueueTask = (PFNCLENQUEUETASK )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask"); + __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel"); + __clewEnqueueMarker = (PFNCLENQUEUEMARKER )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker"); + __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents"); + __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier"); + __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress"); if(__clewGetPlatformIDs == NULL) return 0; - return 1; + return 1; } //! \param error CL error code //! \return a string representation of the error code const char *clErrorString(cl_int error) { - static const char* strings[] = - { - // Error Codes - "CL_SUCCESS" // 0 - , "CL_DEVICE_NOT_FOUND" // -1 - , "CL_DEVICE_NOT_AVAILABLE" // -2 - , "CL_COMPILER_NOT_AVAILABLE" // -3 - , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4 - , "CL_OUT_OF_RESOURCES" // -5 - , "CL_OUT_OF_HOST_MEMORY" // -6 - , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7 - , "CL_MEM_COPY_OVERLAP" // -8 - , "CL_IMAGE_FORMAT_MISMATCH" // -9 - , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10 - , "CL_BUILD_PROGRAM_FAILURE" // -11 - , "CL_MAP_FAILURE" // -12 + static const char* strings[] = + { + // Error Codes + "CL_SUCCESS" // 0 + , "CL_DEVICE_NOT_FOUND" // -1 + , "CL_DEVICE_NOT_AVAILABLE" // -2 + , "CL_COMPILER_NOT_AVAILABLE" // -3 + , "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4 + , "CL_OUT_OF_RESOURCES" // -5 + , "CL_OUT_OF_HOST_MEMORY" // -6 + , "CL_PROFILING_INFO_NOT_AVAILABLE" // -7 + , "CL_MEM_COPY_OVERLAP" // -8 + , "CL_IMAGE_FORMAT_MISMATCH" // -9 + , "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10 + , "CL_BUILD_PROGRAM_FAILURE" // -11 + , "CL_MAP_FAILURE" // -12 - , "" // -13 - , "" // -14 - , "" // -15 - , "" // -16 - , "" // -17 - , "" // -18 - , "" // -19 + , "" // -13 + , "" // -14 + , "" // -15 + , "" // -16 + , "" // -17 + , "" // -18 + , "" // -19 - , "" // -20 - , "" // -21 - , "" // -22 - , "" // -23 - , "" // -24 - , "" // -25 - , "" // -26 - , "" // -27 - , "" // -28 - , "" // -29 + , "" // -20 + , "" // -21 + , "" // -22 + , "" // -23 + , "" // -24 + , "" // -25 + , "" // -26 + , "" // -27 + , "" // -28 + , "" // -29 - , "CL_INVALID_VALUE" // -30 - , "CL_INVALID_DEVICE_TYPE" // -31 - , "CL_INVALID_PLATFORM" // -32 - , "CL_INVALID_DEVICE" // -33 - , "CL_INVALID_CONTEXT" // -34 - , "CL_INVALID_QUEUE_PROPERTIES" // -35 - , "CL_INVALID_COMMAND_QUEUE" // -36 - , "CL_INVALID_HOST_PTR" // -37 - , "CL_INVALID_MEM_OBJECT" // -38 - , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39 - , "CL_INVALID_IMAGE_SIZE" // -40 - , "CL_INVALID_SAMPLER" // -41 - , "CL_INVALID_BINARY" // -42 - , "CL_INVALID_BUILD_OPTIONS" // -43 - , "CL_INVALID_PROGRAM" // -44 - , "CL_INVALID_PROGRAM_EXECUTABLE" // -45 - , "CL_INVALID_KERNEL_NAME" // -46 - , "CL_INVALID_KERNEL_DEFINITION" // -47 - , "CL_INVALID_KERNEL" // -48 - , "CL_INVALID_ARG_INDEX" // -49 - , "CL_INVALID_ARG_VALUE" // -50 - , "CL_INVALID_ARG_SIZE" // -51 - , "CL_INVALID_KERNEL_ARGS" // -52 - , "CL_INVALID_WORK_DIMENSION" // -53 - , "CL_INVALID_WORK_GROUP_SIZE" // -54 - , "CL_INVALID_WORK_ITEM_SIZE" // -55 - , "CL_INVALID_GLOBAL_OFFSET" // -56 - , "CL_INVALID_EVENT_WAIT_LIST" // -57 - , "CL_INVALID_EVENT" // -58 - , "CL_INVALID_OPERATION" // -59 - , "CL_INVALID_GL_OBJECT" // -60 - , "CL_INVALID_BUFFER_SIZE" // -61 - , "CL_INVALID_MIP_LEVEL" // -62 - , "CL_INVALID_GLOBAL_WORK_SIZE" // -63 - }; + , "CL_INVALID_VALUE" // -30 + , "CL_INVALID_DEVICE_TYPE" // -31 + , "CL_INVALID_PLATFORM" // -32 + , "CL_INVALID_DEVICE" // -33 + , "CL_INVALID_CONTEXT" // -34 + , "CL_INVALID_QUEUE_PROPERTIES" // -35 + , "CL_INVALID_COMMAND_QUEUE" // -36 + , "CL_INVALID_HOST_PTR" // -37 + , "CL_INVALID_MEM_OBJECT" // -38 + , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39 + , "CL_INVALID_IMAGE_SIZE" // -40 + , "CL_INVALID_SAMPLER" // -41 + , "CL_INVALID_BINARY" // -42 + , "CL_INVALID_BUILD_OPTIONS" // -43 + , "CL_INVALID_PROGRAM" // -44 + , "CL_INVALID_PROGRAM_EXECUTABLE" // -45 + , "CL_INVALID_KERNEL_NAME" // -46 + , "CL_INVALID_KERNEL_DEFINITION" // -47 + , "CL_INVALID_KERNEL" // -48 + , "CL_INVALID_ARG_INDEX" // -49 + , "CL_INVALID_ARG_VALUE" // -50 + , "CL_INVALID_ARG_SIZE" // -51 + , "CL_INVALID_KERNEL_ARGS" // -52 + , "CL_INVALID_WORK_DIMENSION" // -53 + , "CL_INVALID_WORK_GROUP_SIZE" // -54 + , "CL_INVALID_WORK_ITEM_SIZE" // -55 + , "CL_INVALID_GLOBAL_OFFSET" // -56 + , "CL_INVALID_EVENT_WAIT_LIST" // -57 + , "CL_INVALID_EVENT" // -58 + , "CL_INVALID_OPERATION" // -59 + , "CL_INVALID_GL_OBJECT" // -60 + , "CL_INVALID_BUFFER_SIZE" // -61 + , "CL_INVALID_MIP_LEVEL" // -62 + , "CL_INVALID_GLOBAL_WORK_SIZE" // -63 + }; - return strings[-error]; + return strings[-error]; } CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_opencl.h b/intern/cycles/util/util_opencl.h index 907d372d3ce..5f3f1667bcc 100644 --- a/intern/cycles/util/util_opencl.h +++ b/intern/cycles/util/util_opencl.h @@ -339,8 +339,8 @@ typedef cl_uint cl_command_type; typedef cl_uint cl_profiling_info; typedef struct _cl_image_format { - cl_channel_order image_channel_order; - cl_channel_type image_channel_data_type; + cl_channel_order image_channel_order; + cl_channel_type image_channel_data_type; } cl_image_format; diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp index 0b311b0331a..328c0c97391 100644 --- a/intern/cycles/util/util_view.cpp +++ b/intern/cycles/util/util_view.cpp @@ -55,7 +55,7 @@ static void view_display_text(int x, int y, const char *text) glRasterPos3f(x, y, 0); - for(c=text; *c != '\0'; c++) + for(c = text; *c != '\0'; c++) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, *c); } -- cgit v1.2.3 From 8e7d7d5ea56c75739164b98f5fb2f97ff51d697b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 9 Jun 2012 19:57:14 +0000 Subject: code cleanup: reduce float/double promotion --- source/blender/compositor/CMakeLists.txt | 419 ++++++++++----------- .../compositor/intern/COM_ChunkOrderHotspot.cpp | 2 +- .../blender/compositor/intern/COM_MemoryBuffer.cpp | 4 +- .../operations/COM_BokehBlurOperation.cpp | 6 +- .../operations/COM_BokehImageOperation.cpp | 40 +- .../compositor/operations/COM_BoxMaskOperation.cpp | 14 +- .../operations/COM_ChangeHSVOperation.cpp | 3 +- .../operations/COM_ColorBalanceASCCDLOperation.cpp | 2 +- .../operations/COM_ColorCorrectionOperation.cpp | 30 +- .../operations/COM_ColorCurveOperation.cpp | 24 +- .../operations/COM_DifferenceMatteOperation.cpp | 12 +- .../operations/COM_DirectionalBlurOperation.cpp | 10 +- .../operations/COM_EllipseMaskOperation.cpp | 2 +- .../operations/COM_FogGlowImageOperation.cpp | 2 +- .../compositor/operations/COM_GammaOperation.cpp | 6 +- .../operations/COM_GaussianBokehBlurOperation.cpp | 10 +- .../operations/COM_GaussianXBlurOperation.cpp | 12 +- .../operations/COM_GaussianYBlurOperation.cpp | 10 +- .../COM_HueSaturationValueCorrectOperation.cpp | 4 +- .../compositor/operations/COM_MapUVOperation.cpp | 8 +- .../operations/COM_MathBaseOperation.cpp | 4 +- .../compositor/operations/COM_RotateOperation.cpp | 2 +- .../compositor/operations/COM_TonemapOperation.cpp | 60 +-- .../COM_VariableSizeBokehBlurOperation.cpp | 8 +- 24 files changed, 347 insertions(+), 347 deletions(-) diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 27bf7df8142..22f72270734 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -26,24 +26,24 @@ set(INC . + intern + nodes + operations ../blenkernel ../blenlib + ../blenlib + ../blenloader + ../imbuf ../makesdna - ../render/extern/include - ../render/intern/include ../makesrna - ../blenloader - ../blenlib + ../opencl ../windowmanager - ../imbuf - ../../../intern/guardedalloc - nodes - ../nodes/ + ../nodes ../nodes/composite ../nodes/intern - intern - operations - ../opencl + ../render/extern/include + ../render/intern/include + ../../../intern/guardedalloc ) set(SRC @@ -100,7 +100,7 @@ set(SRC operations/COM_QualityStepHelper.h operations/COM_QualityStepHelper.cpp -# Internal nodes + # Internal nodes nodes/COM_MuteNode.cpp nodes/COM_MuteNode.h nodes/COM_GroupNode.cpp @@ -108,7 +108,7 @@ set(SRC nodes/COM_SocketProxyNode.cpp nodes/COM_SocketProxyNode.h -# input nodes + # input nodes nodes/COM_RenderLayersNode.cpp nodes/COM_RenderLayersNode.h nodes/COM_ImageNode.cpp @@ -132,7 +132,7 @@ set(SRC nodes/COM_MaskNode.cpp nodes/COM_MaskNode.h -# output nodes + # output nodes nodes/COM_CompositorNode.cpp nodes/COM_CompositorNode.h nodes/COM_ViewerNode.cpp @@ -146,7 +146,7 @@ set(SRC operations/COM_CalculateMeanOperation.cpp operations/COM_CalculateMeanOperation.h -# distort nodes + # distort nodes nodes/COM_TranslateNode.cpp nodes/COM_TranslateNode.h nodes/COM_ScaleNode.cpp @@ -193,27 +193,27 @@ set(SRC nodes/COM_DefocusNode.cpp nodes/COM_DefocusNode.h -# color nodes - nodes/COM_VectorCurveNode.cpp - nodes/COM_VectorCurveNode.h - nodes/COM_ColorCurveNode.cpp - nodes/COM_ColorCurveNode.h - nodes/COM_ColorToBWNode.cpp - nodes/COM_ColorToBWNode.h - nodes/COM_ColorRampNode.cpp - nodes/COM_ColorRampNode.h - nodes/COM_MixNode.cpp - nodes/COM_MixNode.h - nodes/COM_AlphaOverNode.cpp - nodes/COM_AlphaOverNode.h - nodes/COM_ZCombineNode.cpp - nodes/COM_ZCombineNode.h - nodes/COM_BrightnessNode.cpp - nodes/COM_BrightnessNode.h - nodes/COM_ColorBalanceNode.cpp - nodes/COM_ColorBalanceNode.h - nodes/COM_InvertNode.cpp - nodes/COM_InvertNode.h + # color nodes + nodes/COM_VectorCurveNode.cpp + nodes/COM_VectorCurveNode.h + nodes/COM_ColorCurveNode.cpp + nodes/COM_ColorCurveNode.h + nodes/COM_ColorToBWNode.cpp + nodes/COM_ColorToBWNode.h + nodes/COM_ColorRampNode.cpp + nodes/COM_ColorRampNode.h + nodes/COM_MixNode.cpp + nodes/COM_MixNode.h + nodes/COM_AlphaOverNode.cpp + nodes/COM_AlphaOverNode.h + nodes/COM_ZCombineNode.cpp + nodes/COM_ZCombineNode.h + nodes/COM_BrightnessNode.cpp + nodes/COM_BrightnessNode.h + nodes/COM_ColorBalanceNode.cpp + nodes/COM_ColorBalanceNode.h + nodes/COM_InvertNode.cpp + nodes/COM_InvertNode.h nodes/COM_GammaNode.cpp nodes/COM_GammaNode.h nodes/COM_SetAlphaNode.cpp @@ -233,25 +233,25 @@ set(SRC operations/COM_TonemapOperation.cpp operations/COM_TonemapOperation.h -# converter nodes - nodes/COM_IDMaskNode.cpp - nodes/COM_IDMaskNode.h - nodes/COM_SeparateRGBANode.cpp - nodes/COM_SeparateRGBANode.h - nodes/COM_CombineRGBANode.cpp - nodes/COM_CombineRGBANode.h - nodes/COM_SeparateHSVANode.cpp - nodes/COM_SeparateHSVANode.h - nodes/COM_CombineHSVANode.cpp - nodes/COM_CombineHSVANode.h - nodes/COM_SeparateYUVANode.cpp - nodes/COM_SeparateYUVANode.h - nodes/COM_CombineYUVANode.cpp - nodes/COM_CombineYUVANode.h - nodes/COM_SeparateYCCANode.cpp - nodes/COM_SeparateYCCANode.h - nodes/COM_CombineYCCANode.cpp - nodes/COM_CombineYCCANode.h + # converter nodes + nodes/COM_IDMaskNode.cpp + nodes/COM_IDMaskNode.h + nodes/COM_SeparateRGBANode.cpp + nodes/COM_SeparateRGBANode.h + nodes/COM_CombineRGBANode.cpp + nodes/COM_CombineRGBANode.h + nodes/COM_SeparateHSVANode.cpp + nodes/COM_SeparateHSVANode.h + nodes/COM_CombineHSVANode.cpp + nodes/COM_CombineHSVANode.h + nodes/COM_SeparateYUVANode.cpp + nodes/COM_SeparateYUVANode.h + nodes/COM_CombineYUVANode.cpp + nodes/COM_CombineYUVANode.h + nodes/COM_SeparateYCCANode.cpp + nodes/COM_SeparateYCCANode.h + nodes/COM_CombineYCCANode.cpp + nodes/COM_CombineYCCANode.h nodes/COM_NormalNode.cpp nodes/COM_NormalNode.h @@ -265,7 +265,7 @@ set(SRC operations/COM_NormalizeOperation.cpp operations/COM_NormalizeOperation.h -# Filter nodes + # Filter nodes nodes/COM_BilateralBlurNode.cpp nodes/COM_BilateralBlurNode.h operations/COM_BilateralBlurOperation.cpp @@ -275,12 +275,10 @@ set(SRC operations/COM_VectorBlurOperation.cpp operations/COM_VectorBlurOperation.h - - - nodes/COM_FilterNode.cpp - nodes/COM_FilterNode.h - nodes/COM_DilateErodeNode.cpp - nodes/COM_DilateErodeNode.h + nodes/COM_FilterNode.cpp + nodes/COM_FilterNode.h + nodes/COM_DilateErodeNode.cpp + nodes/COM_DilateErodeNode.h nodes/COM_BlurNode.cpp nodes/COM_BlurNode.h nodes/COM_BokehBlurNode.cpp @@ -310,7 +308,7 @@ set(SRC operations/COM_GammaCorrectOperation.h operations/COM_GammaCorrectOperation.cpp -# Matte nodes + # Matte nodes nodes/COM_BoxMaskNode.cpp nodes/COM_BoxMaskNode.h nodes/COM_EllipseMaskNode.cpp @@ -322,50 +320,50 @@ set(SRC operations/COM_DoubleEdgeMaskOperation.cpp operations/COM_DoubleEdgeMaskOperation.h -operations/COM_ColorSpillOperation.cpp -operations/COM_ColorSpillOperation.h - operations/COM_RenderLayersBaseProg.cpp - operations/COM_RenderLayersBaseProg.h - operations/COM_RenderLayersImageProg.cpp - operations/COM_RenderLayersImageProg.h - operations/COM_RenderLayersAlphaProg.cpp - operations/COM_RenderLayersAlphaProg.h - operations/COM_RenderLayersDepthProg.cpp - operations/COM_RenderLayersDepthProg.h - operations/COM_RenderLayersNormalOperation.cpp - operations/COM_RenderLayersNormalOperation.h - operations/COM_RenderLayersSpeedOperation.cpp - operations/COM_RenderLayersSpeedOperation.h - operations/COM_RenderLayersColorOperation.cpp - operations/COM_RenderLayersColorOperation.h - operations/COM_RenderLayersUVOperation.cpp - operations/COM_RenderLayersUVOperation.h - operations/COM_RenderLayersMistOperation.cpp - operations/COM_RenderLayersMistOperation.h - operations/COM_RenderLayersObjectIndexOperation.cpp - operations/COM_RenderLayersObjectIndexOperation.h - operations/COM_RenderLayersMaterialIndexOperation.cpp - operations/COM_RenderLayersMaterialIndexOperation.h - operations/COM_RenderLayersDiffuseOperation.cpp - operations/COM_RenderLayersDiffuseOperation.h - operations/COM_RenderLayersSpecularOperation.cpp - operations/COM_RenderLayersSpecularOperation.h - operations/COM_RenderLayersShadowOperation.cpp - operations/COM_RenderLayersShadowOperation.h - operations/COM_RenderLayersAOOperation.cpp - operations/COM_RenderLayersAOOperation.h - operations/COM_RenderLayersEmitOperation.cpp - operations/COM_RenderLayersEmitOperation.h - operations/COM_RenderLayersReflectionOperation.cpp - operations/COM_RenderLayersReflectionOperation.h - operations/COM_RenderLayersRefractionOperation.cpp - operations/COM_RenderLayersRefractionOperation.h - operations/COM_RenderLayersEnvironmentOperation.cpp - operations/COM_RenderLayersEnvironmentOperation.h - operations/COM_RenderLayersIndirectOperation.cpp - operations/COM_RenderLayersIndirectOperation.h - operations/COM_RenderLayersCyclesOperation.cpp - operations/COM_RenderLayersCyclesOperation.h + operations/COM_ColorSpillOperation.cpp + operations/COM_ColorSpillOperation.h + operations/COM_RenderLayersBaseProg.cpp + operations/COM_RenderLayersBaseProg.h + operations/COM_RenderLayersImageProg.cpp + operations/COM_RenderLayersImageProg.h + operations/COM_RenderLayersAlphaProg.cpp + operations/COM_RenderLayersAlphaProg.h + operations/COM_RenderLayersDepthProg.cpp + operations/COM_RenderLayersDepthProg.h + operations/COM_RenderLayersNormalOperation.cpp + operations/COM_RenderLayersNormalOperation.h + operations/COM_RenderLayersSpeedOperation.cpp + operations/COM_RenderLayersSpeedOperation.h + operations/COM_RenderLayersColorOperation.cpp + operations/COM_RenderLayersColorOperation.h + operations/COM_RenderLayersUVOperation.cpp + operations/COM_RenderLayersUVOperation.h + operations/COM_RenderLayersMistOperation.cpp + operations/COM_RenderLayersMistOperation.h + operations/COM_RenderLayersObjectIndexOperation.cpp + operations/COM_RenderLayersObjectIndexOperation.h + operations/COM_RenderLayersMaterialIndexOperation.cpp + operations/COM_RenderLayersMaterialIndexOperation.h + operations/COM_RenderLayersDiffuseOperation.cpp + operations/COM_RenderLayersDiffuseOperation.h + operations/COM_RenderLayersSpecularOperation.cpp + operations/COM_RenderLayersSpecularOperation.h + operations/COM_RenderLayersShadowOperation.cpp + operations/COM_RenderLayersShadowOperation.h + operations/COM_RenderLayersAOOperation.cpp + operations/COM_RenderLayersAOOperation.h + operations/COM_RenderLayersEmitOperation.cpp + operations/COM_RenderLayersEmitOperation.h + operations/COM_RenderLayersReflectionOperation.cpp + operations/COM_RenderLayersReflectionOperation.h + operations/COM_RenderLayersRefractionOperation.cpp + operations/COM_RenderLayersRefractionOperation.h + operations/COM_RenderLayersEnvironmentOperation.cpp + operations/COM_RenderLayersEnvironmentOperation.h + operations/COM_RenderLayersIndirectOperation.cpp + operations/COM_RenderLayersIndirectOperation.h + operations/COM_RenderLayersCyclesOperation.cpp + operations/COM_RenderLayersCyclesOperation.h operations/COM_ImageOperation.cpp operations/COM_ImageOperation.h @@ -377,39 +375,39 @@ operations/COM_ColorSpillOperation.h operations/COM_BokehImageOperation.h - operations/COM_SocketProxyOperation.h - operations/COM_SocketProxyOperation.cpp + operations/COM_SocketProxyOperation.h + operations/COM_SocketProxyOperation.cpp - operations/COM_CompositorOperation.h - operations/COM_CompositorOperation.cpp + operations/COM_CompositorOperation.h + operations/COM_CompositorOperation.cpp operations/COM_OutputFileOperation.h operations/COM_OutputFileOperation.cpp - operations/COM_ViewerBaseOperation.h - operations/COM_ViewerBaseOperation.cpp - operations/COM_ViewerOperation.h - operations/COM_ViewerOperation.cpp - operations/COM_PreviewOperation.h - operations/COM_PreviewOperation.cpp - operations/COM_SplitViewerOperation.h - operations/COM_SplitViewerOperation.cpp - operations/COM_ConvertValueToColourProg.h - operations/COM_ConvertValueToColourProg.cpp - operations/COM_ConvertColourToValueProg.h - operations/COM_ConvertColourToValueProg.cpp - operations/COM_ConvertColorToBWOperation.h - operations/COM_ConvertColorToBWOperation.cpp - operations/COM_ConvertColorToVectorOperation.h - operations/COM_ConvertColorToVectorOperation.cpp - operations/COM_ConvertValueToVectorOperation.h - operations/COM_ConvertValueToVectorOperation.cpp - operations/COM_ConvertVectorToColorOperation.h - operations/COM_ConvertVectorToColorOperation.cpp - operations/COM_ConvertVectorToValueOperation.h - operations/COM_ConvertVectorToValueOperation.cpp -operations/COM_ConvertDepthToRadiusOperation.h -operations/COM_ConvertDepthToRadiusOperation.cpp - operations/COM_ZCombineOperation.cpp - operations/COM_ZCombineOperation.h + operations/COM_ViewerBaseOperation.h + operations/COM_ViewerBaseOperation.cpp + operations/COM_ViewerOperation.h + operations/COM_ViewerOperation.cpp + operations/COM_PreviewOperation.h + operations/COM_PreviewOperation.cpp + operations/COM_SplitViewerOperation.h + operations/COM_SplitViewerOperation.cpp + operations/COM_ConvertValueToColourProg.h + operations/COM_ConvertValueToColourProg.cpp + operations/COM_ConvertColourToValueProg.h + operations/COM_ConvertColourToValueProg.cpp + operations/COM_ConvertColorToBWOperation.h + operations/COM_ConvertColorToBWOperation.cpp + operations/COM_ConvertColorToVectorOperation.h + operations/COM_ConvertColorToVectorOperation.cpp + operations/COM_ConvertValueToVectorOperation.h + operations/COM_ConvertValueToVectorOperation.cpp + operations/COM_ConvertVectorToColorOperation.h + operations/COM_ConvertVectorToColorOperation.cpp + operations/COM_ConvertVectorToValueOperation.h + operations/COM_ConvertVectorToValueOperation.cpp + operations/COM_ConvertDepthToRadiusOperation.h + operations/COM_ConvertDepthToRadiusOperation.cpp + operations/COM_ZCombineOperation.cpp + operations/COM_ZCombineOperation.h operations/COM_ConvertRGBToYCCOperation.h operations/COM_ConvertRGBToYCCOperation.cpp @@ -470,86 +468,86 @@ operations/COM_ConvertDepthToRadiusOperation.cpp operations/COM_GammaOperation.h operations/COM_ColorCorrectionOperation.cpp operations/COM_ColorCorrectionOperation.h - operations/COM_SetValueOperation.h - operations/COM_SetValueOperation.cpp - operations/COM_SetColorOperation.h - operations/COM_SetColorOperation.cpp - operations/COM_SetVectorOperation.h - operations/COM_SetVectorOperation.cpp - - operations/COM_MixBurnOperation.h - operations/COM_MixBurnOperation.cpp - operations/COM_MixColorOperation.h - operations/COM_MixColorOperation.cpp - operations/COM_MixDarkenOperation.h - operations/COM_MixDarkenOperation.cpp - operations/COM_MixDodgeOperation.h - operations/COM_MixDodgeOperation.cpp - operations/COM_MixDifferenceOperation.h - operations/COM_MixDifferenceOperation.cpp - operations/COM_MixDivideOperation.h - operations/COM_MixDivideOperation.cpp - operations/COM_MixHueOperation.h - operations/COM_MixHueOperation.cpp - operations/COM_MixLightenOperation.h - operations/COM_MixLightenOperation.cpp - operations/COM_MixLinearLightOperation.h - operations/COM_MixLinearLightOperation.cpp - operations/COM_MixOverlayOperation.h - operations/COM_MixOverlayOperation.cpp - operations/COM_MixSaturationOperation.h - operations/COM_MixSaturationOperation.cpp - operations/COM_MixScreenOperation.h - operations/COM_MixScreenOperation.cpp - operations/COM_MixSoftLightOperation.h - operations/COM_MixSoftLightOperation.cpp - operations/COM_MixValueOperation.h - operations/COM_MixValueOperation.cpp - operations/COM_MixSubtractOperation.h - operations/COM_MixSubtractOperation.cpp + operations/COM_SetValueOperation.h + operations/COM_SetValueOperation.cpp + operations/COM_SetColorOperation.h + operations/COM_SetColorOperation.cpp + operations/COM_SetVectorOperation.h + operations/COM_SetVectorOperation.cpp + + operations/COM_MixBurnOperation.h + operations/COM_MixBurnOperation.cpp + operations/COM_MixColorOperation.h + operations/COM_MixColorOperation.cpp + operations/COM_MixDarkenOperation.h + operations/COM_MixDarkenOperation.cpp + operations/COM_MixDodgeOperation.h + operations/COM_MixDodgeOperation.cpp + operations/COM_MixDifferenceOperation.h + operations/COM_MixDifferenceOperation.cpp + operations/COM_MixDivideOperation.h + operations/COM_MixDivideOperation.cpp + operations/COM_MixHueOperation.h + operations/COM_MixHueOperation.cpp + operations/COM_MixLightenOperation.h + operations/COM_MixLightenOperation.cpp + operations/COM_MixLinearLightOperation.h + operations/COM_MixLinearLightOperation.cpp + operations/COM_MixOverlayOperation.h + operations/COM_MixOverlayOperation.cpp + operations/COM_MixSaturationOperation.h + operations/COM_MixSaturationOperation.cpp + operations/COM_MixScreenOperation.h + operations/COM_MixScreenOperation.cpp + operations/COM_MixSoftLightOperation.h + operations/COM_MixSoftLightOperation.cpp + operations/COM_MixValueOperation.h + operations/COM_MixValueOperation.cpp + operations/COM_MixSubtractOperation.h + operations/COM_MixSubtractOperation.cpp operations/COM_MathBaseOperation.h operations/COM_MathBaseOperation.cpp - operations/COM_AlphaOverMixedOperation.h - operations/COM_AlphaOverMixedOperation.cpp - operations/COM_AlphaOverPremultiplyOperation.h - operations/COM_AlphaOverPremultiplyOperation.cpp - operations/COM_AlphaOverKeyOperation.h - operations/COM_AlphaOverKeyOperation.cpp - - operations/COM_ColorBalanceLGGOperation.h - operations/COM_ColorBalanceLGGOperation.cpp - operations/COM_ColorBalanceASCCDLOperation.h - operations/COM_ColorBalanceASCCDLOperation.cpp - operations/COM_InvertOperation.cpp - operations/COM_InvertOperation.h + operations/COM_AlphaOverMixedOperation.h + operations/COM_AlphaOverMixedOperation.cpp + operations/COM_AlphaOverPremultiplyOperation.h + operations/COM_AlphaOverPremultiplyOperation.cpp + operations/COM_AlphaOverKeyOperation.h + operations/COM_AlphaOverKeyOperation.cpp + + operations/COM_ColorBalanceLGGOperation.h + operations/COM_ColorBalanceLGGOperation.cpp + operations/COM_ColorBalanceASCCDLOperation.h + operations/COM_ColorBalanceASCCDLOperation.cpp + operations/COM_InvertOperation.cpp + operations/COM_InvertOperation.h operations/COM_SetAlphaOperation.cpp operations/COM_SetAlphaOperation.h operations/COM_MapValueOperation.cpp operations/COM_MapValueOperation.h -# Distort operation - operations/COM_TranslateOperation.h - operations/COM_TranslateOperation.cpp - operations/COM_RotateOperation.h - operations/COM_RotateOperation.cpp - operations/COM_ScaleOperation.h - operations/COM_ScaleOperation.cpp - operations/COM_MapUVOperation.h - operations/COM_MapUVOperation.cpp - operations/COM_DisplaceOperation.h - operations/COM_DisplaceOperation.cpp - operations/COM_DisplaceSimpleOperation.h - operations/COM_DisplaceSimpleOperation.cpp - operations/COM_FlipOperation.h - operations/COM_FlipOperation.cpp - operations/COM_ProjectorLensDistortionOperation.cpp - operations/COM_ProjectorLensDistortionOperation.h - operations/COM_ScreenLensDistortionOperation.cpp - operations/COM_ScreenLensDistortionOperation.h - -#Filter operations + # Distort operation + operations/COM_TranslateOperation.h + operations/COM_TranslateOperation.cpp + operations/COM_RotateOperation.h + operations/COM_RotateOperation.cpp + operations/COM_ScaleOperation.h + operations/COM_ScaleOperation.cpp + operations/COM_MapUVOperation.h + operations/COM_MapUVOperation.cpp + operations/COM_DisplaceOperation.h + operations/COM_DisplaceOperation.cpp + operations/COM_DisplaceSimpleOperation.h + operations/COM_DisplaceSimpleOperation.cpp + operations/COM_FlipOperation.h + operations/COM_FlipOperation.cpp + operations/COM_ProjectorLensDistortionOperation.cpp + operations/COM_ProjectorLensDistortionOperation.h + operations/COM_ScreenLensDistortionOperation.cpp + operations/COM_ScreenLensDistortionOperation.h + + #Filter operations operations/COM_ConvolutionFilterOperation.h operations/COM_ConvolutionFilterOperation.cpp operations/COM_ConvolutionEdgeFilterOperation.h @@ -572,7 +570,7 @@ operations/COM_ConvertDepthToRadiusOperation.cpp operations/COM_SetSamplerOperation.h -#Convert operations + #Convert operations operations/COM_IDMaskOperation.cpp operations/COM_IDMaskOperation.h @@ -583,7 +581,8 @@ operations/COM_ConvertDepthToRadiusOperation.cpp operations/COM_DotproductOperation.cpp operations/COM_DotproductOperation.h -# Matte operation + + # Matte operation operations/COM_BoxMaskOperation.h operations/COM_BoxMaskOperation.cpp operations/COM_EllipseMaskOperation.h diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp index 94110f0bcfe..0ab08ec5810 100644 --- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp +++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp @@ -35,6 +35,6 @@ double ChunkOrderHotspot::determineDistance(int x, int y) int dx = x-this->x; int dy = y-this->y; double result = sqrt((double)(dx*dx+dy*dy)); - result += this->addition; + result += (double)this->addition; return result; } diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 37d79607d12..3ebf8398c02 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -150,8 +150,8 @@ void MemoryBuffer::readCubic(float result[4], float x, float y) float valuex = x - x1; float valuey = y - y1; - float mvaluex = 1.0 - valuex; - float mvaluey = 1.0 - valuey; + float mvaluex = 1.0f - valuex; + float mvaluey = 1.0f - valuey; float color1[4]; float color2[4]; diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index c48f3b0a291..71a87dce2a7 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -121,9 +121,9 @@ void BokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer * bufferindex +=offsetadd; } } - color[0] = tempColor[0]*(1.0/overallmultiplyerr); - color[1] = tempColor[1]*(1.0/overallmultiplyerg); - color[2] = tempColor[2]*(1.0/overallmultiplyerb); + color[0] = tempColor[0] * (1.0f / overallmultiplyerr); + color[1] = tempColor[1] * (1.0f / overallmultiplyerg); + color[2] = tempColor[2] * (1.0f / overallmultiplyerb); color[3] = 1.0f; } else { diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.cpp b/source/blender/compositor/operations/COM_BokehImageOperation.cpp index 0279b9a5bdf..a0297b12961 100644 --- a/source/blender/compositor/operations/COM_BokehImageOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehImageOperation.cpp @@ -34,25 +34,25 @@ void BokehImageOperation::initExecution() this->centerY = getHeight() / 2; this->center[0] = this->centerX; this->center[1] = this->centerY; - this->inverseRounding = 1.0-this->data->rounding; + this->inverseRounding = 1.0f - this->data->rounding; this->circularDistance = getWidth()/2; - this->flapRad = (M_PI*2)/this->data->flaps; - this->flapRadAdd = (this->data->angle/360.0)*M_PI*2; - while (this->flapRadAdd<0.0f) { - this->flapRadAdd+=M_PI*2; + this->flapRad = (float)(M_PI * 2) / this->data->flaps; + this->flapRadAdd = (this->data->angle / 360.0f) * (float)(M_PI * 2.0); + while (this->flapRadAdd < 0.0f) { + this->flapRadAdd += (float)(M_PI * 2.0); } - while (this->flapRadAdd>M_PI) { - this->flapRadAdd-=M_PI*2; + while (this->flapRadAdd > (float)M_PI) { + this->flapRadAdd -= (float)(M_PI * 2.0); } } void BokehImageOperation::detemineStartPointOfFlap(float r[2], int flapNumber, float distance) { - r[0] = sin(flapRad*flapNumber + flapRadAdd)*distance+centerX; - r[1] = cos(flapRad*flapNumber + flapRadAdd)*distance+centerY; + r[0] = sinf(flapRad * flapNumber + flapRadAdd) * distance + centerX; + r[1] = cosf(flapRad * flapNumber + flapRadAdd) * distance + centerY; } float BokehImageOperation::isInsideBokeh(float distance, float x, float y) { - float insideBokeh = 0.0; + float insideBokeh = 0.0f; const float deltaX = x - centerX; const float deltaY = y - centerY; float closestPoint[2]; @@ -63,7 +63,7 @@ float BokehImageOperation::isInsideBokeh(float distance, float x, float y) point[1] = y; const float distanceToCenter = len_v2v2(point, center); - const float bearing = (atan2f(deltaX, deltaY) + (M_PI*2)); + const float bearing = (atan2f(deltaX, deltaY) + (float)(M_PI * 2.0)); int flapNumber = (int)((bearing-flapRadAdd)/flapRad); detemineStartPointOfFlap(lineP1, flapNumber, distance); @@ -73,16 +73,16 @@ float BokehImageOperation::isInsideBokeh(float distance, float x, float y) const float distanceLineToCenter = len_v2v2(center, closestPoint); const float distanceRoundingToCenter = inverseRounding*distanceLineToCenter+this->data->rounding*distance; - const float catadioptricDistanceToCenter = distanceRoundingToCenter*this->data->catadioptric; - if (distanceRoundingToCenter>=distanceToCenter && catadioptricDistanceToCenter<=distanceToCenter) { - if (distanceRoundingToCenter-distanceToCenter<1.0) { + const float catadioptricDistanceToCenter = distanceRoundingToCenter * this->data->catadioptric; + if (distanceRoundingToCenter>=distanceToCenter && catadioptricDistanceToCenter <= distanceToCenter) { + if (distanceRoundingToCenter - distanceToCenter < 1.0f) { insideBokeh = (distanceRoundingToCenter-distanceToCenter); } - else if (this->data->catadioptric != 0.0 && distanceToCenter-catadioptricDistanceToCenter<1.0) { - insideBokeh = (distanceToCenter-catadioptricDistanceToCenter); + else if (this->data->catadioptric != 0.0f && distanceToCenter - catadioptricDistanceToCenter < 1.0f) { + insideBokeh = (distanceToCenter - catadioptricDistanceToCenter); } else { - insideBokeh = 1.0; + insideBokeh = 1.0f; } } return insideBokeh; @@ -90,11 +90,11 @@ float BokehImageOperation::isInsideBokeh(float distance, float x, float y) void BokehImageOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) { float shift = this->data->lensshift; - float shift2 = shift/2.0f; + float shift2 = shift / 2.0f; float distance = this->circularDistance; float insideBokehMax = isInsideBokeh(distance, x, y); - float insideBokehMed = isInsideBokeh(distance-fabs(shift2*distance), x, y); - float insideBokehMin = isInsideBokeh(distance-fabs(shift*distance), x, y); + float insideBokehMed = isInsideBokeh(distance - fabsf(shift2 * distance), x, y); + float insideBokehMin = isInsideBokeh(distance - fabsf(shift * distance), x, y); if (shift<0) { color[0] = insideBokehMax; color[1] = insideBokehMed; diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp index 0244be4cad3..ae83115ff69 100644 --- a/source/blender/compositor/operations/COM_BoxMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_BoxMaskOperation.cpp @@ -38,7 +38,7 @@ void BoxMaskOperation::initExecution() { this->inputMask = this->getInputSocketReader(0); this->inputValue = this->getInputSocketReader(1); - const double rad = DEG2RAD(this->data->rotation); + const double rad = DEG2RAD((double)this->data->rotation); this->cosine = cos(rad); this->sine = sin(rad); this->aspectRatio = ((float)this->getWidth())/this->getHeight(); @@ -60,12 +60,12 @@ void BoxMaskOperation::executePixel(float *color, float x, float y, PixelSampler this->inputMask->read(inputMask, x, y, sampler, inputBuffers); this->inputValue->read(inputValue, x, y, sampler, inputBuffers); - float halfHeight = (this->data->height)/2.0f; - float halfWidth = this->data->width/2.0f; - bool inside = rx > this->data->x-halfWidth - && rx < this->data->x+halfWidth - && ry > this->data->y-halfHeight - && ry < this->data->y+halfHeight; + float halfHeight = this->data->height / 2.0f; + float halfWidth = this->data->width / 2.0f; + bool inside = (rx > this->data->x - halfWidth && + rx < this->data->x + halfWidth && + ry > this->data->y - halfHeight && + ry < this->data->y + halfHeight); switch (this->maskType) { case CMP_NODE_MASKTYPE_ADD: diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp b/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp index 9b7f87e38bc..f949b0a55fa 100644 --- a/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp +++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.cpp @@ -46,7 +46,8 @@ void ChangeHSVOperation::executePixel(float *outputValue, float x, float y, Pixe inputOperation->read(inputColor1, x, y, sampler, inputBuffers); outputValue[0] = inputColor1[0] + (this->hue - 0.5f); - if (outputValue[0]>1.0f) outputValue[0]-=1.0; else if (outputValue[0]<0.0) outputValue[0]+= 1.0; + if (outputValue[0] > 1.0f) outputValue[0] -= 1.0f; + else if (outputValue[0] < 0.0f) outputValue[0] += 1.0f; outputValue[1] = inputColor1[1] * this->saturation; outputValue[2] = inputColor1[2] * this->value; outputValue[3] = inputColor1[3]; diff --git a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp index cc535cd95df..6fe6bde7c09 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorBalanceASCCDLOperation.cpp @@ -28,7 +28,7 @@ inline float colorbalance_cdl(float in, float offset, float power, float slope) float x = in * slope + offset; /* prevent NaN */ - CLAMP(x, 0.0, 1.0); + CLAMP(x, 0.0f, 1.0f); return powf(x, power); } diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp index af28b776892..82a71f6a7a8 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp @@ -62,21 +62,21 @@ void ColorCorrectionOperation::executePixel(float *output, float x, float y, Pix float levelShadows = 0.0; float levelMidtones = 0.0; float levelHighlights = 0.0; -#define MARGIN 0.10 -#define MARGIN_DIV (0.5/MARGIN) - if (level < this->data->startmidtones-MARGIN) { +#define MARGIN 0.10f +#define MARGIN_DIV (0.5f / MARGIN) + if (level < this->data->startmidtones - MARGIN) { levelShadows = 1.0f; } - else if (level < this->data->startmidtones+MARGIN) { - levelMidtones = ((level-this->data->startmidtones)*MARGIN_DIV)+0.5; - levelShadows = 1.0 - levelMidtones; + else if (level < this->data->startmidtones + MARGIN) { + levelMidtones = ((level - this->data->startmidtones) * MARGIN_DIV) + 0.5f; + levelShadows = 1.0f - levelMidtones; } - else if (level < this->data->endmidtones-MARGIN) { + else if (level < this->data->endmidtones - MARGIN) { levelMidtones = 1.0f; } - else if (level < this->data->endmidtones+MARGIN) { - levelHighlights = ((level-this->data->endmidtones)*MARGIN_DIV)+0.5; - levelMidtones = 1.0 - levelHighlights; + else if (level < this->data->endmidtones + MARGIN) { + levelHighlights = ((level - this->data->endmidtones) * MARGIN_DIV) + 0.5f; + levelMidtones = 1.0f - levelHighlights; } else { levelHighlights = 1.0f; @@ -93,15 +93,15 @@ void ColorCorrectionOperation::executePixel(float *output, float x, float y, Pix g = inputImageColor[1]; b = inputImageColor[2]; - float invgamma = 1.0f/gamma; - float luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; + float invgamma = 1.0f / gamma; + float luma = 0.2126f * r + 0.7152f * g + 0.0722f * b; r = (luma + saturation * (r - luma)); g = (luma + saturation * (g - luma)); b = (luma + saturation * (b - luma)); - r = 0.5+((r-0.5)*contrast); - g = 0.5+((g-0.5)*contrast); - b = 0.5+((b-0.5)*contrast); + r = 0.5f + ((r - 0.5f) * contrast); + g = 0.5f + ((g - 0.5f) * contrast); + b = 0.5f + ((b - 0.5f) * contrast); r = powf(r*gain+lift, invgamma); g = powf(g*gain+lift, invgamma); diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp index 069bbde5e73..a38012271f1 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp @@ -76,19 +76,19 @@ void ColorCurveOperation::executePixel(float *color, float x, float y, PixelSamp this->inputFacProgram->read(fac, x, y, sampler, inputBuffers); this->inputImageProgram->read(image, x, y, sampler, inputBuffers); - if (fac[0] >= 1.0) + if (*fac >= 1.0f) curvemapping_evaluate_premulRGBF(workingCopy, color, image); - else if (*fac<=0.0) { + else if (*fac <= 0.0f) { color[0] = image[0]; color[1] = image[1]; color[2] = image[2]; } else { - float col[4], mfac = 1.0f-*fac; + float col[4], mfac = 1.0f - *fac; curvemapping_evaluate_premulRGBF(workingCopy, col, image); - color[0] = mfac*image[0] + *fac*col[0]; - color[1] = mfac*image[1] + *fac*col[1]; - color[2] = mfac*image[2] + *fac*col[2]; + color[0] = mfac * image[0] + *fac * col[0]; + color[1] = mfac * image[1] + *fac * col[1]; + color[2] = mfac * image[2] + *fac * col[2]; } color[3] = image[3]; MEM_freeN(workingCopy); @@ -137,19 +137,19 @@ void ConstantLevelColorCurveOperation::executePixel(float *color, float x, float this->inputFacProgram->read(fac, x, y, sampler, inputBuffers); this->inputImageProgram->read(image, x, y, sampler, inputBuffers); - if (fac[0] >= 1.0) + if (*fac >= 1.0f) curvemapping_evaluate_premulRGBF(this->curveMapping, color, image); - else if (*fac<=0.0) { + else if (*fac <= 0.0f) { color[0] = image[0]; color[1] = image[1]; color[2] = image[2]; } else { - float col[4], mfac = 1.0f-*fac; + float col[4], mfac = 1.0f - *fac; curvemapping_evaluate_premulRGBF(this->curveMapping, col, image); - color[0] = mfac*image[0] + *fac*col[0]; - color[1] = mfac*image[1] + *fac*col[1]; - color[2] = mfac*image[2] + *fac*col[2]; + color[0] = mfac * image[0] + *fac * col[0]; + color[1] = mfac * image[1] + *fac * col[1]; + color[2] = mfac * image[2] + *fac * col[2]; } color[3] = image[3]; } diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp index 628daa7c775..0b1ac1b2127 100644 --- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp @@ -57,16 +57,16 @@ void DifferenceMatteOperation::executePixel(float *outputValue, float x, float y this->inputImage1Program->read(inColor1, x, y, sampler, inputBuffers); this->inputImage2Program->read(inColor2, x, y, sampler, inputBuffers); - difference = (fabs(inColor2[0] - inColor1[0]) + - fabs(inColor2[1] - inColor1[1]) + - fabs(inColor2[2] - inColor1[2])); + difference = (fabsf(inColor2[0] - inColor1[0]) + + fabsf(inColor2[1] - inColor1[1]) + + fabsf(inColor2[2] - inColor1[2])); - /*average together the distances*/ - difference=difference/3.0; + /* average together the distances */ + difference = difference / 3.0f; /*make 100% transparent*/ if (difference < tolerence) { - outputValue[0]=0.0; + outputValue[0] = 0.0f; } /*in the falloff region, make partially transparent */ else if (difference < falloff+tolerence) { diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp index 30a09a45ade..43cba09d16f 100644 --- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp @@ -51,17 +51,17 @@ void DirectionalBlurOperation::initExecution() const float height = getHeight(); const float a = angle; - const float itsc = 1.f / pow(2.f, (float)iterations); + const float itsc = 1.0f / powf(2.0f, (float)iterations); float D; D = distance * sqrtf(width*width + height*height); center_x_pix = center_x * width; center_y_pix = center_y * height; - tx= itsc * D * cos(a); - ty= -itsc * D * sin(a); - sc= itsc * zoom; - rot = itsc * spin; + tx = itsc * D * cosf(a); + ty = -itsc * D * sinf(a); + sc = itsc * zoom; + rot = itsc * spin; } diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp index 85a629f7365..650c57dd8dc 100644 --- a/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.cpp @@ -38,7 +38,7 @@ void EllipseMaskOperation::initExecution() { this->inputMask = this->getInputSocketReader(0); this->inputValue = this->getInputSocketReader(1); - const double rad = DEG2RAD(this->data->rotation); + const double rad = DEG2RAD((double)this->data->rotation); this->cosine = cos(rad); this->sine = sin(rad); this->aspectRatio = ((float)this->getWidth())/this->getHeight(); diff --git a/source/blender/compositor/operations/COM_FogGlowImageOperation.cpp b/source/blender/compositor/operations/COM_FogGlowImageOperation.cpp index 600bfde64d9..05a758aca7f 100644 --- a/source/blender/compositor/operations/COM_FogGlowImageOperation.cpp +++ b/source/blender/compositor/operations/COM_FogGlowImageOperation.cpp @@ -37,7 +37,7 @@ void FogGlowImageOperation::executePixel(float *color, float x, float y, PixelSa u = 2.f*(x / (float)512) - 1.f; r = (u*u + v*v)*256; d = -sqrtf(sqrtf(sqrtf(r))); - w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI)); + w = (0.5f + 0.5f * cosf(u * (float)M_PI)) * (0.5f + 0.5f * cosf(v * (float)M_PI)); color[0] = expf(d*cs_r) * w; color[1] = expf(d*cs_g) * w; color[2] = expf(d*cs_b) * w; diff --git a/source/blender/compositor/operations/COM_GammaOperation.cpp b/source/blender/compositor/operations/COM_GammaOperation.cpp index f0887d4adee..989ffd5dfba 100644 --- a/source/blender/compositor/operations/COM_GammaOperation.cpp +++ b/source/blender/compositor/operations/COM_GammaOperation.cpp @@ -46,9 +46,9 @@ void GammaOperation::executePixel(float *color, float x, float y, PixelSampler s this->inputGammaProgram->read(inputGamma, x, y, sampler, inputBuffers); const float gamma = inputGamma[0]; /* check for negative to avoid nan's */ - color[0] = inputValue[0]>0.0f?pow(inputValue[0], gamma):inputValue[0]; - color[1] = inputValue[1]>0.0f?pow(inputValue[1], gamma):inputValue[1]; - color[2] = inputValue[2]>0.0f?pow(inputValue[2], gamma):inputValue[2]; + color[0] = inputValue[0] > 0.0f ? powf(inputValue[0], gamma) : inputValue[0]; + color[1] = inputValue[1] > 0.0f ? powf(inputValue[1], gamma) : inputValue[1]; + color[2] = inputValue[2] > 0.0f ? powf(inputValue[2], gamma) : inputValue[2]; color[3] = inputValue[3]; } diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index 642a28627bd..e522d334d8b 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -147,11 +147,11 @@ void GaussianBokehBlurOperation::executePixel(float *color, int x, int y, Memory bufferindex +=offsetadd; } } - float divider = 1.0/overallmultiplyer; - color[0] = tempColor[0]*divider; - color[1] = tempColor[1]*divider; - color[2] = tempColor[2]*divider; - color[3] = tempColor[3]*divider; + float divider = 1.0f / overallmultiplyer; + color[0] = tempColor[0] * divider; + color[1] = tempColor[1] * divider; + color[2] = tempColor[2] * divider; + color[3] = tempColor[3] * divider; } void GaussianBokehBlurOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 852754416f4..2eb51b4577f 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -77,7 +77,7 @@ void GaussianXBlurOperation::executePixel(float *color, int x, int y, MemoryBuff tempColor[1] = 0; tempColor[2] = 0; tempColor[3] = 0; - float overallmultiplyer = 0; + float overallmultiplyer = 0.0f; MemoryBuffer *inputBuffer = (MemoryBuffer*)data; float *buffer = inputBuffer->getBuffer(); int bufferwidth = inputBuffer->getWidth(); @@ -106,11 +106,11 @@ void GaussianXBlurOperation::executePixel(float *color, int x, int y, MemoryBuff overallmultiplyer += multiplyer; bufferindex +=offsetadd; } - float divider = 1.0/overallmultiplyer; - color[0] = tempColor[0]*divider; - color[1] = tempColor[1]*divider; - color[2] = tempColor[2]*divider; - color[3] = tempColor[3]*divider; + float divider = 1.0f / overallmultiplyer; + color[0] = tempColor[0] * divider; + color[1] = tempColor[1] * divider; + color[2] = tempColor[2] * divider; + color[3] = tempColor[3] * divider; } void GaussianXBlurOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index cab3e3d6094..28e8e548530 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -101,11 +101,11 @@ void GaussianYBlurOperation::executePixel(float *color, int x, int y, MemoryBuff tempColor[3] += multiplyer * buffer[bufferindex+3]; overallmultiplyer += multiplyer; } - float divider = 1.0/overallmultiplyer; - color[0] = tempColor[0]*divider; - color[1] = tempColor[1]*divider; - color[2] = tempColor[2]*divider; - color[3] = tempColor[3]*divider; + float divider = 1.0f / overallmultiplyer; + color[0] = tempColor[0] * divider; + color[1] = tempColor[1] * divider; + color[2] = tempColor[2] * divider; + color[3] = tempColor[3] * divider; } void GaussianYBlurOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp index 2970c396493..2afcc2e5cc7 100644 --- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp @@ -63,8 +63,8 @@ void HueSaturationValueCorrectOperation::executePixel(float *output, float x, fl f = curvemapping_evaluateF(this->curveMapping, 2, hsv[0]); hsv[2] *= (f * 2.f); - hsv[0] = hsv[0] - floor(hsv[0]); /* mod 1.0 */ - CLAMP(hsv[1], 0.f, 1.f); + hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ + CLAMP(hsv[1], 0.0f, 1.0f); output[0] = hsv[0]; output[1] = hsv[1]; diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp index 7b393cc04a8..035f5584065 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cpp +++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp @@ -61,16 +61,16 @@ void MapUVOperation::executePixel(float *color, float x, float y, PixelSampler s /* adaptive sampling, red (U) channel */ this->inputUVProgram->read(uv_a, x-1, y, COM_PS_NEAREST, inputBuffers); this->inputUVProgram->read(uv_b, x+1, y, COM_PS_NEAREST, inputBuffers); - uv_l = uv_a[2]!=0.f? fabs(inputUV[0] - uv_a[0]) : 0.f; - uv_r = uv_b[2]!=0.f? fabs(inputUV[0] - uv_b[0]) : 0.f; + uv_l = uv_a[2]!=0.f? fabsf(inputUV[0] - uv_a[0]) : 0.f; + uv_r = uv_b[2]!=0.f? fabsf(inputUV[0] - uv_b[0]) : 0.f; dx = 0.5f * (uv_l + uv_r); /* adaptive sampling, green (V) channel */ this->inputUVProgram->read(uv_a, x, y-1, COM_PS_NEAREST, inputBuffers); this->inputUVProgram->read(uv_b, x, y+1, COM_PS_NEAREST, inputBuffers); - uv_u = uv_a[2]!=0.f? fabs(inputUV[1] - uv_a[1]) : 0.f; - uv_d = uv_b[2]!=0.f? fabs(inputUV[1] - uv_b[1]) : 0.f; + uv_u = uv_a[2]!=0.f? fabsf(inputUV[1] - uv_a[1]) : 0.f; + uv_d = uv_b[2]!=0.f? fabsf(inputUV[1] - uv_b[1]) : 0.f; dy = 0.5f * (uv_u + uv_d); diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp index 2ea5f85253b..b943ec88fde 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp @@ -196,8 +196,8 @@ void MathPowerOperation::executePixel(float *outputValue, float x, float y, Pixe else { float y_mod_1 = fmod(inputValue2[0], 1); /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ - if (y_mod_1 > 0.999 || y_mod_1 < 0.001) { - outputValue[0] = pow(inputValue1[0], (float)floor(inputValue2[0] + 0.5)); + if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { + outputValue[0] = pow(inputValue1[0], floorf(inputValue2[0] + 0.5f)); } else { outputValue[0] = 0.0; diff --git a/source/blender/compositor/operations/COM_RotateOperation.cpp b/source/blender/compositor/operations/COM_RotateOperation.cpp index 313e49d8609..af2633f0e53 100644 --- a/source/blender/compositor/operations/COM_RotateOperation.cpp +++ b/source/blender/compositor/operations/COM_RotateOperation.cpp @@ -43,7 +43,7 @@ void RotateOperation::initExecution() this->degreeSocket->read(degree, 0, 0, COM_PS_NEAREST, NULL); double rad; if (this->doDegree2RadConversion) { - rad = DEG2RAD(degree[0]); + rad = DEG2RAD((double)degree[0]); } else { rad = degree[0]; diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp index 56830f4970d..d8089bdf3ea 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cpp +++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp @@ -53,14 +53,14 @@ void TonemapOperation::executePixel(float *color, int x, int y, MemoryBuffer *in float dr = output[0] + this->data->offset; float dg = output[1] + this->data->offset; float db = output[2] + this->data->offset; - output[0] /= ((dr == 0.f) ? 1.f : dr); - output[1] /= ((dg == 0.f) ? 1.f : dg); - output[2] /= ((db == 0.f) ? 1.f : db); + output[0] /= ((dr == 0.f) ? 1.0f : dr); + output[1] /= ((dg == 0.f) ? 1.0f : dg); + output[2] /= ((db == 0.f) ? 1.0f : db); const float igm = avg->igm; - if (igm != 0.f) { - output[0] = pow((double)MAX2(output[0], 0.), (double)igm); - output[1] = pow((double)MAX2(output[1], 0.), (double)igm); - output[2] = pow((double)MAX2(output[2], 0.), (double)igm); + if (igm != 0.0f) { + output[0] = powf(MAX2(output[0], 0.0f), igm); + output[1] = powf(MAX2(output[1], 0.0f), igm); + output[2] = powf(MAX2(output[2], 0.0f), igm); } color[0] = output[0]; @@ -68,31 +68,31 @@ void TonemapOperation::executePixel(float *color, int x, int y, MemoryBuffer *in color[2] = output[2]; color[3] = output[3]; } -void PhotoreceptorTonemapOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void * data) +void PhotoreceptorTonemapOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { - AvgLogLum * avg = (AvgLogLum*)data; + AvgLogLum *avg = (AvgLogLum *)data; NodeTonemap *ntm = this->data; - const float f = exp((double)-this->data->f); - const float m = (ntm->m > 0.f) ? ntm->m : (0.3f + 0.7f*pow((double)avg->auto_key, 1.4)); - const float ic = 1.f - ntm->c, ia = 1.f - ntm->a; + const float f = expf(-this->data->f); + const float m = (ntm->m > 0.0f) ? ntm->m : (0.3f + 0.7f * powf(avg->auto_key, 1.4f)); + const float ic = 1.0f - ntm->c, ia = 1.0f - ntm->a; float output[4]; this->imageReader->read(output, x, y, inputBuffers, NULL); - const float L = 0.212671f*output[0] + 0.71516f*output[1] + 0.072169f*output[2]; - float I_l = output[0] + ic*(L - output[0]); - float I_g = avg->cav[0] + ic*(avg->lav - avg->cav[0]); - float I_a = I_l + ia*(I_g - I_l); - output[0] /= (output[0] + pow((double)f*I_a, (double)m)); - I_l = output[1] + ic*(L - output[1]); - I_g = avg->cav[1] + ic*(avg->lav - avg->cav[1]); - I_a = I_l + ia*(I_g - I_l); - output[1] /= (output[1] + pow((double)f*I_a,(double)m)); - I_l = output[2] + ic*(L - output[2]); - I_g = avg->cav[2] + ic*(avg->lav - avg->cav[2]); - I_a = I_l + ia*(I_g - I_l); - output[2] /= (output[2] + pow((double)f*I_a, (double)m)); + const float L = 0.212671f * output[0] + 0.71516f * output[1] + 0.072169f * output[2]; + float I_l = output[0] + ic * (L - output[0]); + float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]); + float I_a = I_l + ia * (I_g - I_l); + output[0] /= (output[0] + powf(f * I_a, m)); + I_l = output[1] + ic * (L - output[1]); + I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]); + I_a = I_l + ia * (I_g - I_l); + output[1] /= (output[1] + powf(f * I_a, m)); + I_l = output[2] + ic * (L - output[2]); + I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]); + I_a = I_l + ia * (I_g - I_l); + output[2] /= (output[2] + powf(f * I_a, m)); color[0] = output[0]; color[1] = output[1]; @@ -133,20 +133,20 @@ void *TonemapOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuff float * buffer = tile->getBuffer(); - float lsum = 0; + float lsum = 0.0f; int p = tile->getWidth() * tile->getHeight(); float *bc = buffer; float avl, maxl = -1e10f, minl = 1e10f; - const float sc = 1.f/(p); + const float sc = 1.0f / p; float Lav = 0.f; float cav[4] = {0.0f,0.0f,0.0f,0.0f}; while (p--) { - float L = 0.212671f*bc[0] + 0.71516f*bc[1] + 0.072169f*bc[2]; + float L = 0.212671f * bc[0] + 0.71516f * bc[1] + 0.072169f * bc[2]; Lav += L; cav[0] += bc[0]; cav[1] += bc[1]; cav[2] += bc[2]; - lsum += (float)log((double)MAX2(L, 0.0) + 1e-5); + lsum += logf(MAX2(L, 0.0f) + 1e-5f); maxl = (L > maxl) ? L : maxl; minl = (L < minl) ? L : minl; bc+=4; @@ -155,7 +155,7 @@ void *TonemapOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuff data->cav[0] = cav[0]*sc; data->cav[1] = cav[1]*sc; data->cav[2] = cav[2]*sc; - maxl = log((double)maxl + 1e-5); minl = log((double)minl + 1e-5f); avl = lsum*sc; + maxl = log((double)maxl + 1e-5); minl = log((double)minl + 1e-5); avl = lsum * sc; data->auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.f; float al = exp((double)avl); data->al = (al == 0.f) ? 0.f : (this->data->key / al); diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index f14de097dfd..270fedc174b 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -89,7 +89,7 @@ void VariableSizeBokehBlurOperation::executePixel(float *color, int x, int y, Me if (nx == x && ny == y) { /* pass */ } - else if (size>= fabs(dx) && size >= fabs(dy)) { + else if (size >= fabsf(dx) && size >= fabsf(dy)) { float u = 256 + dx*256/size; float v = 256 + dy*256/size; inputBokehProgram->read(bokeh, u, v, COM_PS_NEAREST, inputBuffers); @@ -104,9 +104,9 @@ void VariableSizeBokehBlurOperation::executePixel(float *color, int x, int y, Me } } } - color[0] = tempColor[0]*(1.0/overallmultiplyerr); - color[1] = tempColor[1]*(1.0/overallmultiplyerg); - color[2] = tempColor[2]*(1.0/overallmultiplyerb); + color[0] = tempColor[0] * (1.0f / overallmultiplyerr); + color[1] = tempColor[1] * (1.0f / overallmultiplyerg); + color[2] = tempColor[2] * (1.0f / overallmultiplyerb); color[3] = 1.0f; } -- cgit v1.2.3 From 02bcba341dd403906027ed0a4122c3ce68bf6b7a Mon Sep 17 00:00:00 2001 From: Dan Eicher Date: Sat, 9 Jun 2012 21:43:22 +0000 Subject: OBJECT_OT_drop_named_material -- missing notifier for material panel UI update --- source/blender/editors/object/object_relations.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 85b9d78c657..fc0aa39e733 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1929,6 +1929,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *even DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma); return OPERATOR_FINISHED; } -- cgit v1.2.3 From 0d6ffd925df0c4a5658d6195ca0e535f0e09fdac Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 00:22:18 +0000 Subject: remove duplicate import --- release/scripts/modules/bpy/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 2e6d1bf8fbc..4e8179775d5 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -345,8 +345,7 @@ def preset_paths(subdir): dirs.append(directory) # Find addons preset paths - import addon_utils - for path in addon_utils.paths(): + for path in _addon_utils.paths(): directory = _os.path.join(path, "presets", subdir) if _os.path.isdir(directory): dirs.append(directory) -- cgit v1.2.3 From 0586705b63fba83a70d38ea7e3035212971ce852 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Sun, 10 Jun 2012 07:35:45 +0000 Subject: Fix #31747, broken image sequence loading after r47432. The image file name function was updating the iuser->framenr using a supposed cfra parameter. However, the actual cfra is unknown when loading movies or sequences, so the iuser->framenr value itself was passed in its place, leading to incremental addition of the iuser frame offset. Removed the cfra parameter altogether from the image path function. This should instead be done separately if necessary, it's not an inherent part of constructing the image file name. --- intern/cycles/blender/blender_util.h | 6 ++++-- source/blender/blenkernel/BKE_image.h | 2 +- source/blender/blenkernel/intern/image.c | 18 ++++++------------ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 9b9e0d3a425..b5a76836bed 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -53,7 +53,8 @@ int rna_Object_is_deform_modified(void *ob, void *scene, int settings); void BLI_timestr(double _time, char *str); void rna_ColorRamp_eval(void *coba, float position, float color[4]); void rna_Scene_frame_set(void *scene, int frame, float subframe); -void BKE_image_user_file_path(void *iuser, void *ima, int cfra, char *path); +void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr); +void BKE_image_user_file_path(void *iuser, void *ima, char *path); } @@ -105,7 +106,8 @@ static inline bool BKE_object_is_deform_modified(BL::Object self, BL::Scene scen static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, int cfra) { char filepath[1024]; - BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, cfra, filepath); + BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0); + BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath); return string(filepath); } diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 279ec272fe8..baa530c0599 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -157,7 +157,7 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); void BKE_image_user_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); void BKE_image_user_check_frame_calc(struct ImageUser *iuser, int cfra, int fieldnr); int BKE_image_user_frame_get(const struct ImageUser *iuser, int cfra, int fieldnr); -void BKE_image_user_file_path(struct ImageUser *iuser, struct Image *ima, int cfra, char *path); +void BKE_image_user_file_path(struct ImageUser *iuser, struct Image *ima, char *path); /* sets index offset for multilayer files */ struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d733092e792..157c8782523 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2092,7 +2092,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) ima->tpageflag |= IMA_TPAGE_REFRESH; ima->lastframe = frame; - BKE_image_user_file_path(iuser, ima, frame, name); + BKE_image_user_file_path(iuser, ima, name); flag = IB_rect | IB_multilayer; if (ima->flag & IMA_DO_PREMUL) @@ -2204,7 +2204,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) if (ima->anim == NULL) { char str[FILE_MAX]; - BKE_image_user_file_path(iuser, ima, frame, str); + BKE_image_user_file_path(iuser, ima, str); /* FIXME: make several stream accessible in image editor, too*/ ima->anim = openanim(str, IB_rect, 0); @@ -2267,7 +2267,8 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) flag |= IB_premul; /* get the right string */ - BKE_image_user_file_path(iuser, ima, cfra, str); + BKE_image_user_frame_calc(iuser, cfra, 0); + BKE_image_user_file_path(iuser, ima, str); /* read ibuf */ ibuf = IMB_loadiffname(str, flag); @@ -2741,21 +2742,14 @@ void BKE_image_user_check_frame_calc(ImageUser *iuser, int cfra, int fieldnr) } } -void BKE_image_user_file_path(ImageUser *iuser, Image *ima, int cfra, char *filepath) +void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath) { BLI_strncpy(filepath, ima->name, FILE_MAX); if (ima->source == IMA_SRC_SEQUENCE) { char head[FILE_MAX], tail[FILE_MAX]; unsigned short numlen; - int frame; - - if(iuser) { - BKE_image_user_frame_calc(iuser, cfra, 0); - frame = iuser->framenr; - } - else { - } + int frame = iuser->framenr; BLI_stringdec(filepath, head, tail, &numlen); BLI_stringenc(filepath, head, tail, numlen, frame); -- cgit v1.2.3 From 945cc4651a0de868c3607ee294db18ec44da0720 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Sun, 10 Jun 2012 07:51:57 +0000 Subject: Fix for compositor image node draw function. The image user pointer needs to be constructed explicitly from the node storage pointer. --- source/blender/editors/space_node/drawnode.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index d37a2739fc3..12c369874fe 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1442,18 +1442,16 @@ static void node_shader_set_butfunc(bNodeType *ntype) static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; - PointerRNA imaptr; - PropertyRNA *prop; + PointerRNA imaptr, iuserptr; uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); if (!node->id) return; - prop = RNA_struct_find_property(ptr, "image"); - if (!prop || RNA_property_type(prop) != PROP_POINTER) return; - imaptr = RNA_property_pointer_get(ptr, prop); + imaptr = RNA_pointer_get(ptr, "image"); + RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr); - node_buts_image_user(layout, C, &imaptr, ptr); + node_buts_image_user(layout, C, &imaptr, &iuserptr); } static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) -- cgit v1.2.3 From bdc10e7b41cbb891e7a902c134591eb580c5766c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 09:04:49 +0000 Subject: Missed NULL-pointer checks in poll some functions --- source/blender/editors/space_clip/tracking_ops.c | 26 +++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index f3a96ef7a79..08fc84d193c 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -2140,14 +2140,17 @@ static int set_orientation_poll(bContext *C) if (sc) { Scene *scene = CTX_data_scene(C); MovieClip *clip = ED_space_clip(sc); - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { - return TRUE; - } - else { - return OBACT != NULL; + if (clip) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); + + if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { + return TRUE; + } + else { + return OBACT != NULL; + } } } @@ -2750,10 +2753,13 @@ static int set_solution_scale_poll(bContext *C) if (sc) { MovieClip *clip = ED_space_clip(sc); - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); - return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0; + if (clip) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_active_object(tracking); + + return (tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0; + } } return FALSE; -- cgit v1.2.3 From 6e9e758d605741a2ecb8b0fbf24881a17dbe7453 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 09:05:49 +0000 Subject: fix for un-initialized memory use for modal inset/bevel. --- source/blender/editors/include/ED_transform.h | 2 +- source/blender/editors/mesh/editmesh_tools.c | 17 +++++++++++++---- source/blender/editors/transform/transform.c | 8 ++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 42036d1ea17..608df8dd9b3 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -103,7 +103,7 @@ enum { * returns 1 if successful, 0 otherwise (usually means there's no selection) * (if 0 is returns, *vec is unmodified) * */ -int calculateTransformCenter(struct bContext *C, int centerMode, float *cent3d, int *cent2d); +int calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], int cent2d[2]); struct TransInfo; struct ScrArea; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 93ed7d37235..b6d89a62d05 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4498,13 +4498,18 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) BevelData *opdata; float mlen[2]; - if (!edbm_bevel_init(C, op, TRUE)) + if (!edbm_bevel_init(C, op, TRUE)) { return OPERATOR_CANCELLED; + } - /* initialize mouse values */ opdata = op->customdata; - calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter); + /* initialize mouse values */ + if (!calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter)) { + /* in this case the tool will likely do nothing, + * ideally this will never happen and should be checked for above */ + opdata->mcenter[0] = opdata->mcenter[1] = 0; + } mlen[0] = opdata->mcenter[0] - event->mval[0]; mlen[1] = opdata->mcenter[1] - event->mval[1]; opdata->initial_length = len_v2(mlen); @@ -4795,8 +4800,12 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event) opdata = op->customdata; - calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter); /* initialize mouse values */ + if (!calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter)) { + /* in this case the tool will likely do nothing, + * ideally this will never happen and should be checked for above */ + opdata->mcenter[0] = opdata->mcenter[1] = 0; + } mlen[0] = opdata->mcenter[0] - event->mval[0]; mlen[1] = opdata->mcenter[1] - event->mval[1]; opdata->initial_length = len_v2(mlen); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index b437d186549..ea86083fac4 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1178,10 +1178,10 @@ int transformEvent(TransInfo *t, wmEvent *event) return OPERATOR_PASS_THROUGH; } -int calculateTransformCenter(bContext *C, int centerMode, float *cent3d, int *cent2d) +int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int cent2d[2]) { TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); - int success = 1; + int success; t->state = TRANS_RUNNING; @@ -1196,10 +1196,10 @@ int calculateTransformCenter(bContext *C, int centerMode, float *cent3d, int *ce t->around = centerMode; // override userdefined mode if (t->total == 0) { - success = 0; + success = FALSE; } else { - success = 1; + success = TRUE; calculateCenter(t); -- cgit v1.2.3 From 18a966293e2a987c7bd5cd17df6a16f76048a042 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Sun, 10 Jun 2012 09:30:31 +0000 Subject: Fix for Tile group nodes with internally unconnected outputs, this was crashing due to missing constant value operations for such outputs. The SocketProxyNode now checks connection of the input socket on conversion, so this also simplifies usage of proxy nodes quite a bit. --- source/blender/compositor/nodes/COM_GroupNode.cpp | 15 ++--- .../compositor/nodes/COM_SocketProxyNode.cpp | 78 +++++++++++----------- .../blender/compositor/nodes/COM_SocketProxyNode.h | 6 -- 3 files changed, 42 insertions(+), 57 deletions(-) diff --git a/source/blender/compositor/nodes/COM_GroupNode.cpp b/source/blender/compositor/nodes/COM_GroupNode.cpp index 076d4f1501a..ec06a3acd7e 100644 --- a/source/blender/compositor/nodes/COM_GroupNode.cpp +++ b/source/blender/compositor/nodes/COM_GroupNode.cpp @@ -45,23 +45,16 @@ void GroupNode::ungroup(ExecutionSystem &system) InputSocket * inputSocket = inputsockets[index]; bNodeSocket *editorInput = inputSocket->getbNodeSocket(); if (editorInput->groupsock) { - if (inputSocket->isConnected()) { - SocketProxyNode * proxy = new SocketProxyNode(this->getbNode(), editorInput, editorInput->groupsock); - inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system); - ExecutionSystemHelper::addNode(system.getNodes(), proxy); - } - else { - OutputSocketProxyNode * proxy = new OutputSocketProxyNode(this->getbNode(), editorInput, editorInput->groupsock); - inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system); - ExecutionSystemHelper::addNode(system.getNodes(), proxy); - } + SocketProxyNode * proxy = new SocketProxyNode(this->getbNode(), editorInput, editorInput->groupsock); + inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system); + ExecutionSystemHelper::addNode(system.getNodes(), proxy); } } for (index = 0 ; index < outputsockets.size();index ++) { OutputSocket * outputSocket = outputsockets[index]; bNodeSocket *editorOutput = outputSocket->getbNodeSocket(); - if (outputSocket->isConnected() && editorOutput->groupsock) { + if (editorOutput->groupsock) { SocketProxyNode * proxy = new SocketProxyNode(this->getbNode(), editorOutput->groupsock, editorOutput); outputSocket->relinkConnections(proxy->getOutputSocket(0)); ExecutionSystemHelper::addNode(system.getNodes(), proxy); diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp index 42dd49bd1da..fbb25afe266 100644 --- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp +++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp @@ -44,52 +44,50 @@ SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bN } void SocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorContext * context) -{ - OutputSocket * outputsocket = this->getOutputSocket(0); - if (outputsocket->isConnected()) { - SocketProxyOperation *operation = new SocketProxyOperation(); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0)); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - } -} - -void OutputSocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorContext * context) { OutputSocket * outputsocket = this->getOutputSocket(0); InputSocket * inputsocket = this->getInputSocket(0); if (outputsocket->isConnected()) { - switch (outputsocket->getActualDataType()) { - case COM_DT_VALUE: - { - SetValueOperation *operation = new SetValueOperation(); - bNodeSocketValueFloat *dval = (bNodeSocketValueFloat*)inputsocket->getbNodeSocket()->default_value; - operation->setValue(dval->value); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - break; - } - case COM_DT_COLOR: - { - SetColorOperation *operation = new SetColorOperation(); - bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA*)inputsocket->getbNodeSocket()->default_value; - operation->setChannels(dval->value); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); - break; - } - case COM_DT_VECTOR: - { - SetVectorOperation *operation = new SetVectorOperation(); - bNodeSocketValueVector *dval = (bNodeSocketValueVector*)inputsocket->getbNodeSocket()->default_value; - operation->setVector(dval->value); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); + if (inputsocket->isConnected()) { + SocketProxyOperation *operation = new SocketProxyOperation(); + inputsocket->relinkConnections(operation->getInputSocket(0)); + outputsocket->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(operation); - break; } - /* quiet warnings */ - case COM_DT_UNKNOWN: - break; + else { + /* If input is not connected, add a constant value operation instead */ + switch (outputsocket->getActualDataType()) { + case COM_DT_VALUE: + { + SetValueOperation *operation = new SetValueOperation(); + bNodeSocketValueFloat *dval = (bNodeSocketValueFloat*)inputsocket->getbNodeSocket()->default_value; + operation->setValue(dval->value); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + break; + } + case COM_DT_COLOR: + { + SetColorOperation *operation = new SetColorOperation(); + bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA*)inputsocket->getbNodeSocket()->default_value; + operation->setChannels(dval->value); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + break; + } + case COM_DT_VECTOR: + { + SetVectorOperation *operation = new SetVectorOperation(); + bNodeSocketValueVector *dval = (bNodeSocketValueVector*)inputsocket->getbNodeSocket()->default_value; + operation->setVector(dval->value); + outputsocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + break; + } + /* quiet warnings */ + case COM_DT_UNKNOWN: + break; + } } } } diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.h b/source/blender/compositor/nodes/COM_SocketProxyNode.h index 1b5ee699211..b73ca24a45e 100644 --- a/source/blender/compositor/nodes/COM_SocketProxyNode.h +++ b/source/blender/compositor/nodes/COM_SocketProxyNode.h @@ -37,10 +37,4 @@ public: virtual bool isProxyNode() const { return true; } }; -class OutputSocketProxyNode: public SocketProxyNode { -public: - OutputSocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput): SocketProxyNode(editorNode, editorInput, editorOutput) {} - void convertToOperations(ExecutionSystem *graph, CompositorContext * context); -}; - #endif -- cgit v1.2.3 From 6ba5650428390158208cf4369e0cc6a2baad2fbd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 10:15:49 +0000 Subject: code cleanup: rename flag --> dflag (draw flag), since this is overly generic name and was passed about to many functions. --- source/blender/editors/space_view3d/drawarmature.c | 24 ++--- source/blender/editors/space_view3d/drawobject.c | 116 +++++++++++---------- source/blender/editors/space_view3d/view3d_draw.c | 12 +-- .../blender/editors/space_view3d/view3d_intern.h | 37 ++++--- 4 files changed, 99 insertions(+), 90 deletions(-) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 7edf18136d2..e51f7a312eb 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -557,7 +557,7 @@ static void draw_bone_solid_octahedral(void) /* *************** Armature drawing, bones ******************* */ -static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id) +static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, int id) { /* Draw root point if we are not connected */ if ((boneflag & BONE_CONNECTED) == 0) { @@ -862,7 +862,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], } /* does wire only for outline selecting */ -static void draw_sphere_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, +static void draw_sphere_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { GLUquadricObj *qobj; @@ -1100,7 +1100,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned glPopMatrix(); } -static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth) +static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth, float length, float zwidth) { int segments = 0; @@ -1128,7 +1128,7 @@ static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float l } } -static void draw_b_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, +static void draw_b_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { float xwidth, length, zwidth; @@ -1242,7 +1242,7 @@ static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float len } } -static void draw_wire_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, +static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { Mat4 *bbones = NULL; @@ -1293,7 +1293,7 @@ static void draw_wire_bone(int dt, int armflag, int boneflag, short constflag, u draw_wire_bone_segments(pchan, bbones, length, segments); } -static void draw_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, float length) +static void draw_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, float length) { /* Draw a 3d octahedral bone, we use normalized space based on length, @@ -1364,7 +1364,7 @@ static void draw_bone(int dt, int armflag, int boneflag, short constflag, unsign } static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, - int dt, int armflag, int boneflag, unsigned int id, float length) + const short dt, int armflag, int boneflag, unsigned int id, float length) { if (ob == NULL) return; @@ -1657,7 +1657,7 @@ static void bone_matrix_translate_y(float mat[][4], float y) /* assumes object is Armature with pose */ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - int dt, const unsigned char ob_wire_col[4], + const short dt, const unsigned char ob_wire_col[4], const short do_const_color, const short is_outline) { RegionView3D *rv3d = ar->regiondata; @@ -2082,7 +2082,7 @@ static void get_matrix_editbone(EditBone *eBone, float bmat[][4]) add_v3_v3(bmat[3], eBone->head); } -static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) +static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) { RegionView3D *rv3d = ar->regiondata; EditBone *eBone; @@ -2559,7 +2559,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) /* called from drawobject.c, return 1 if nothing was drawn * (ob_wire_col == NULL) when drawing ghost */ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - int dt, int flag, const unsigned char ob_wire_col[4], + const short dt, const short dflag, const unsigned char ob_wire_col[4], const short is_outline) { Object *ob = base->object; @@ -2613,7 +2613,7 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (arm->ghostep) draw_ghost_poses(scene, v3d, ar, base); } - if ((flag & DRAW_SCENESET) == 0) { + if ((dflag & DRAW_SCENESET) == 0) { if (ob == OBACT) arm->flag |= ARM_POSEMODE; else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) { @@ -2624,7 +2624,7 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } } - draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (flag & DRAW_CONSTCOLOR), is_outline); + draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline); arm->flag &= ~ARM_POSEMODE; if (ob->mode & OB_MODE_POSE) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index edb40adfc67..15473492b9d 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -333,7 +333,7 @@ static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], s /* check for glsl drawing */ -int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt) +int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt) { if (!GPU_glsl_support()) return 0; @@ -1190,7 +1190,7 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z) } static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - int dt, int flag, const unsigned char ob_wire_col[4]) + const short dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); @@ -1213,7 +1213,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if (drawcone && !v3d->transp) { /* in this case we need to draw delayed */ - add_view3d_after(&v3d->afterdraw_transp, base, flag); + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); return; } @@ -1232,7 +1232,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, /* lamp center */ copy_v3_v3(vec, ob->obmat[3]); - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { /* for AA effects */ curcol[0] = ob_wire_col[0]; curcol[1] = ob_wire_col[1]; @@ -1243,7 +1243,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if (lampsize > 0.0f) { - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { if (ob->id.us > 1) { if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155); else glColor4ub(0x77, 0xCC, 0xCC, 155); @@ -1257,7 +1257,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, drawcircball(GL_POLYGON, vec, lampsize, imat); /* restore */ - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { if (ob->id.us > 1) glColor4ubv(curcol); } @@ -1492,7 +1492,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, glDisable(GL_BLEND); - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { /* restore for drawing extra stuff */ glColor3ubv(ob_wire_col); } @@ -1558,8 +1558,8 @@ static void draw_bundle_sphere(void) } static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d, - MovieClip *clip, MovieTrackingObject *tracking_object, int flag, - int *global_track_index, int draw_selected) + MovieClip *clip, MovieTrackingObject *tracking_object, + const short dflag, int *global_track_index, int draw_selected) { MovieTracking *tracking = &clip->tracking; MovieTrackingTrack *track; @@ -1602,7 +1602,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D if ((track->flag & TRACK_HAS_BUNDLE) == 0) continue; - if (flag & DRAW_PICKING) + if (dflag & DRAW_PICKING) glLoadName(base->selcol + (tracknr << 16)); glPushMatrix(); @@ -1668,7 +1668,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D glPopMatrix(); - if ((flag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) { + if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) { float pos[3]; unsigned char tcol[4]; @@ -1682,7 +1682,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D tracknr++; } - if ((flag & DRAW_PICKING) == 0) { + if ((dflag & DRAW_PICKING) == 0) { if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) { MovieTrackingReconstruction *reconstruction; reconstruction = BKE_tracking_object_reconstruction(tracking, tracking_object); @@ -1713,7 +1713,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D } static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, - int flag, const unsigned char ob_wire_col[4], + const short dflag, const unsigned char ob_wire_col[4], int draw_selected) { MovieTracking *tracking = &clip->tracking; @@ -1734,7 +1734,7 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, tracking_object = tracking->objects.first; while (tracking_object) { draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object, - flag, &global_track_index, draw_selected); + dflag, &global_track_index, draw_selected); tracking_object = tracking_object->next; } @@ -1744,17 +1744,17 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { glColor3ubv(ob_wire_col); } - if (flag & DRAW_PICKING) + if (dflag & DRAW_PICKING) glLoadName(base->selcol); } /* flag similar to draw_object() */ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - int flag, const unsigned char ob_wire_col[4]) + const short dflag, const unsigned char ob_wire_col[4]) { /* a standing up pyramid with (0,0,0) as top */ Camera *cam; @@ -1768,13 +1768,13 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base /* draw data for movie clip set as active for scene */ if (clip) { - draw_viewport_reconstruction(scene, base, v3d, clip, flag, ob_wire_col, FALSE); - draw_viewport_reconstruction(scene, base, v3d, clip, flag, ob_wire_col, TRUE); + draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, FALSE); + draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, TRUE); } #ifdef VIEW3D_CAMERA_BORDER_HACK if (is_view && !(G.f & G_PICKSEL)) { - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { view3d_camera_border_hack_col[0] = ob_wire_col[0]; view3d_camera_border_hack_col[1] = ob_wire_col[1]; view3d_camera_border_hack_col[2] = ob_wire_col[2]; @@ -1851,7 +1851,7 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base glEnd(); } - if (flag == 0) { + if (dflag == 0) { if (cam->flag & (CAM_SHOWLIMITS + CAM_SHOWMIST)) { float nobmat[4][4]; World *wrld; @@ -3146,7 +3146,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index) } static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt) + Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt) { Mesh *me = ob->data; @@ -3353,7 +3353,8 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) } } -static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag) +static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dt, const short dflag) { Object *ob = base->object; Mesh *me = ob->data; @@ -3439,7 +3440,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D else if (dt == OB_SOLID) { if (draw_flags & DRAW_MODIFIERS_PREVIEW) { /* for object selection draws no shade */ - if (flag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material); } else { @@ -3541,7 +3542,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D UI_ThemeColor(TH_GROUP_ACTIVE); else if (ob->flag & OB_FROMGROUP) UI_ThemeColorShade(TH_GROUP_ACTIVE, -16); - else if (flag != DRAW_CONSTCOLOR) + else if (dflag != DRAW_CONSTCOLOR) UI_ThemeColor(is_obact ? TH_ACTIVE : TH_SELECT); else glColor3ub(80, 80, 80); @@ -3550,7 +3551,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (ob->flag & OB_FROMGROUP) UI_ThemeColor(TH_GROUP); else { - if (ob->dtx & OB_DRAWWIRE && flag == DRAW_CONSTCOLOR) + if (ob->dtx & OB_DRAWWIRE && dflag == DRAW_CONSTCOLOR) glColor3ub(80, 80, 80); else UI_ThemeColor(TH_WIRE); @@ -3607,7 +3608,8 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* returns 1 if nothing was drawn, for detecting to draw an object center */ -static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag) +static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dt, const short dflag) { Object *ob = base->object; Object *obedit = scene->obedit; @@ -3671,7 +3673,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D (check_alpha) ? &do_alpha_after : NULL); } - draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag); + draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, dflag); GPU_end_object_materials(); @@ -3679,20 +3681,20 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } } - if ((flag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { - add_view3d_after(&v3d->afterdraw_xraytransp, base, flag); + ED_view3d_after_add(&v3d->afterdraw_xraytransp, base, dflag); } else { - add_view3d_after(&v3d->afterdraw_transp, base, flag); + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); } } else if (ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) { /* special case xray+transp when alpha is 1.0, without this the object vanishes */ if (v3d->xray == 0 && v3d->transp == 0) { - add_view3d_after(&v3d->afterdraw_xray, base, flag); + ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); } } } @@ -3925,7 +3927,7 @@ static void drawCurveDMWired(Object *ob) } /* return 1 when nothing was drawn */ -static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt) +static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -3958,7 +3960,7 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B /* returns 1 when nothing was drawn */ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - int dt, const unsigned char ob_wire_col[4]) + const short dt, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -5585,7 +5587,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - int dt, const unsigned char ob_wire_col[4]) + const short dt, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -5913,7 +5915,7 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[ } /* return 1 if nothing was drawn */ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - int dt, const unsigned char ob_wire_col[4]) + const short dt, const unsigned char ob_wire_col[4]) { Object *ob = base->object; MetaBall *mb; @@ -6547,7 +6549,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ } /* flag can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) +void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) { static int warning_recursive = 0; ModifierData *md = NULL; @@ -6581,12 +6583,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) return; /* xray delay? */ - if ((flag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ if (!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY) && !(ob->dtx & OB_DRAWTRANSP)) { - add_view3d_after(&v3d->afterdraw_xray, base, flag); + ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); return; } } @@ -6614,7 +6616,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) ED_view3d_init_mats_rv3d_gl(ob, rv3d); /* which wire color */ - if ((flag & DRAW_CONSTCOLOR) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { project_short(ar, ob->obmat[3], &base->sx); @@ -6679,8 +6681,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && ob->type != OB_MESH) { - if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (flag & DRAW_SCENESET) == 0) { - if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(flag & DRAW_PICKING)) { + if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { + if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(dflag & DRAW_PICKING)) { drawObjectSelect(scene, v3d, ar, base, ob_wire_col); } @@ -6689,8 +6691,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) switch (ob->type) { case OB_MESH: - empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, flag); - if (flag != DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself + empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, dflag); + if (dflag != DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself break; case OB_FONT: @@ -6831,7 +6833,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) break; case OB_LAMP: if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - drawlamp(scene, v3d, rv3d, base, dt, flag, ob_wire_col); + drawlamp(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); if (dtx || (base->flag & SELECT)) glMultMatrixf(ob->obmat); } break; @@ -6839,12 +6841,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0 || (rv3d->persp == RV3D_CAMOB && v3d->camera == ob)) /* special exception for active camera */ { - drawcamera(scene, v3d, rv3d, base, flag, ob_wire_col); + drawcamera(scene, v3d, rv3d, base, dflag, ob_wire_col); break; } case OB_SPEAKER: if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) - drawspeaker(scene, v3d, rv3d, ob, flag); + drawspeaker(scene, v3d, rv3d, ob, dflag); break; case OB_LATTICE: if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { @@ -6862,7 +6864,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) else { if (dt > OB_WIRE) GPU_enable_material(0, NULL); /* we use default material */ - empty_object = draw_armature(scene, v3d, ar, base, dt, flag, ob_wire_col, FALSE); + empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, FALSE); if (dt > OB_WIRE) GPU_disable_material(); } @@ -6876,7 +6878,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { - if (ob->soft /*&& flag & OB_SBMOTION*/) { + if (ob->soft /*&& dflag & OB_SBMOTION*/) { float mrt[3][3], msc[3][3], mtr[3][3]; SoftBody *sb = NULL; float tipw = 0.5f, tiph = 0.5f, drawsize = 4.0f; @@ -6901,7 +6903,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* code for new particle system */ if ((warning_recursive == 0) && (ob->particlesystem.first) && - (flag & DRAW_PICKING) == 0 && + (dflag & DRAW_PICKING) == 0 && (ob != scene->obedit) ) { @@ -6935,7 +6937,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* draw edit particles last so that they can draw over child particles */ if ( (warning_recursive == 0) && - (flag & DRAW_PICKING) == 0 && + (dflag & DRAW_PICKING) == 0 && (!scene->obedit)) { @@ -7093,7 +7095,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if (dtx & OB_DRAWNAME) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ /* but, we also don't draw names for sets or duplicators */ - if (flag == 0) { + if (dflag == 0) { const float zero[3] = {0, 0, 0}; view3d_cached_text_draw_add(zero, ob->id.name + 2, 10, 0, ob_wire_col); } @@ -7151,13 +7153,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) do_draw_center = DESELECT; if (do_draw_center != -1) { - if (flag & DRAW_PICKING) { + if (dflag & DRAW_PICKING) { /* draw a single point for opengl selection */ glBegin(GL_POINTS); glVertex3fv(ob->obmat[3]); glEnd(); } - else if ((flag & DRAW_CONSTCOLOR) == 0) { + else if ((dflag & DRAW_CONSTCOLOR) == 0) { /* we don't draw centers for duplicators and sets */ if (U.obcenter_dia > 0) { /* check > 0 otherwise grease pencil can draw into the circle select which is annoying. */ @@ -7168,7 +7170,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } /* not for sets, duplicators or picking */ - if (flag == 0 && (v3d->flag & V3D_HIDE_HELPLINES) == 0 && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if (dflag == 0 && (v3d->flag & V3D_HIDE_HELPLINES) == 0 && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { ListBase *list; /* draw hook center and offset line */ @@ -7510,7 +7512,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* helper function for drawing object instances - meshes */ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, int dt, int outline) + Object *ob, const short dt, int outline) { Mesh *me = ob->data; DerivedMesh *dm = NULL, *edm = NULL; @@ -7558,7 +7560,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if (dm) dm->release(dm); } -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int outline) +void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const short dt, int outline) { if (ob == NULL) return; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index a36c14151e6..6d9507ebff1 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1728,17 +1728,17 @@ static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d, typedef struct View3DAfter { struct View3DAfter *next, *prev; struct Base *base; - int flag; + short dflag; } View3DAfter; /* temp storage of Objects that need to be drawn as last */ -void add_view3d_after(ListBase *lb, Base *base, int flag) +void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag) { View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after"); BLI_assert((base->flag & OB_FROMDUPLI) == 0); BLI_addtail(lb, v3da); v3da->base = base; - v3da->flag = flag; + v3da->dflag = dflag; } /* disables write in zbuffer and draws it over */ @@ -1751,7 +1751,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d) for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) { next = v3da->next; - draw_object(scene, ar, v3d, v3da->base, v3da->flag); + draw_object(scene, ar, v3d, v3da->base, v3da->dflag); BLI_remlink(&v3d->afterdraw_transp, v3da); MEM_freeN(v3da); } @@ -1772,7 +1772,7 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear) v3d->xray = TRUE; for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) { next = v3da->next; - draw_object(scene, ar, v3d, v3da->base, v3da->flag); + draw_object(scene, ar, v3d, v3da->base, v3da->dflag); BLI_remlink(&v3d->afterdraw_xray, v3da); MEM_freeN(v3da); } @@ -1793,7 +1793,7 @@ static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, int c for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) { next = v3da->next; - draw_object(scene, ar, v3d, v3da->base, v3da->flag); + draw_object(scene, ar, v3d, v3da->base, v3da->dflag); BLI_remlink(&v3d->afterdraw_xraytransp, v3da); MEM_freeN(v3da); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index de259efdf59..3c6a0dd4b9f 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -53,13 +53,17 @@ struct wmWindowManager; #define BL_NEAR_CLIP 0.001 /* drawing flags: */ -#define DRAW_PICKING 1 -#define DRAW_CONSTCOLOR 2 -#define DRAW_SCENESET 4 +enum { + DRAW_PICKING = (1 << 0), + DRAW_CONSTCOLOR = (1 << 1), + DRAW_SCENESET = (1 << 2) +}; /* draw_mesh_fancy/draw_mesh_textured draw_flags */ -#define DRAW_MODIFIERS_PREVIEW 1 -#define DRAW_FACE_SELECT 2 +enum { + DRAW_MODIFIERS_PREVIEW = (1 << 0), + DRAW_FACE_SELECT = (1 << 1) +}; /* view3d_header.c */ void VIEW3D_OT_layers(struct wmOperatorType *ot); @@ -112,24 +116,27 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ -void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, int flag); -int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, int dt); -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, int dt, int outline); +void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); +int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const short dt); +void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const short dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); void drawaxes(float size, char drawtype); void view3d_cached_text_draw_begin(void); void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4]); void view3d_cached_text_draw_end(View3D * v3d, ARegion * ar, int depth_write, float mat[][4]); -#define V3D_CACHE_TEXT_ZBUF (1 << 0) -#define V3D_CACHE_TEXT_WORLDSPACE (1 << 1) -#define V3D_CACHE_TEXT_ASCII (1 << 2) -#define V3D_CACHE_TEXT_GLOBALSPACE (1 << 3) -#define V3D_CACHE_TEXT_LOCALCLIP (1 << 4) + +enum { + V3D_CACHE_TEXT_ZBUF = (1 << 0), + V3D_CACHE_TEXT_WORLDSPACE = (1 << 1), + V3D_CACHE_TEXT_ASCII = (1 << 2), + V3D_CACHE_TEXT_GLOBALSPACE = (1 << 3), + V3D_CACHE_TEXT_LOCALCLIP = (1 << 4) +}; /* drawarmature.c */ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, - int dt, int flag, const unsigned char ob_wire_col[4], + const short dt, const short dflag, const unsigned char ob_wire_col[4], const short is_outline); /* drawmesh.c */ @@ -142,7 +149,7 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d, void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar); void draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, int (*func)(void *)); void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); -void add_view3d_after(ListBase *lb, Base *base, int flag); +void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag); void circf(float x, float y, float rad); void circ(float x, float y, float rad); -- cgit v1.2.3 From 5e29381825bb7e84b6e3535bd6ca6a53c8079e2a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 12:09:25 +0000 Subject: mango request - optionally display the histogram as lines (not filled areas). - expand the enum for faster access. - keep the sample line displayed after doing the line sample (running again clears). --- release/scripts/startup/bl_ui/space_image.py | 10 ++- source/blender/editors/interface/interface_draw.c | 83 +++++++++++++++-------- source/blender/editors/space_image/image_draw.c | 22 ++++++ source/blender/editors/space_image/image_intern.h | 1 + source/blender/editors/space_image/image_ops.c | 14 +++- source/blender/editors/space_image/space_image.c | 7 +- source/blender/makesdna/DNA_color_types.h | 12 +++- source/blender/makesrna/intern/rna_color.c | 16 +++-- 8 files changed, 122 insertions(+), 43 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 861a5670393..44fb429ffe7 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -502,9 +502,12 @@ class IMAGE_PT_view_histogram(Panel): layout = self.layout sima = context.space_data + hist = sima.scopes.histogram layout.template_histogram(sima.scopes, "histogram") - layout.prop(sima.scopes.histogram, "mode", icon_only=True) + row = layout.row(align=True) + row.prop(hist, "mode", icon_only=True, expand=True) + row.prop(hist, "show_line", text="") class IMAGE_PT_view_waveform(Panel): @@ -560,10 +563,13 @@ class IMAGE_PT_sample_line(Panel): layout = self.layout sima = context.space_data + hist = sima.sample_histogram layout.operator("image.sample_line") layout.template_histogram(sima, "sample_histogram") - layout.prop(sima.sample_histogram, "mode") + row = layout.row(align=True) + row.prop(hist, "mode", expand=True) + row.prop(hist, "show_line", text="") class IMAGE_PT_scope_sample(Panel): diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index a0b418c1a9a..1300c1d266c 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -658,37 +658,59 @@ static void draw_scope_end(rctf *rect, GLint *scissor) } static void histogram_draw_one(float r, float g, float b, float alpha, - float x, float y, float w, float h, float *data, int res) + float x, float y, float w, float h, float *data, int res, const short is_line) { int i; - /* under the curve */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4f(r, g, b, alpha); - - glShadeModel(GL_FLAT); - glBegin(GL_QUAD_STRIP); - glVertex2f(x, y); - glVertex2f(x, y + (data[0] * h)); - for (i = 1; i < res; i++) { - float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); - glVertex2f(x2, y); + if (is_line) { + + glLineWidth(1.5); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor4f(r, g, b, alpha); + + /* curve outline */ + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glEnable(GL_LINE_SMOOTH); + glBegin(GL_LINE_STRIP); + for (i = 0; i < res; i++) { + float x2 = x + i * (w / (float)res); + glVertex2f(x2, y + (data[i] * h)); + } + glEnd(); + glDisable(GL_LINE_SMOOTH); + + glLineWidth(1.0); } - glEnd(); - - /* curve outline */ - glColor4f(0.f, 0.f, 0.f, 0.25f); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_LINE_SMOOTH); - glBegin(GL_LINE_STRIP); - for (i = 0; i < res; i++) { - float x2 = x + i * (w / (float)res); - glVertex2f(x2, y + (data[i] * h)); + else { + /* under the curve */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor4f(r, g, b, alpha); + + glShadeModel(GL_FLAT); + glBegin(GL_QUAD_STRIP); + glVertex2f(x, y); + glVertex2f(x, y + (data[0] * h)); + for (i = 1; i < res; i++) { + float x2 = x + i * (w / (float)res); + glVertex2f(x2, y + (data[i] * h)); + glVertex2f(x2, y); + } + glEnd(); + + /* curve outline */ + glColor4f(0.f, 0.f, 0.f, 0.25f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_LINE_SMOOTH); + glBegin(GL_LINE_STRIP); + for (i = 0; i < res; i++) { + float x2 = x + i * (w / (float)res); + glVertex2f(x2, y + (data[i] * h)); + } + glEnd(); + glDisable(GL_LINE_SMOOTH); } - glEnd(); - glDisable(GL_LINE_SMOOTH); } void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti) @@ -698,6 +720,7 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) rctf rect; int i; float w, h; + const short is_line = (hist->flag & HISTO_FLAG_LINE) != 0; //float alpha; GLint scissor[4]; @@ -731,14 +754,14 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) } if (hist->mode == HISTO_MODE_LUMA) - histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res); + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line); else { if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) - histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res); + histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_G) - histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res); + histogram_draw_one(0.0, 1.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_g, res, is_line); if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_B) - histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res); + histogram_draw_one(0.0, 0.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_b, res, is_line); } /* outline, scale gripper */ diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 0440aff3f65..998ebac1cb9 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -578,6 +578,28 @@ void draw_image_grease_pencil(bContext *C, short onlyv2d) } } +void draw_image_sample_line(SpaceImage *sima) +{ + if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) { + Histogram *hist = &sima->sample_line_hist; + + glBegin(GL_LINES); + glColor3ub(0, 0, 0); + glVertex2fv(hist->co[0]); + glVertex2fv(hist->co[1]); + glEnd(); + + setlinestyle(1); + glBegin(GL_LINES); + glColor3ub(255, 255, 255); + glVertex2fv(hist->co[0]); + glVertex2fv(hist->co[1]); + glEnd(); + setlinestyle(0); + + } +} + /* XXX becomes WM paint cursor */ #if 0 static void draw_image_view_tool(Scene *scene) diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 121130ec536..0d3a7614f10 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -54,6 +54,7 @@ extern const char *image_context_dir[]; /* doc access */ /* image_draw.c */ void draw_image_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene); void draw_image_grease_pencil(struct bContext *C, short onlyv2d); +void draw_image_sample_line(struct SpaceImage *sima); /* image_ops.c */ int space_image_main_area_poll(struct bContext *C); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 02b95f8e7c8..5075147869d 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2137,7 +2137,14 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) hist->x_resolution = 256; hist->xmax = 1.0f; hist->ymax = 1.0f; - + + /* persistent draw */ + hist->co[0][0] = x1f; + hist->co[0][1] = y1f; + hist->co[1][0] = x2f; + hist->co[1][1] = y2f; + hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */ + for (i = 0; i < 256; i++) { x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f); y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f); @@ -2179,7 +2186,10 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) static int image_sample_line_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); - + + Histogram *hist = &sima->sample_line_hist; + hist->flag &= ~HISTO_FLAG_SAMPLELINE; + if (!ED_space_image_has_buffer(sima)) return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a2a16fd84a8..6652a7470c2 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -824,15 +824,18 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) draw_uvedit_main(sima, ar, scene, obedit, obact); ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); - + /* Grease Pencil too (in addition to UV's) */ draw_image_grease_pencil((bContext *)C, 1); + /* sample line */ + draw_image_sample_line(sima); + UI_view2d_view_restore(C); /* draw Grease Pencil - screen space only */ draw_image_grease_pencil((bContext *)C, 0); - + /* scrollers? */ #if 0 scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_UNIT_VALUES, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 676389ffeea..dd2b38ffcf5 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -102,6 +102,11 @@ typedef enum CurveMappingPreset { #define HISTO_MODE_G 3 #define HISTO_MODE_B 4 +enum { + HISTO_FLAG_LINE = (1 << 0), + HISTO_FLAG_SAMPLELINE = (1 << 1) +}; + typedef struct Histogram { int channels; int x_resolution; @@ -110,8 +115,13 @@ typedef struct Histogram { float data_b[256]; float data_luma[256]; float xmax, ymax; - int mode; + short mode; + short flag; int height; + + /* sample line only */ + /* image coords src -> est */ + float co[2][2]; } Histogram; struct ImBuf; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 9a69cfc7f15..bd0e6c36c48 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -570,11 +570,11 @@ static void rna_def_histogram(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem prop_mode_items[] = { - {HISTO_MODE_LUMA, "LUMA", ICON_COLOR, "Luma", ""}, - {HISTO_MODE_RGB, "RGB", ICON_COLOR, "Red Green Blue", ""}, - {HISTO_MODE_R, "R", ICON_COLOR, "Red", ""}, - {HISTO_MODE_G, "G", ICON_COLOR, "Green", ""}, - {HISTO_MODE_B, "B", ICON_COLOR, "Blue", ""}, + {HISTO_MODE_LUMA, "LUMA", 0, "Luma", "Luma"}, + {HISTO_MODE_RGB, "RGB", 0, "RGB", "Red Green Blue"}, + {HISTO_MODE_R, "R", 0, "R", "Red"}, + {HISTO_MODE_G, "G", 0, "G", "Green"}, + {HISTO_MODE_B, "B", 0, "B", "Blue"}, {0, NULL, 0, NULL, NULL} }; @@ -585,7 +585,11 @@ static void rna_def_histogram(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, prop_mode_items); RNA_def_property_ui_text(prop, "Mode", "Channels to display when drawing the histogram"); - + + prop = RNA_def_property(srna, "show_line", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", HISTO_FLAG_LINE); + RNA_def_property_ui_text(prop, "Show Line", "Displays lines rather then filled shapes"); + RNA_def_property_ui_icon(prop, ICON_IPO, 0); } static void rna_def_scopes(BlenderRNA *brna) -- cgit v1.2.3 From 7496a58cfb3e9c77645265af262543b357f9e361 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Sun, 10 Jun 2012 12:26:33 +0000 Subject: Applied and completed a compositor patch by Brecht to use signalling and waiting in scheduling and worker threads instead of continuous loops with sleep times. This should help reduce unnecessary wait times in Tile. --- source/blender/blenlib/BLI_threads.h | 1 + source/blender/blenlib/intern/threads.c | 51 +++++++++++++---- .../compositor/intern/COM_ExecutionGroup.cpp | 3 +- .../compositor/intern/COM_WorkScheduler.cpp | 65 ++++++---------------- .../blender/compositor/intern/COM_WorkScheduler.h | 13 ----- 5 files changed, 60 insertions(+), 73 deletions(-) diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index b13da9f0dd4..fb8771722c1 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -136,6 +136,7 @@ void *BLI_thread_queue_pop(ThreadQueue *queue); void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms); int BLI_thread_queue_size(ThreadQueue *queue); +void BLI_thread_queue_wait_finish(ThreadQueue *queue); void BLI_thread_queue_nowait(ThreadQueue *queue); #endif diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index f9f677d7c22..dc4c15a82fc 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -520,8 +520,10 @@ void BLI_insert_work(ThreadedWorker *worker, void *param) struct ThreadQueue { GSQueue *queue; pthread_mutex_t mutex; - pthread_cond_t cond; - int nowait; + pthread_cond_t push_cond; + pthread_cond_t finish_cond; + volatile int nowait; + volatile int cancelled; }; ThreadQueue *BLI_thread_queue_init(void) @@ -532,14 +534,17 @@ ThreadQueue *BLI_thread_queue_init(void) queue->queue = BLI_gsqueue_new(sizeof(void *)); pthread_mutex_init(&queue->mutex, NULL); - pthread_cond_init(&queue->cond, NULL); + pthread_cond_init(&queue->push_cond, NULL); + pthread_cond_init(&queue->finish_cond, NULL); return queue; } void BLI_thread_queue_free(ThreadQueue *queue) { - pthread_cond_destroy(&queue->cond); + /* destroy everything, assumes no one is using queue anymore */ + pthread_cond_destroy(&queue->finish_cond); + pthread_cond_destroy(&queue->push_cond); pthread_mutex_destroy(&queue->mutex); BLI_gsqueue_free(queue->queue); @@ -554,7 +559,7 @@ void BLI_thread_queue_push(ThreadQueue *queue, void *work) BLI_gsqueue_push(queue->queue, &work); /* signal threads waiting to pop */ - pthread_cond_signal(&queue->cond); + pthread_cond_signal(&queue->push_cond); pthread_mutex_unlock(&queue->mutex); } @@ -565,11 +570,15 @@ void *BLI_thread_queue_pop(ThreadQueue *queue) /* wait until there is work */ pthread_mutex_lock(&queue->mutex); while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) - pthread_cond_wait(&queue->cond, &queue->mutex); - + pthread_cond_wait(&queue->push_cond, &queue->mutex); + /* if we have something, pop it */ - if (!BLI_gsqueue_is_empty(queue->queue)) + if (!BLI_gsqueue_is_empty(queue->queue)) { BLI_gsqueue_pop(queue->queue, &work); + + if(BLI_gsqueue_is_empty(queue->queue)) + pthread_cond_broadcast(&queue->finish_cond); + } pthread_mutex_unlock(&queue->mutex); @@ -623,16 +632,20 @@ void *BLI_thread_queue_pop_timeout(ThreadQueue *queue, int ms) /* wait until there is work */ pthread_mutex_lock(&queue->mutex); while (BLI_gsqueue_is_empty(queue->queue) && !queue->nowait) { - if (pthread_cond_timedwait(&queue->cond, &queue->mutex, &timeout) == ETIMEDOUT) + if (pthread_cond_timedwait(&queue->push_cond, &queue->mutex, &timeout) == ETIMEDOUT) break; else if (PIL_check_seconds_timer() - t >= ms * 0.001) break; } /* if we have something, pop it */ - if (!BLI_gsqueue_is_empty(queue->queue)) + if (!BLI_gsqueue_is_empty(queue->queue)) { BLI_gsqueue_pop(queue->queue, &work); - + + if(BLI_gsqueue_is_empty(queue->queue)) + pthread_cond_broadcast(&queue->finish_cond); + } + pthread_mutex_unlock(&queue->mutex); return work; @@ -656,10 +669,23 @@ void BLI_thread_queue_nowait(ThreadQueue *queue) queue->nowait = 1; /* signal threads waiting to pop */ - pthread_cond_signal(&queue->cond); + pthread_cond_broadcast(&queue->push_cond); + pthread_mutex_unlock(&queue->mutex); +} + +void BLI_thread_queue_wait_finish(ThreadQueue *queue) +{ + /* wait for finish condition */ + pthread_mutex_lock(&queue->mutex); + + while(!BLI_gsqueue_is_empty(queue->queue)) + pthread_cond_wait(&queue->finish_cond, &queue->mutex); + pthread_mutex_unlock(&queue->mutex); } +/* ************************************************ */ + void BLI_begin_threaded_malloc(void) { if (thread_levels == 0) { @@ -674,3 +700,4 @@ void BLI_end_threaded_malloc(void) if (thread_levels == 0) MEM_set_lock_callback(NULL, NULL); } + diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 44b3c8dafbb..481b83c81a3 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -351,7 +351,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph) startIndex = index+1; } } - PIL_sleep_ms(10); + + WorkScheduler::finish(); if (bTree->test_break && bTree->test_break(bTree->tbh)) { breaked = true; diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 172107f720b..ba8bfe55310 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -39,8 +39,6 @@ #endif -/// @brief global state of the WorkScheduler. -static WorkSchedulerState state; /// @brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is created static vector cpudevices; @@ -68,43 +66,29 @@ static bool openclActive = false; #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE void *WorkScheduler::thread_execute_cpu(void *data) { - bool continueLoop = true; Device *device = (Device*)data; - while (continueLoop) { - WorkPackage *work = (WorkPackage*)BLI_thread_queue_pop(cpuqueue); - if (work) { - device->execute(work); - delete work; - } - PIL_sleep_ms(10); - - if (WorkScheduler::isStopping()) { - continueLoop = false; - } + WorkPackage *work; + + while ((work = (WorkPackage*)BLI_thread_queue_pop(cpuqueue))) { + device->execute(work); + delete work; } + return NULL; } void *WorkScheduler::thread_execute_gpu(void *data) { - bool continueLoop = true; Device *device = (Device*)data; - while (continueLoop) { - WorkPackage *work = (WorkPackage*)BLI_thread_queue_pop(gpuqueue); - if (work) { - device->execute(work); - delete work; - } - PIL_sleep_ms(10); - - if (WorkScheduler::isStopping()) { - continueLoop = false; - } + WorkPackage *work; + + while ((work = (WorkPackage*)BLI_thread_queue_pop(gpuqueue))) { + device->execute(work); + delete work; } + return NULL; } - -bool WorkScheduler::isStopping() {return state == COM_WSS_STOPPING;} #endif @@ -135,7 +119,6 @@ void WorkScheduler::start(CompositorContext &context) #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE unsigned int index; cpuqueue = BLI_thread_queue_init(); - BLI_thread_queue_nowait(cpuqueue); BLI_init_threads(&cputhreads, thread_execute_cpu, cpudevices.size()); for (index = 0 ; index < cpudevices.size() ; index ++) { Device *device = cpudevices[index]; @@ -144,7 +127,6 @@ void WorkScheduler::start(CompositorContext &context) #ifdef COM_OPENCL_ENABLED if (context.getHasActiveOpenCLDevices()) { gpuqueue = BLI_thread_queue_init(); - BLI_thread_queue_nowait(gpuqueue); BLI_init_threads(&gputhreads, thread_execute_gpu, gpudevices.size()); for (index = 0 ; index < gpudevices.size() ; index ++) { Device *device = gpudevices[index]; @@ -157,45 +139,39 @@ void WorkScheduler::start(CompositorContext &context) } #endif #endif - state = COM_WSS_STARTED; } void WorkScheduler::finish() { #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE #ifdef COM_OPENCL_ENABLED if (openclActive) { - while (BLI_thread_queue_size(gpuqueue) + BLI_thread_queue_size(cpuqueue) > 0) { - PIL_sleep_ms(10); - } + BLI_thread_queue_wait_finish(gpuqueue); + BLI_thread_queue_wait_finish(cpuqueue); } else { - while (BLI_thread_queue_size(cpuqueue) > 0) { - PIL_sleep_ms(10); - } + BLI_thread_queue_wait_finish(cpuqueue); } #else - while (BLI_thread_queue_size(cpuqueue) > 0) { - PIL_sleep_ms(10); - } + BLI_thread_queue_wait_finish(cpuqueue); #endif #endif } void WorkScheduler::stop() { - state = COM_WSS_STOPPING; #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE + BLI_thread_queue_nowait(cpuqueue); BLI_end_threads(&cputhreads); BLI_thread_queue_free(cpuqueue); cpuqueue = NULL; #ifdef COM_OPENCL_ENABLED if (openclActive) { + BLI_thread_queue_nowait(gpuqueue); BLI_end_threads(&gputhreads); BLI_thread_queue_free(gpuqueue); gpuqueue = NULL; } #endif #endif - state = COM_WSS_STOPPED; } bool WorkScheduler::hasGPUDevices() @@ -218,8 +194,6 @@ extern void clContextError(const char *errinfo, const void *private_info, size_t void WorkScheduler::initialize() { - state = COM_WSS_UNKNOWN; - #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE int numberOfCPUThreads = BLI_system_thread_count(); @@ -298,8 +272,6 @@ void WorkScheduler::initialize() } #endif #endif - - state = COM_WSS_INITIALIZED; } void WorkScheduler::deinitialize() @@ -329,5 +301,4 @@ void WorkScheduler::deinitialize() } #endif #endif - state = COM_WSS_DEINITIALIZED; } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h index 0de1763749e..b03b514d139 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.h +++ b/source/blender/compositor/intern/COM_WorkScheduler.h @@ -31,19 +31,6 @@ extern "C" { #include "COM_defines.h" #include "COM_Device.h" -// STATES -/** @brief states of the WorkScheduler - * @ingroup execution - */ -typedef enum WorkSchedulerState { - COM_WSS_UNKNOWN = -1, - COM_WSS_INITIALIZED = 0, - COM_WSS_STARTED = 1, - COM_WSS_STOPPING = 2, - COM_WSS_STOPPED = 3, - COM_WSS_DEINITIALIZED = 4 -} WorkSchedulerState; - /** @brief the workscheduler * @ingroup execution */ -- cgit v1.2.3 From c27472c04ef294a1de6ab9804c3b87f5635a8fcd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 12:30:47 +0000 Subject: Synchronize changes with tomato branch --- release/scripts/startup/bl_ui/space_clip.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 10361eeef0d..d0f0f3de276 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -181,16 +181,6 @@ class CLIP_PT_reconstruction_panel: return clip and sc.mode == 'RECONSTRUCTION' and sc.view == 'CLIP' -class CLIP_PT_distortion_panel: - - @classmethod - def poll(cls, context): - sc = context.space_data - clip = sc.clip - - return clip and sc.mode == 'DISTORTION' and sc.view == 'CLIP' - - class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' -- cgit v1.2.3 From 219eca0f515f9a54953566539520fde37f2ea13b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 12:33:27 +0000 Subject: mango request - add alpha to histogram & sample line. --- source/blender/blenkernel/intern/colortools.c | 62 ++++++++++++----------- source/blender/editors/interface/interface_draw.c | 6 ++- source/blender/editors/space_image/image_ops.c | 20 ++++---- source/blender/makesdna/DNA_color_types.h | 18 ++++--- source/blender/makesrna/intern/rna_color.c | 3 +- 5 files changed, 61 insertions(+), 48 deletions(-) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index d15f678f1c5..12dee600532 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -910,7 +910,7 @@ DO_INLINE int get_bin_float(float f) return bin; } -DO_INLINE void save_sample_line(Scopes *scopes, const int idx, const float fx, const float rgb[3], const float ycc[3]) +static void save_sample_line(Scopes *scopes, const int idx, const float fx, const float rgb[3], const float ycc[3]) { float yuv[3]; @@ -953,9 +953,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) double div, divl; float *rf = NULL; unsigned char *rc = NULL; - unsigned int *bin_r, *bin_g, *bin_b, *bin_lum; + unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; int savedlines, saveline; - float rgb[3], ycc[3], luma; + float rgba[4], ycc[3], luma; int ycc_mode = -1; const short is_float = (ibuf->rect_float != NULL); @@ -987,11 +987,12 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) break; } - /* temp table to count pix value for histo */ - bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); - bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); - bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); - bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + /* temp table to count pix value for histogram */ + bin_r = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + bin_g = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + bin_b = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + bin_a = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); + bin_lum = MEM_callocN(256 * sizeof(unsigned int), "temp historgram bins"); /* convert to number of lines with logarithmic scale */ scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y; @@ -1038,27 +1039,28 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) if (is_float) { if (use_color_management) - linearrgb_to_srgb_v3_v3(rgb, rf); + linearrgb_to_srgb_v3_v3(rgba, rf); else - copy_v3_v3(rgb, rf); + copy_v3_v3(rgba, rf); + rgba[3] = rf[3]; } else { - for (c = 0; c < 3; c++) - rgb[c] = rc[c] * INV_255; + for (c = 0; c < 4; c++) + rgba[c] = rc[c] * INV_255; } /* we still need luma for histogram */ - luma = rgb_to_luma(rgb); + luma = rgb_to_luma(rgba); /* check for min max */ if (ycc_mode == -1) { for (c = 0; c < 3; c++) { - if (rgb[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgb[c]; - if (rgb[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgb[c]; + if (rgba[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = rgba[c]; + if (rgba[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = rgba[c]; } } else { - rgb_to_ycc(rgb[0], rgb[1], rgb[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode); + rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode); for (c = 0; c < 3; c++) { ycc[c] *= INV_255; if (ycc[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = ycc[c]; @@ -1066,16 +1068,17 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) } } /* increment count for histo*/ - bin_r[get_bin_float(rgb[0])] += 1; - bin_g[get_bin_float(rgb[1])] += 1; - bin_b[get_bin_float(rgb[2])] += 1; bin_lum[get_bin_float(luma)] += 1; + bin_r[get_bin_float(rgba[0])] += 1; + bin_g[get_bin_float(rgba[1])] += 1; + bin_b[get_bin_float(rgba[2])] += 1; + bin_a[get_bin_float(rgba[3])] += 1; /* save sample if needed */ if (saveline) { const float fx = (float)x / (float)ibuf->x; const int idx = 2 * (ibuf->x * savedlines + x); - save_sample_line(scopes, idx, fx, rgb, ycc); + save_sample_line(scopes, idx, fx, rgba, ycc); } rf += ibuf->channels; @@ -1089,27 +1092,26 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) n = 0; nl = 0; for (x = 0; x < 256; x++) { - if (bin_r[x] > n) - n = bin_r[x]; - if (bin_g[x] > n) - n = bin_g[x]; - if (bin_b[x] > n) - n = bin_b[x]; - if (bin_lum[x] > nl) - nl = bin_lum[x]; + if (bin_lum[x] > nl) nl = bin_lum[x]; + if (bin_r[x] > n) n = bin_r[x]; + if (bin_g[x] > n) n = bin_g[x]; + if (bin_b[x] > n) n = bin_b[x]; + if (bin_a[x] > n) n = bin_a[x]; } div = 1.0 / (double)n; divl = 1.0 / (double)nl; for (x = 0; x < 256; x++) { + scopes->hist.data_luma[x] = bin_lum[x] * divl; scopes->hist.data_r[x] = bin_r[x] * div; scopes->hist.data_g[x] = bin_g[x] * div; scopes->hist.data_b[x] = bin_b[x] * div; - scopes->hist.data_luma[x] = bin_lum[x] * divl; + scopes->hist.data_a[x] = bin_a[x] * div; } + MEM_freeN(bin_lum); MEM_freeN(bin_r); MEM_freeN(bin_g); MEM_freeN(bin_b); - MEM_freeN(bin_lum); + MEM_freeN(bin_a); scopes->ok = 1; } diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 1300c1d266c..f6339d4456f 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -753,8 +753,12 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) fdrawline(rect.xmin + (i / 4.f) * w, rect.ymin, rect.xmin + (i / 4.f) * w, rect.ymax); } - if (hist->mode == HISTO_MODE_LUMA) + if (hist->mode == HISTO_MODE_LUMA) { histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_luma, res, is_line); + } + else if (hist->mode == HISTO_MODE_ALPHA) { + histogram_draw_one(1.0, 1.0, 1.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_a, res, is_line); + } else { if (hist->mode == HISTO_MODE_RGB || hist->mode == HISTO_MODE_R) histogram_draw_one(1.0, 0.0, 0.0, 0.75, rect.xmin, rect.ymin, w, h, hist->data_r, res, is_line); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 5075147869d..97f3bd744dc 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2150,7 +2150,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f); if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y) { - hist->data_luma[i] = hist->data_r[i] = hist->data_g[i] = hist->data_b[i] = 0.0f; + hist->data_luma[i] = hist->data_r[i] = hist->data_g[i] = hist->data_b[i] = hist->data_a[i] = 0.0f; } else { if (ibuf->rect_float) { @@ -2161,17 +2161,19 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) else copy_v3_v3(rgb, fp); - hist->data_r[i] = rgb[0]; - hist->data_g[i] = rgb[1]; - hist->data_b[i] = rgb[2]; - hist->data_luma[i] = rgb_to_luma(rgb); + hist->data_luma[i] = rgb_to_luma(rgb); + hist->data_r[i] = rgb[0]; + hist->data_g[i] = rgb[1]; + hist->data_b[i] = rgb[2]; + hist->data_a[i] = fp[3]; } else if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); - hist->data_r[i] = (float)cp[0] / 255.0f; - hist->data_g[i] = (float)cp[1] / 255.0f; - hist->data_b[i] = (float)cp[2] / 255.0f; - hist->data_luma[i] = (float)rgb_to_luma_byte(cp) / 255.0f; + hist->data_luma[i] = (float)rgb_to_luma_byte(cp) / 255.0f; + hist->data_r[i] = (float)cp[0] / 255.0f; + hist->data_g[i] = (float)cp[1] / 255.0f; + hist->data_b[i] = (float)cp[2] / 255.0f; + hist->data_a[i] = (float)cp[3] / 255.0f; } } } diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index dd2b38ffcf5..99e2a123fe7 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -96,11 +96,14 @@ typedef enum CurveMappingPreset { } CurveMappingPreset; /* histogram->mode */ -#define HISTO_MODE_LUMA 0 -#define HISTO_MODE_RGB 1 -#define HISTO_MODE_R 2 -#define HISTO_MODE_G 3 -#define HISTO_MODE_B 4 +enum { + HISTO_MODE_LUMA = 0, + HISTO_MODE_RGB = 1, + HISTO_MODE_R = 2, + HISTO_MODE_G = 3, + HISTO_MODE_B = 4, + HISTO_MODE_ALPHA = 5 +}; enum { HISTO_FLAG_LINE = (1 << 0), @@ -110,17 +113,18 @@ enum { typedef struct Histogram { int channels; int x_resolution; + float data_luma[256]; float data_r[256]; float data_g[256]; float data_b[256]; - float data_luma[256]; + float data_a[256]; float xmax, ymax; short mode; short flag; int height; /* sample line only */ - /* image coords src -> est */ + /* image coords src -> dst */ float co[2][2]; } Histogram; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index bd0e6c36c48..ce0b396caf7 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -575,9 +575,10 @@ static void rna_def_histogram(BlenderRNA *brna) {HISTO_MODE_R, "R", 0, "R", "Red"}, {HISTO_MODE_G, "G", 0, "G", "Green"}, {HISTO_MODE_B, "B", 0, "B", "Blue"}, + {HISTO_MODE_ALPHA, "A", 0, "A", "Alpha"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "Histogram", NULL); RNA_def_struct_ui_text(srna, "Histogram", "Statistical view of the levels of color in an image"); -- cgit v1.2.3 From f6e21881f5d0f86725836391d20949fe0343bd19 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 13:34:59 +0000 Subject: change RNA_struct_find_function to accept a type rather then a PointerRNA, add a check duplicate functions are not defined. --- source/blender/editors/include/UI_interface.h | 3 ++- source/blender/editors/interface/interface_handlers.c | 7 +++---- source/blender/makesrna/RNA_access.h | 2 +- source/blender/makesrna/intern/rna_access.c | 12 ++++++------ source/blender/makesrna/intern/rna_define.c | 7 +++++++ source/blender/python/intern/bpy_rna.c | 4 ++-- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index b82a0c5e480..bb6f9fad771 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -195,7 +195,8 @@ typedef struct uiLayout uiLayout; /*#define FUN 192*/ /*UNUSED*/ #define BIT 256 -#define BUTPOIN (128 + 64 + 32) +/* button reqyires a pointer */ +#define BUTPOIN (FLO | SHO | CHA) #define BUT (1 << 9) #define ROW (2 << 9) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 8753c427816..a2adbd7a143 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3819,22 +3819,21 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx Histogram *hist = (Histogram *)but->poin; /* rcti rect; */ int changed = 1; - float /* dx, */ dy, yfac = 1.f; /* UNUSED */ + float /* dx, */ dy; /* UNUSED */ /* rect.xmin = but->x1; rect.xmax = but->x2; */ /* rect.ymin = but->y1; rect.ymax = but->y2; */ /* dx = mx - data->draglastx; */ /* UNUSED */ dy = my - data->draglasty; - - + if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { /* resize histogram widget itself */ hist->height = (but->y2 - but->y1) + (data->dragstarty - my); } else { /* scale histogram values */ - yfac = MIN2(powf(hist->ymax, 2.f), 1.f) * 0.5f; + const float yfac = MIN2(powf(hist->ymax, 2.f), 1.f) * 0.5f; hist->ymax += dy * yfac; CLAMP(hist->ymax, 1.f, 100.f); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 37455563ee0..8fc39c95d81 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -675,7 +675,7 @@ int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test); const struct ListBase *RNA_struct_type_properties(StructRNA *srna); PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier); -FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier); +FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier); const struct ListBase *RNA_struct_type_functions(StructRNA *srna); char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 5e8c6b33b0d..c8ca0be8ab7 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -664,12 +664,12 @@ PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifi return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier)); } -FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier) +FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier) { #if 1 FunctionRNA *func; StructRNA *type; - for (type = ptr->type; type; type = type->base) { + for (type = srna; type; type = type->base) { func = (FunctionRNA *)BLI_findstring_ptr(&type->functions, identifier, offsetof(FunctionRNA, identifier)); if (func) { return func; @@ -683,7 +683,7 @@ FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier) PropertyRNA *iterprop; FunctionRNA *func; - RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr); + RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr); iterprop = RNA_struct_find_property(&tptr, "functions"); func = NULL; @@ -5132,7 +5132,7 @@ int RNA_function_call_lookup(bContext *C, ReportList *reports, PointerRNA *ptr, { FunctionRNA *func; - func = RNA_struct_find_function(ptr, identifier); + func = RNA_struct_find_function(ptr->type, identifier); if (func) return RNA_function_call(C, reports, ptr, func, parms); @@ -5160,7 +5160,7 @@ int RNA_function_call_direct_lookup(bContext *C, ReportList *reports, PointerRNA { FunctionRNA *func; - func = RNA_struct_find_function(ptr, identifier); + func = RNA_struct_find_function(ptr->type, identifier); if (func) { va_list args; @@ -5535,7 +5535,7 @@ int RNA_function_call_direct_va_lookup(bContext *C, ReportList *reports, Pointer { FunctionRNA *func; - func = RNA_struct_find_function(ptr, identifier); + func = RNA_struct_find_function(ptr->type, identifier); if (func) return RNA_function_call_direct_va(C, reports, ptr, func, format, args); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 7d73de00b49..02d8cbef4a3 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ #include "DNA_sdna_types.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" #include "BLI_ghash.h" #include "RNA_define.h" @@ -2631,6 +2633,11 @@ FunctionRNA *RNA_def_function(StructRNA *srna, const char *identifier, const cha FunctionRNA *func; FunctionDefRNA *dfunc; + if (BLI_findstring_ptr(&srna->functions, identifier, offsetof(FunctionRNA, identifier))) { + fprintf(stderr, "%s: %s.%s already defined.\n", __func__, srna->identifier, identifier); + return NULL; + } + func = rna_def_function(srna, identifier); if (!DefRNA.preprocess) { diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 873f5353bff..04f9a90f0d2 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -3467,7 +3467,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) ret = pyrna_prop_to_py(&self->ptr, prop); } /* RNA function only if callback is declared (no optional functions) */ - else if ((func = RNA_struct_find_function(&self->ptr, name)) && RNA_function_defined(func)) { + else if ((func = RNA_struct_find_function(self->ptr.type, name)) && RNA_function_defined(func)) { ret = pyrna_func_to_py(&self->ptr, func); } else if (self->ptr.type == &RNA_Context) { @@ -3780,7 +3780,7 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject return ret; } - else if ((func = RNA_struct_find_function(&r_ptr, name))) { + else if ((func = RNA_struct_find_function(r_ptr.type, name))) { PyObject *self_collection = pyrna_struct_CreatePyObject(&r_ptr); ret = pyrna_func_to_py(&((BPy_DummyPointerRNA *)self_collection)->ptr, func); Py_DECREF(self_collection); -- cgit v1.2.3 From 10932e2e9785b92f786deeec2794816a05a6fed1 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Sun, 10 Jun 2012 15:07:08 +0000 Subject: Fix #31778. BKE_image_user_frame_calc can be called with iuser==NULL in some circumstances now, so needs to check that. --- source/blender/blenkernel/intern/image.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 157c8782523..eaf4c898b86 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2722,15 +2722,17 @@ int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr) void BKE_image_user_frame_calc(ImageUser *iuser, int cfra, int fieldnr) { - const int framenr = BKE_image_user_frame_get(iuser, cfra, fieldnr); - - /* allows image users to handle redraws */ - if (iuser->flag & IMA_ANIM_ALWAYS) - if (framenr != iuser->framenr) - iuser->flag |= IMA_ANIM_REFRESHED; - - iuser->framenr = framenr; - if (iuser->ok == 0) iuser->ok = 1; + if (iuser) { + const int framenr = BKE_image_user_frame_get(iuser, cfra, fieldnr); + + /* allows image users to handle redraws */ + if (iuser->flag & IMA_ANIM_ALWAYS) + if (framenr != iuser->framenr) + iuser->flag |= IMA_ANIM_REFRESHED; + + iuser->framenr = framenr; + if (iuser->ok == 0) iuser->ok = 1; + } } void BKE_image_user_check_frame_calc(ImageUser *iuser, int cfra, int fieldnr) -- cgit v1.2.3 From 5534701e5d7659d8fdd73ef64375116bb07463e8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Jun 2012 15:20:10 +0000 Subject: style cleanup: use capital camel case names for typedef's --- source/blender/blenkernel/intern/anim.c | 8 +-- source/blender/blenkernel/intern/seqcache.c | 40 ++++++------- source/blender/blenlib/BLI_boxpack2d.h | 2 +- source/blender/blenlib/intern/boxpack2d.c | 28 ++++----- source/blender/blenlib/intern/fileops.c | 70 +++++++++++----------- .../blender/editors/animation/keyframes_general.c | 8 +-- source/blender/editors/mesh/editmesh_loopcut.c | 22 +++---- source/blender/editors/mesh/editmesh_tools.c | 38 ++++++------ source/blender/editors/sculpt_paint/paint_vertex.c | 12 ++-- source/gameengine/Ketsji/KX_NearSensor.h | 2 +- source/gameengine/Ketsji/KX_TouchSensor.h | 6 +- source/gameengine/VideoTexture/ImageBase.cpp | 6 +- 12 files changed, 122 insertions(+), 120 deletions(-) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 701ce6c8299..170638f0e8d 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -840,7 +840,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind *ob = copyob; } -typedef struct vertexDupliData { +typedef struct VertexDupliData { ID *id; /* scene or group, for recursive loops */ int level; int animated; @@ -851,7 +851,7 @@ typedef struct vertexDupliData { Object *ob, *par; float (*orco)[3]; int par_index; -} vertexDupliData; +} VertexDupliData; /* ------------- */ @@ -859,7 +859,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]) { DupliObject *dob; - vertexDupliData *vdd = userData; + VertexDupliData *vdd = userData; float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4]; int origlay; @@ -910,7 +910,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl Mesh *me = par->data; Base *base = NULL; DerivedMesh *dm; - vertexDupliData vdd; + VertexDupliData vdd; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index ea4699f8495..582034ae623 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -29,7 +29,7 @@ #include -#include "BLO_sys_types.h" /* for intptr_t */ +#include "BLO_sys_types.h" /* for intptr_t */ #include "MEM_guardedalloc.h" @@ -38,21 +38,21 @@ #include "IMB_moviecache.h" -typedef struct seqCacheKey { - struct Sequence * seq; +typedef struct SeqCacheKey { + struct Sequence *seq; SeqRenderData context; float cfra; seq_stripelem_ibuf_t type; -} seqCacheKey; +} SeqCacheKey; static struct MovieCache *moviecache = NULL; static unsigned int seqcache_hashhash(const void *key_) { - const seqCacheKey *key = (seqCacheKey*) key_; + const SeqCacheKey *key = (SeqCacheKey *) key_; unsigned int rval = seq_hash_render_data(&key->context); - rval ^= *(unsigned int*) &key->cfra; + rval ^= *(unsigned int *) &key->cfra; rval += key->type; rval ^= ((intptr_t) key->seq) << 6; @@ -61,11 +61,11 @@ static unsigned int seqcache_hashhash(const void *key_) static int seqcache_hashcmp(const void *a_, const void *b_) { - const seqCacheKey * a = (seqCacheKey*) a_; - const seqCacheKey * b = (seqCacheKey*) b_; + const SeqCacheKey *a = (SeqCacheKey *) a_; + const SeqCacheKey *b = (SeqCacheKey *) b_; if (a->seq < b->seq) { - return -1; + return -1; } if (a->seq > b->seq) { return 1; @@ -98,18 +98,18 @@ void seq_stripelem_cache_cleanup(void) { if (moviecache) { IMB_moviecache_free(moviecache); - moviecache = IMB_moviecache_create(sizeof(seqCacheKey), seqcache_hashhash, - seqcache_hashcmp, NULL); + moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), seqcache_hashhash, + seqcache_hashcmp, NULL); } } -struct ImBuf * seq_stripelem_cache_get( - SeqRenderData context, struct Sequence * seq, - float cfra, seq_stripelem_ibuf_t type) +struct ImBuf *seq_stripelem_cache_get( + SeqRenderData context, struct Sequence *seq, + float cfra, seq_stripelem_ibuf_t type) { if (moviecache && seq) { - seqCacheKey key; + SeqCacheKey key; key.seq = seq; key.context = context; @@ -123,18 +123,18 @@ struct ImBuf * seq_stripelem_cache_get( } void seq_stripelem_cache_put( - SeqRenderData context, struct Sequence * seq, - float cfra, seq_stripelem_ibuf_t type, struct ImBuf * i) + SeqRenderData context, struct Sequence *seq, + float cfra, seq_stripelem_ibuf_t type, struct ImBuf *i) { - seqCacheKey key; + SeqCacheKey key; if (!i) { return; } if (!moviecache) { - moviecache = IMB_moviecache_create(sizeof(seqCacheKey), seqcache_hashhash, - seqcache_hashcmp, NULL); + moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), seqcache_hashhash, + seqcache_hashcmp, NULL); } key.seq = seq; diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack2d.h index 77e937d7b6f..3bc486054f5 100644 --- a/source/blender/blenlib/BLI_boxpack2d.h +++ b/source/blender/blenlib/BLI_boxpack2d.h @@ -43,7 +43,7 @@ typedef struct BoxPack { /* Verts this box uses * (BL,TR,TL,BR) / 0,1,2,3 */ - struct boxVert *v[4]; + struct BoxVert *v[4]; } BoxPack; void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *tot_height); diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index bf63517a4c2..feaa60b40b2 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -33,7 +33,7 @@ * * The defined Below are for internal use only */ -typedef struct boxVert { +typedef struct BoxVert { float x; float y; short free; @@ -48,7 +48,7 @@ typedef struct boxVert { struct BoxPack *isect_cache[4]; int index; -} boxVert; +} BoxVert; /* free vert flags */ #define EPSILON 0.0000001f @@ -121,11 +121,11 @@ static int box_areasort(const void *p1, const void *p2) * */ static float box_width; static float box_height; -static boxVert *vertarray; +static BoxVert *vertarray; static int vertex_sort(const void *p1, const void *p2) { - boxVert *v1, *v2; + BoxVert *v1, *v2; float a1, a2; v1 = vertarray + ((int *)p1)[0]; @@ -154,7 +154,7 @@ static int vertex_sort(const void *p1, const void *p2) * */ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *tot_height) { - boxVert *vert; /* the current vert */ + BoxVert *vert; /* the current vert */ int box_index, verts_pack_len, i, j, k, isect; int quad_flags[4] = {BLF, TRF, TLF, BRF}; /* use for looping */ BoxPack *box, *box_test; /*current box and another for intersection tests*/ @@ -170,38 +170,38 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float * qsort(boxarray, len, sizeof(BoxPack), box_areasort); /* add verts to the boxes, these are only used internally */ - vert = vertarray = MEM_mallocN(len * 4 * sizeof(boxVert), "BoxPack Verts"); + vert = vertarray = MEM_mallocN(len * 4 * sizeof(BoxVert), "BoxPack Verts"); vertex_pack_indices = MEM_mallocN(len * 3 * sizeof(int), "BoxPack Indices"); for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) { vert->blb = vert->brb = vert->tlb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~TRF; vert->trb = box; vert->index = i; i++; box->v[BL] = vert; vert++; vert->trb = vert->brb = vert->tlb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~BLF; vert->blb = box; vert->index = i; i++; box->v[TR] = vert; vert++; vert->trb = vert->blb = vert->tlb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~BRF; vert->brb = box; vert->index = i; i++; box->v[TL] = vert; vert++; vert->trb = vert->blb = vert->brb = - vert->isect_cache[0] = vert->isect_cache[1] = - vert->isect_cache[2] = vert->isect_cache[3] = NULL; + vert->isect_cache[0] = vert->isect_cache[1] = + vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~TLF; vert->tlb = box; vert->index = i; i++; diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index e6d06484e74..ec7b59702bd 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -385,16 +385,16 @@ int BLI_rename(const char *from, const char *to) enum { /* operation succeeded succeeded */ - recursiveOp_Callback_OK = 0, + RecursiveOp_Callback_OK = 0, /* operation requested not to perform recursive digging for current path */ - recursiveOp_Callback_StopRecurs = 1, + RecursiveOp_Callback_StopRecurs = 1, /* error occured in callback and recursive walking should stop immediately */ - recursiveOp_Callback_Error = 2 + RecursiveOp_Callback_Error = 2 } recuresiveOp_Callback_Result; -typedef int (*recursiveOp_Callback)(const char *from, const char *to); +typedef int (*RecursiveOp_Callback)(const char *from, const char *to); /* appending of filename to dir (ensures for buffer size before appending) */ static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, const char *file) @@ -419,8 +419,8 @@ static char *strip_last_slash(const char *dir) return result; } -static int recursive_operation(const char *startfrom, const char *startto, recursiveOp_Callback callback_dir_pre, - recursiveOp_Callback callback_file, recursiveOp_Callback callback_dir_post) +static int recursive_operation(const char *startfrom, const char *startto, RecursiveOp_Callback callback_dir_pre, + RecursiveOp_Callback callback_file, RecursiveOp_Callback callback_dir_post) { struct dirent **dirlist; struct stat st; @@ -446,7 +446,7 @@ static int recursive_operation(const char *startfrom, const char *startto, recur if (callback_file) { ret = callback_file(from, to); - if (ret != recursiveOp_Callback_OK) + if (ret != RecursiveOp_Callback_OK) ret = -1; } @@ -472,11 +472,11 @@ static int recursive_operation(const char *startfrom, const char *startto, recur /* call pre-recursive walking directory callback */ ret = callback_dir_pre(from, to); - if (ret != recursiveOp_Callback_OK) { + if (ret != RecursiveOp_Callback_OK) { MEM_freeN(from); if (to) free(to); - if (ret == recursiveOp_Callback_StopRecurs) { + if (ret == RecursiveOp_Callback_StopRecurs) { /* callback requested not to perform recursive walking, not an error */ return 0; } @@ -505,7 +505,7 @@ static int recursive_operation(const char *startfrom, const char *startto, recur else if (callback_file) { /* call file callback for current path */ ret = callback_file(from_path, to_path); - if (ret != recursiveOp_Callback_OK) + if (ret != RecursiveOp_Callback_OK) ret = -1; } @@ -522,7 +522,7 @@ static int recursive_operation(const char *startfrom, const char *startto, recur if (callback_dir_post) { /* call post-recursive directory callback */ ret = callback_dir_post(from, to); - if (ret != recursiveOp_Callback_OK) + if (ret != RecursiveOp_Callback_OK) ret = -1; } } @@ -541,10 +541,10 @@ static int delete_callback_post(const char *from, const char *UNUSED(to)) if (rmdir(from)) { perror("rmdir"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } static int delete_single_file(const char *from, const char *UNUSED(to)) @@ -552,10 +552,10 @@ static int delete_single_file(const char *from, const char *UNUSED(to)) if (unlink(from)) { perror("unlink"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } FILE *BLI_fopen(const char *filename, const char *mode) @@ -628,27 +628,27 @@ static int copy_callback_pre(const char *from, const char *to) if (check_the_same(from, to)) { fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } if (lstat(from, &st)) { perror("stat"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } /* create a directory */ if (mkdir(to, st.st_mode)) { perror("mkdir"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } /* set proper owner and group on new directory */ if (chown(to, st.st_uid, st.st_gid)) { perror("chown"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } static int copy_single_file(const char *from, const char *to) @@ -660,12 +660,12 @@ static int copy_single_file(const char *from, const char *to) if (check_the_same(from, to)) { fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } if (lstat(from, &st)) { perror("lstat"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } if (S_ISLNK(st.st_mode)) { @@ -690,7 +690,7 @@ static int copy_single_file(const char *from, const char *to) if (need_free) MEM_freeN(link_buffer); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } link_buffer[link_len] = 0; @@ -698,13 +698,13 @@ static int copy_single_file(const char *from, const char *to) if (symlink(link_buffer, to)) { perror("symlink"); if (need_free) MEM_freeN(link_buffer); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } if (need_free) MEM_freeN(link_buffer); - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || @@ -714,30 +714,30 @@ static int copy_single_file(const char *from, const char *to) /* copy special type of file */ if (mknod(to, st.st_mode, st.st_rdev)) { perror("mknod"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } if (set_permissions(to, &st)) - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } else if (!S_ISREG(st.st_mode)) { fprintf(stderr, "Copying of this kind of files isn't supported yet\n"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } from_stream = fopen(from, "rb"); if (!from_stream) { perror("fopen"); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } to_stream = fopen(to, "wb"); if (!to_stream) { perror("fopen"); fclose(from_stream); - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; } while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) { @@ -748,9 +748,9 @@ static int copy_single_file(const char *from, const char *to) fclose(from_stream); if (set_permissions(to, &st)) - return recursiveOp_Callback_Error; + return RecursiveOp_Callback_Error; - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } static int move_callback_pre(const char *from, const char *to) @@ -760,7 +760,7 @@ static int move_callback_pre(const char *from, const char *to) if (ret) return copy_callback_pre(from, to); - return recursiveOp_Callback_StopRecurs; + return RecursiveOp_Callback_StopRecurs; } static int move_single_file(const char *from, const char *to) @@ -770,7 +770,7 @@ static int move_single_file(const char *from, const char *to) if (ret) return copy_single_file(from, to); - return recursiveOp_Callback_OK; + return RecursiveOp_Callback_OK; } int BLI_move(const char *file, const char *to) diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index ac37b6c4141..14bee00a72a 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -374,16 +374,16 @@ void smooth_fcurve(FCurve *fcu) /* ---------------- */ /* little cache for values... */ -typedef struct tempFrameValCache { +typedef struct TempFrameValCache { float frame, val; -} tempFrameValCache; +} TempFrameValCache; /* Evaluates the curves between each selected keyframe on each frame, and keys the value */ void sample_fcurve(FCurve *fcu) { BezTriple *bezt, *start = NULL, *end = NULL; - tempFrameValCache *value_cache, *fp; + TempFrameValCache *value_cache, *fp; int sfra, range; int i, n, nIndex; @@ -406,7 +406,7 @@ void sample_fcurve(FCurve *fcu) sfra = (int)(floor(start->vec[1][0]) ); if (range) { - value_cache = MEM_callocN(sizeof(tempFrameValCache) * range, "IcuFrameValCache"); + value_cache = MEM_callocN(sizeof(TempFrameValCache) * range, "IcuFrameValCache"); /* sample values */ for (n = 1, fp = value_cache; n < range && fp; n++, fp++) { diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 7298153791e..185c804661d 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -86,7 +86,7 @@ /* ringsel operator */ /* struct for properties used while drawing */ -typedef struct tringselOpData { +typedef struct RingSelOpData { ARegion *ar; /* region that ringsel was activated in */ void *draw_handle; /* for drawing preview loop */ @@ -102,13 +102,13 @@ typedef struct tringselOpData { int extend; int do_cut; -} tringselOpData; +} RingSelOpData; /* modal loop selection drawing callback */ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) { View3D *v3d = CTX_wm_view3d(C); - tringselOpData *lcd = arg; + RingSelOpData *lcd = arg; int i; if (lcd->totedge > 0) { @@ -176,7 +176,7 @@ static void edgering_find_order(BMEdge *lasteed, BMEdge *eed, } } -static void edgering_sel(tringselOpData *lcd, int previewlines, int select) +static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) { BMEditMesh *em = lcd->em; BMEdge *startedge = lcd->eed; @@ -290,7 +290,7 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select) lcd->totedge = tot; } -static void ringsel_find_edge(tringselOpData *lcd, int cuts) +static void ringsel_find_edge(RingSelOpData *lcd, int cuts) { if (lcd->eed) { edgering_sel(lcd, cuts, 0); @@ -304,7 +304,7 @@ static void ringsel_find_edge(tringselOpData *lcd, int cuts) static void ringsel_finish(bContext *C, wmOperator *op) { - tringselOpData *lcd = op->customdata; + RingSelOpData *lcd = op->customdata; int cuts = RNA_int_get(op->ptr, "number_cuts"); if (lcd->eed) { @@ -350,7 +350,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) /* called when modal loop selection is done... */ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) { - tringselOpData *lcd = op->customdata; + RingSelOpData *lcd = op->customdata; /* deactivate the extra drawing stuff in 3D-View */ ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle); @@ -368,10 +368,10 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) /* called when modal loop selection gets set up... */ static int ringsel_init(bContext *C, wmOperator *op, int do_cut) { - tringselOpData *lcd; + RingSelOpData *lcd; /* alloc new customdata */ - lcd = op->customdata = MEM_callocN(sizeof(tringselOpData), "ringsel Modal Op Data"); + lcd = op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data"); /* assign the drawing handle for drawing preview line... */ lcd->ar = CTX_wm_region(C); @@ -402,7 +402,7 @@ static int ringcut_cancel(bContext *C, wmOperator *op) static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) { Object *obedit = CTX_data_edit_object(C); - tringselOpData *lcd; + RingSelOpData *lcd; BMEdge *edge; int dist = 75; @@ -434,7 +434,7 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) { int cuts = RNA_int_get(op->ptr, "number_cuts"); - tringselOpData *lcd = op->customdata; + RingSelOpData *lcd = op->customdata; int show_cuts = 0; view3d_operator_needs_opengl(C); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index b6d89a62d05..0f7d4c5c547 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3676,14 +3676,14 @@ enum { SRT_REVERSE, /* Reverse current order of selected elements. */ }; -typedef struct bmelemsort { +typedef struct BMElemSort { float srt; /* Sort factor */ int org_idx; /* Original index of this element _in its mempool_ */ -} bmelemsort; +} BMElemSort; static int bmelemsort_comp(const void *v1, const void *v2) { - const bmelemsort *x1 = v1, *x2 = v2; + const BMElemSort *x1 = v1, *x2 = v2; return (x1->srt > x2->srt) - (x1->srt < x2->srt); } @@ -3704,7 +3704,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const /* In all five elements below, 0 = vertices, 1 = edges, 2 = faces. */ /* Just to mark protected elements. */ char *pblock[3] = {NULL, NULL, NULL}, *pb; - bmelemsort *sblock[3] = {NULL, NULL, NULL}, *sb; + BMElemSort *sblock[3] = {NULL, NULL, NULL}, *sb; int *map[3] = {NULL, NULL, NULL}, *mp; int totelem[3] = {0, 0, 0}, tot; int affected[3] = {0, 0, 0}, aff; @@ -3733,7 +3733,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[0]) { pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock"); - sb = sblock[0] = MEM_callocN(sizeof(bmelemsort) * totelem[0], "sort_bmelem vert sblock"); + sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock"); BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(ve, flag)) { @@ -3752,7 +3752,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[1]) { pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock"); - sb = sblock[1] = MEM_callocN(sizeof(bmelemsort) * totelem[1], "sort_bmelem edge sblock"); + sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock"); BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(ed, flag)) { @@ -3772,7 +3772,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[2]) { pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock"); - sb = sblock[2] = MEM_callocN(sizeof(bmelemsort) * totelem[2], "sort_bmelem face sblock"); + sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock"); BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { @@ -3806,7 +3806,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[0]) { pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock"); - sb = sblock[0] = MEM_callocN(sizeof(bmelemsort) * totelem[0], "sort_bmelem vert sblock"); + sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock"); BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(ve, flag)) { @@ -3822,7 +3822,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[1]) { pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock"); - sb = sblock[1] = MEM_callocN(sizeof(bmelemsort) * totelem[1], "sort_bmelem edge sblock"); + sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock"); BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(ed, flag)) { @@ -3841,7 +3841,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[2]) { pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock"); - sb = sblock[2] = MEM_callocN(sizeof(bmelemsort) * totelem[2], "sort_bmelem face sblock"); + sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock"); BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { @@ -3862,7 +3862,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const /* Faces only! */ else if (action == SRT_MATERIAL && totelem[2]) { pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock"); - sb = sblock[2] = MEM_callocN(sizeof(bmelemsort) * totelem[2], "sort_bmelem face sblock"); + sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock"); BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { @@ -3966,7 +3966,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const * enabling/disabling an element type. */ BLI_srandom(seed); pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock"); - sb = sblock[0] = MEM_callocN(sizeof(bmelemsort) * totelem[0], "sort_bmelem vert sblock"); + sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock"); BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(ve, flag)) { @@ -3983,7 +3983,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[1]) { BLI_srandom(seed); pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock"); - sb = sblock[1] = MEM_callocN(sizeof(bmelemsort) * totelem[1], "sort_bmelem edge sblock"); + sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock"); BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(ed, flag)) { @@ -4000,7 +4000,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[2]) { BLI_srandom(seed); pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock"); - sb = sblock[2] = MEM_callocN(sizeof(bmelemsort) * totelem[2], "sort_bmelem face sblock"); + sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock"); BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { @@ -4018,7 +4018,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const else if (action == SRT_REVERSE) { if (totelem[0]) { pb = pblock[0] = MEM_callocN(sizeof(char) * totelem[0], "sort_bmelem vert pblock"); - sb = sblock[0] = MEM_callocN(sizeof(bmelemsort) * totelem[0], "sort_bmelem vert sblock"); + sb = sblock[0] = MEM_callocN(sizeof(BMElemSort) * totelem[0], "sort_bmelem vert sblock"); BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(ve, flag)) { @@ -4034,7 +4034,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[1]) { pb = pblock[1] = MEM_callocN(sizeof(char) * totelem[1], "sort_bmelem edge pblock"); - sb = sblock[1] = MEM_callocN(sizeof(bmelemsort) * totelem[1], "sort_bmelem edge sblock"); + sb = sblock[1] = MEM_callocN(sizeof(BMElemSort) * totelem[1], "sort_bmelem edge sblock"); BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(ed, flag)) { @@ -4050,7 +4050,7 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const if (totelem[2]) { pb = pblock[2] = MEM_callocN(sizeof(char) * totelem[2], "sort_bmelem face pblock"); - sb = sblock[2] = MEM_callocN(sizeof(bmelemsort) * totelem[2], "sort_bmelem face sblock"); + sb = sblock[2] = MEM_callocN(sizeof(BMElemSort) * totelem[2], "sort_bmelem face sblock"); BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { @@ -4086,11 +4086,11 @@ static void sort_bmelem_flag(bContext *C, const int types, const int flag, const sb = sblock[j]; if (pb && sb && !map[j]) { char *p_blk; - bmelemsort *s_blk; + BMElemSort *s_blk; tot = totelem[j]; aff = affected[j]; - qsort(sb, aff, sizeof(bmelemsort), bmelemsort_comp); + qsort(sb, aff, sizeof(BMElemSort), bmelemsort_comp); mp = map[j] = MEM_mallocN(sizeof(int) * tot, "sort_bmelem map"); p_blk = pb + tot - 1; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 43981770784..3c37ad8cf2a 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2624,10 +2624,10 @@ void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot) * - revise whether op->customdata should be added in object, in set_vpaint */ -typedef struct polyfacemap_e { - struct polyfacemap_e *next, *prev; +typedef struct PolyFaceMap { + struct PolyFaceMap *next, *prev; int facenr; -} polyfacemap_e; +} PolyFaceMap; typedef struct VPaintData { ViewContext vc; @@ -2648,7 +2648,7 @@ typedef struct VPaintData { static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) { MFace *mf; - polyfacemap_e *e; + PolyFaceMap *e; int *origIndex; int i; @@ -2667,7 +2667,7 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) if (*origIndex == ORIGINDEX_NONE) continue; - e = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(polyfacemap_e)); + e = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(PolyFaceMap)); e->facenr = i; BLI_addtail(&vd->polyfacemap[*origIndex], e); @@ -2784,7 +2784,7 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob, MCol *mc; MLoop *ml; MLoopCol *mlc; - polyfacemap_e *e; + PolyFaceMap *e; unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart; unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart; float alpha; diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 8655d93d406..82f523283ed 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -74,7 +74,7 @@ public: virtual void ReParent(SCA_IObject* parent); virtual bool NewHandleCollision(void* obj1,void* obj2, - const PHY_CollData * coll_data); + const PHY_CollData * coll_data); virtual bool BroadPhaseFilterCollision(void*obj1,void*obj2); virtual bool BroadPhaseSensorFilterCollision(void* obj1,void* obj2) { return false; } virtual sensortype GetSensorType() { return ST_NEAR; } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 1a22067f9ac..d739144d70d 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -93,8 +93,10 @@ public: virtual void UnregisterSumo(KX_TouchEventManager* touchman); virtual void UnregisterToManager(); -// virtual DT_Bool HandleCollision(void* obj1,void* obj2, -// const DT_CollData * coll_data); +#if 0 + virtual DT_Bool HandleCollision(void* obj1,void* obj2, + const DT_CollData * coll_data); +#endif virtual bool NewHandleCollision(void*obj1,void*obj2,const PHY_CollData* colldata); diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index b1d77d8807f..ac92bcc6d41 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -444,9 +444,9 @@ PyObject * Image_getImage (PyImage * self, char * mode) // get an empty buffer buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, NULL); // and fill it - for (i=0, d=(unsigned char*)buffer->buf.asbyte, s=(unsigned char*)image; - ibuf.asbyte, s = (unsigned char *)image; + i < pixels; + i++, d += ncolor, s += 4) { for (c=0; c Date: Sun, 10 Jun 2012 15:26:50 +0000 Subject: Support for per-track Grease Pencil datablocks for motion tracking Originally was needed to reach easy way of defining masks used for tracking (do eliminate textures which doesn't belong to feature when tracking. Implemented as alternative to GP datablock for clip and added switch between per-clip and per-track GP datablocks -- internal limitations of GP doesn't allow to display all GP datablocks easily. So either you see.edit GP associated with clip or with track. GP strokes associated with track are relative to track's position, following tracks during tracking and could be shared between several tracks. Masking code presents in libmv and there's rasterizer of GP datablocks for masks in blender's tracking module, but they still need to be glued together. Some documentation cound be found at this page: http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker#Grease_Pencil --- source/blender/blenloader/intern/readfile.c | 18 ++++++++++ source/blender/editors/gpencil/gpencil_buttons.c | 29 +++++++++++---- source/blender/editors/gpencil/gpencil_edit.c | 21 +++++++++-- source/blender/editors/gpencil/gpencil_paint.c | 10 ++++++ source/blender/editors/space_clip/clip_draw.c | 46 ++++++++++++++++++++---- source/blender/editors/space_clip/space_clip.c | 7 ++-- source/blender/makesdna/DNA_space_types.h | 11 +++++- source/blender/makesdna/DNA_tracking_types.h | 3 ++ source/blender/makesrna/intern/rna_movieclip.c | 1 + source/blender/makesrna/intern/rna_space.c | 13 +++++++ source/blender/makesrna/intern/rna_tracking.c | 8 +++++ 11 files changed, 147 insertions(+), 20 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 85d597ccbdd..fccdcbef564 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6164,17 +6164,35 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) } } +static void lib_link_movieTracks(FileData *fd, MovieClip *clip, ListBase *tracksbase) +{ + MovieTrackingTrack *track; + + for (track = tracksbase->first; track; track = track->next) { + track->gpd = newlibadr_us(fd, clip->id.lib, track->gpd); + } +} + static void lib_link_movieclip(FileData *fd, Main *main) { MovieClip *clip; for (clip = main->movieclip.first; clip; clip = clip->id.next) { if (clip->id.flag & LIB_NEEDLINK) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *object; + if (clip->adt) lib_link_animdata(fd, &clip->id, clip->adt); clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd); + lib_link_movieTracks(fd, clip, &tracking->tracks); + + for (object = tracking->objects.first; object; object = object->next) { + lib_link_movieTracks(fd, clip, &object->tracks); + } + clip->id.flag -= LIB_NEEDLINK; } } diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index 3a7e806c2ed..b59f3756819 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -40,6 +40,7 @@ #include "DNA_gpencil_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "BKE_context.h" #include "BKE_global.h" @@ -236,6 +237,7 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin PointerRNA gpd_ptr; bGPDlayer *gpl; uiLayout *col, *row; + SpaceClip *sc= CTX_wm_space_clip(C); short v3d_stroke_opts = STROKE_OPTS_NORMAL; const short is_v3d = CTX_wm_view3d(C) != NULL; @@ -244,6 +246,16 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin /* draw gpd settings first ------------------------------------- */ col = uiLayoutColumn(layout, 0); + + if (sc) { + bScreen *screen = CTX_wm_screen(C); + PointerRNA sc_ptr; + + RNA_pointer_create(&screen->id, &RNA_SpaceClipEditor, sc, &sc_ptr); + row = uiLayoutRow(col, 1); + uiItemR(row, &sc_ptr, "grease_pencil_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + } + /* current Grease Pencil block */ /* TODO: show some info about who owns this? */ uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink"); @@ -281,14 +293,17 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin row = uiLayoutRow(col, 1); uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NONE); uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NONE); - row = uiLayoutRow(col, 1); - uiLayoutSetActive(row, v3d_stroke_opts); - uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE); - uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE); - row = uiLayoutRow(col, 0); - uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON); - uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE); + if (sc == NULL) { + row = uiLayoutRow(col, 1); + uiLayoutSetActive(row, v3d_stroke_opts); + uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NONE); + uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NONE); + + row = uiLayoutRow(col, 0); + uiLayoutSetActive(row, v3d_stroke_opts == STROKE_OPTS_V3D_ON); + uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NONE); + } } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 9250d48a20c..71cbabe9114 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -57,6 +57,7 @@ #include "BKE_library.h" #include "BKE_object.h" #include "BKE_report.h" +#include "BKE_tracking.h" #include "WM_api.h" @@ -144,9 +145,23 @@ bGPdata **gpencil_data_get_pointers(bContext *C, PointerRNA *ptr) MovieClip *clip = ED_space_clip(sc); if (clip) { - /* for now, as long as there's a clip, default to using that in Clip Editor */ - if (ptr) RNA_id_pointer_create(&clip->id, ptr); - return &clip->gpd; + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_active_track(&clip->tracking); + + if (!track) + return NULL; + + if (ptr) + RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); + + return &track->gpd; + } + else { + if (ptr) + RNA_id_pointer_create(&clip->id, ptr); + + return &clip->gpd; + } } } break; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 3e569f8eb96..89d8ed9c465 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -44,6 +44,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" +#include "BKE_tracking.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -1125,6 +1126,15 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) p->custom_color[1] = 0.0f; p->custom_color[2] = 0.5f; p->custom_color[3] = 0.9f; + + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + int framenr = sc->user.framenr; + MovieTrackingTrack *track = BKE_tracking_active_track(&sc->clip->tracking); + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + p->imat[3][0] -= marker->pos[0]; + p->imat[3][1] -= marker->pos[1]; + } } break; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index cca72e7469a..93a32fb06fc 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1203,8 +1203,10 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, int i, j, a; float pos[2], tpos[2], grid[11][11][2]; MovieTracking *tracking = &clip->tracking; + bGPdata *gpd = NULL; float aspy = 1.0f / tracking->camera.pixel_aspect; float dx = (float)width / n, dy = (float)height / n * aspy; + float offsx = 0.0f, offsy = 0.0f; if (sc->mode != SC_MODE_DISTORTION) return; @@ -1312,8 +1314,26 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, } } - if (sc->flag & SC_MANUAL_CALIBRATION && clip->gpd) { - bGPDlayer *layer = clip->gpd->layers.first; + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_active_track(&sc->clip->tracking); + + if (track) { + int framenr = sc->user.framenr; + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + offsx = marker->pos[0]; + offsy = marker->pos[1]; + + gpd = track->gpd; + } + + } + else { + gpd = clip->gpd; + } + + if (sc->flag & SC_MANUAL_CALIBRATION && gpd) { + bGPDlayer *layer = gpd->layers.first; while (layer) { bGPDframe *frame = layer->frames.first; @@ -1338,11 +1358,11 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, float npos[2], dpos[2], len; int steps; - pos[0] = stroke->points[i].x * width; - pos[1] = stroke->points[i].y * height * aspy; + pos[0] = (stroke->points[i].x + offsx) * width; + pos[1] = (stroke->points[i].y + offsy) * height * aspy; - npos[0] = stroke->points[i + 1].x * width; - npos[1] = stroke->points[i + 1].y * height * aspy; + npos[0] = (stroke->points[i + 1].x + offsx) * width; + npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy; len = len_v2v2(pos, npos); steps = ceil(len / 5.0f); @@ -1367,7 +1387,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, } else if (stroke->totpoints == 1) { glBegin(GL_POINTS); - glVertex2f(stroke->points[0].x, stroke->points[0].y); + glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy); glEnd(); } } @@ -1467,6 +1487,18 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) { glPushMatrix(); glMultMatrixf(sc->unistabmat); + + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_active_track(&sc->clip->tracking); + + if (track) { + int framenr = sc->user.framenr; + MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + + glTranslatef(marker->pos[0], marker->pos[1], 0.0f); + } + } + draw_gpencil_2dimage(C); glPopMatrix(); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 92ba194c8e1..a49319abd20 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -393,8 +393,11 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) } break; case NC_SCREEN: - if (wmn->data == ND_ANIMPLAY) { - ED_area_tag_redraw(sa); + switch (wmn->data) { + case ND_ANIMPLAY: + case ND_GPENCIL: + ED_area_tag_redraw(sa); + break; } break; case NC_SPACE: diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 7e9a1d976d8..a315feed6c5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -999,7 +999,10 @@ typedef struct SpaceClip { * defined when drawing and used for mouse position calculation */ /* movie postprocessing */ - int postproc_flag, pad2; + int postproc_flag; + + /* grease pencil */ + short gpencil_src, pad2; void *draw_context; @@ -1068,6 +1071,12 @@ typedef enum eSpaceClip_Dopesheet_Flag { SC_DOPE_SORT_INVERSE = (1 << 0), } eSpaceClip_Dopesheet_Flag; +/* SpaceClip->gpencil_src */ +typedef enum eSpaceClip_GPencil_Source { + SC_GPENCIL_SRC_CLIP = 0, + SC_GPENCIL_SRC_TRACK = 1, +} eSpaceClip_GPencil_Source; + /* **************** SPACE DEFINES ********************* */ /* headerbuttons: 450-499 */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 6bf059c7ecb..823ecbbbba6 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -39,6 +39,7 @@ /* match-moving data */ +struct bGPdata; struct ImBuf; struct MovieReconstructedCamera; struct MovieTrackingCamera; @@ -107,6 +108,8 @@ typedef struct MovieTrackingTrack { /* ** SAD tracker settings ** */ float minimum_correlation; /* minimal correlation which is still treated as successful tracking */ + + struct bGPdata *gpd; /* grease-pencil data */ } MovieTrackingTrack; typedef struct MovieTrackingSettings { diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 592e2c9f348..a4b7516a930 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -284,6 +284,7 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this movie clip"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* frame offset */ prop = RNA_def_property(srna, "start_frame", PROP_INT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 98ff8ab70bf..cafe8ebefad 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3003,6 +3003,12 @@ static void rna_def_space_clip(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem gpencil_source_items[] = { + {SC_GPENCIL_SRC_CLIP, "CLIP", 0, "Clip", "Show grease pencil datablock which belongs to movie clip"}, + {SC_GPENCIL_SRC_TRACK, "TRACK", 0, "Track", "Show grease pencil datablock which belongs to active track"}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem pivot_items[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", "Pivot around bounding box center of selected object(s)"}, @@ -3212,6 +3218,13 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + /* grease pencil source */ + prop = RNA_def_property(srna, "grease_pencil_source", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "gpencil_src"); + RNA_def_property_enum_items(prop, gpencil_source_items); + RNA_def_property_ui_text(prop, "Grease Pencil Source", "Where the grease pencil comes from"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + /* pivot point */ prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "around"); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index b1d2bc7ac8d..17940dfca92 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -1102,6 +1102,14 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "error"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Average Error", "Average error of re-projection"); + + /* grease pencil */ + prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "gpd"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "GreasePencil"); + RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this track"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); } static void rna_def_trackingStabilization(BlenderRNA *brna) -- cgit v1.2.3 From 59ef51aa2753895442aaf2d8e4ef8ff923be3973 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 15:27:41 +0000 Subject: Initial Ceres integration into Blender Currently only put sources of Ceres library into extern/libmv/third_party and setup CMake and SCons building systems. Integration details: - Even CMake build files are not re-used from Ceres's trunk: they're using some automatic stuff detection like glog, pthreads, protobuf and so and it's not so clear how to re-use that files without modifications. And IMO it's easier if build files are getting re-generated automatically to match Blender-specific setup rather than keeping changes made locally in Blender in sync when re-bundling Ceres library. Especially in case when it's already needed to support SCons build system. - Integrated only actual sources, all tests were stripped. Probably it'll be nice to have them, but they'll need clear integration with current module test stuff in Blender. - Suitesparse was disabled. It'll help a lot having it, but there are some difficulties making cholmod working fine on windows. Would be added in future - collections_port.cc was also stripped. It's not used by Ceres's upstream and it gives compilation error (undefined uint32 -- looks like namespace issue). - Currently all schur eliminators are included. Not sure if it makes sense, also not sure if it makes sense having them switchable on and off -- IMO better to have single configuration which works and does not require special tweaks after everything was set up. To bundle updated version of Ceres: - Go to extern/libmv/third_party/ceres folder - Run ./bundle.sh This will checkout fresh Ceres snapshot of Windows branch (which is currently most interesting from integration into Blender POV), apply all patches listed in patches/series and copy needed files into Blender's working copy. This will also re-generate CMake/SCons build rules. If you'll need extra files from Ceres repository which are not present in Blender, you'll need to copy them manually and then run ./mkfiles.sh from extern/libmv/third_party/ceres folder which will update list of files used by Blender. Thanks to Leir Mierle and Sameer Agarwal (and all others who helped developing Ceres) this library and thanks to Keir Mierle with help integrating it into Blender! --- extern/libmv/CMakeLists.txt | 3 + extern/libmv/SConscript | 4 +- extern/libmv/bundle.sh | 17 +- extern/libmv/mkfiles.sh | 2 +- extern/libmv/third_party/CMakeLists.txt | 2 + extern/libmv/third_party/SConscript | 3 + extern/libmv/third_party/ceres/CMakeLists.txt | 218 ++++++ extern/libmv/third_party/ceres/ChangeLog | 324 +++++++++ extern/libmv/third_party/ceres/LICENSE | 27 + extern/libmv/third_party/ceres/README | 3 + extern/libmv/third_party/ceres/SConscript | 34 + extern/libmv/third_party/ceres/bundle.sh | 185 +++++ extern/libmv/third_party/ceres/files.txt | 150 ++++ .../ceres/include/ceres/autodiff_cost_function.h | 211 ++++++ .../libmv/third_party/ceres/include/ceres/ceres.h | 48 ++ .../include/ceres/conditioned_cost_function.h | 97 +++ .../ceres/include/ceres/cost_function.h | 127 ++++ .../ceres/include/ceres/internal/autodiff.h | 370 ++++++++++ .../ceres/include/ceres/internal/eigen.h | 80 +++ .../ceres/include/ceres/internal/fixed_array.h | 193 ++++++ .../ceres/include/ceres/internal/macros.h | 154 +++++ .../include/ceres/internal/manual_constructor.h | 214 ++++++ .../ceres/include/ceres/internal/port.h | 44 ++ .../ceres/include/ceres/internal/scoped_ptr.h | 311 +++++++++ .../ceres/include/ceres/iteration_callback.h | 159 +++++ extern/libmv/third_party/ceres/include/ceres/jet.h | 755 +++++++++++++++++++++ .../ceres/include/ceres/local_parameterization.h | 189 ++++++ .../ceres/include/ceres/loss_function.h | 322 +++++++++ .../third_party/ceres/include/ceres/normal_prior.h | 75 ++ .../include/ceres/numeric_diff_cost_function.h | 283 ++++++++ .../third_party/ceres/include/ceres/problem.h | 265 ++++++++ .../third_party/ceres/include/ceres/rotation.h | 526 ++++++++++++++ .../ceres/include/ceres/sized_cost_function.h | 88 +++ .../libmv/third_party/ceres/include/ceres/solver.h | 376 ++++++++++ .../libmv/third_party/ceres/include/ceres/types.h | 258 +++++++ .../internal/ceres/block_evaluate_preparer.cc | 73 ++ .../ceres/internal/ceres/block_evaluate_preparer.h | 67 ++ .../internal/ceres/block_jacobi_preconditioner.cc | 136 ++++ .../internal/ceres/block_jacobi_preconditioner.h | 84 +++ .../ceres/internal/ceres/block_jacobian_writer.cc | 209 ++++++ .../ceres/internal/ceres/block_jacobian_writer.h | 127 ++++ .../ceres/block_random_access_dense_matrix.cc | 83 +++ .../ceres/block_random_access_dense_matrix.h | 98 +++ .../internal/ceres/block_random_access_matrix.cc | 40 ++ .../internal/ceres/block_random_access_matrix.h | 132 ++++ .../ceres/block_random_access_sparse_matrix.cc | 158 +++++ .../ceres/block_random_access_sparse_matrix.h | 109 +++ .../ceres/internal/ceres/block_sparse_matrix.cc | 286 ++++++++ .../ceres/internal/ceres/block_sparse_matrix.h | 144 ++++ .../ceres/internal/ceres/block_structure.cc | 92 +++ .../ceres/internal/ceres/block_structure.h | 105 +++ .../internal/ceres/canonical_views_clustering.cc | 238 +++++++ .../internal/ceres/canonical_views_clustering.h | 133 ++++ .../libmv/third_party/ceres/internal/ceres/casts.h | 108 +++ .../ceres/internal/ceres/cgnr_linear_operator.h | 120 ++++ .../ceres/internal/ceres/cgnr_solver.cc | 80 +++ .../third_party/ceres/internal/ceres/cgnr_solver.h | 66 ++ .../ceres/internal/ceres/collections_port.h | 141 ++++ .../ceres/compressed_row_jacobian_writer.cc | 201 ++++++ .../ceres/compressed_row_jacobian_writer.h | 75 ++ .../internal/ceres/compressed_row_sparse_matrix.cc | 334 +++++++++ .../internal/ceres/compressed_row_sparse_matrix.h | 129 ++++ .../internal/ceres/conditioned_cost_function.cc | 130 ++++ .../internal/ceres/conjugate_gradients_solver.cc | 233 +++++++ .../internal/ceres/conjugate_gradients_solver.h | 74 ++ .../third_party/ceres/internal/ceres/corrector.cc | 125 ++++ .../third_party/ceres/internal/ceres/corrector.h | 88 +++ .../ceres/internal/ceres/dense_jacobian_writer.h | 110 +++ .../ceres/internal/ceres/dense_qr_solver.cc | 93 +++ .../ceres/internal/ceres/dense_qr_solver.h | 99 +++ .../ceres/internal/ceres/dense_sparse_matrix.cc | 197 ++++++ .../ceres/internal/ceres/dense_sparse_matrix.h | 116 ++++ .../ceres/internal/ceres/detect_structure.cc | 114 ++++ .../ceres/internal/ceres/detect_structure.h | 63 ++ .../third_party/ceres/internal/ceres/evaluator.cc | 71 ++ .../third_party/ceres/internal/ceres/evaluator.h | 129 ++++ .../libmv/third_party/ceres/internal/ceres/file.cc | 93 +++ .../libmv/third_party/ceres/internal/ceres/file.h | 52 ++ .../ceres/generated/schur_eliminator_2_2_2.cc | 53 ++ .../ceres/generated/schur_eliminator_2_2_3.cc | 53 ++ .../ceres/generated/schur_eliminator_2_2_4.cc | 53 ++ .../ceres/generated/schur_eliminator_2_2_d.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_3.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_4.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_9.cc | 53 ++ .../ceres/generated/schur_eliminator_2_3_d.cc | 53 ++ .../ceres/generated/schur_eliminator_2_4_3.cc | 53 ++ .../ceres/generated/schur_eliminator_2_4_4.cc | 53 ++ .../ceres/generated/schur_eliminator_2_4_d.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_2.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_3.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_4.cc | 53 ++ .../ceres/generated/schur_eliminator_4_4_d.cc | 53 ++ .../ceres/generated/schur_eliminator_d_d_d.cc | 53 ++ .../ceres/gradient_checking_cost_function.cc | 308 +++++++++ .../ceres/gradient_checking_cost_function.h | 85 +++ .../libmv/third_party/ceres/internal/ceres/graph.h | 138 ++++ .../ceres/internal/ceres/graph_algorithms.h | 270 ++++++++ .../internal/ceres/implicit_schur_complement.cc | 237 +++++++ .../internal/ceres/implicit_schur_complement.h | 176 +++++ .../ceres/internal/ceres/integral_types.h | 92 +++ .../ceres/iterative_schur_complement_solver.cc | 150 ++++ .../ceres/iterative_schur_complement_solver.h | 94 +++ .../ceres/internal/ceres/levenberg_marquardt.cc | 574 ++++++++++++++++ .../ceres/internal/ceres/levenberg_marquardt.h | 65 ++ .../ceres/linear_least_squares_problems.cc | 744 ++++++++++++++++++++ .../internal/ceres/linear_least_squares_problems.h | 87 +++ .../ceres/internal/ceres/linear_operator.cc | 40 ++ .../ceres/internal/ceres/linear_operator.h | 59 ++ .../ceres/internal/ceres/linear_solver.cc | 87 +++ .../ceres/internal/ceres/linear_solver.h | 291 ++++++++ .../ceres/internal/ceres/local_parameterization.cc | 140 ++++ .../ceres/internal/ceres/loss_function.cc | 93 +++ .../third_party/ceres/internal/ceres/map_util.h | 129 ++++ .../ceres/internal/ceres/matrix_proto.h | 40 ++ .../third_party/ceres/internal/ceres/minimizer.h | 104 +++ .../libmv/third_party/ceres/internal/ceres/mutex.h | 312 +++++++++ .../ceres/internal/ceres/normal_prior.cc | 67 ++ .../ceres/internal/ceres/parameter_block.h | 256 +++++++ .../internal/ceres/partitioned_matrix_view.cc | 315 +++++++++ .../ceres/internal/ceres/partitioned_matrix_view.h | 121 ++++ .../third_party/ceres/internal/ceres/problem.cc | 149 ++++ .../ceres/internal/ceres/problem_impl.cc | 359 ++++++++++ .../ceres/internal/ceres/problem_impl.h | 127 ++++ .../third_party/ceres/internal/ceres/program.cc | 233 +++++++ .../third_party/ceres/internal/ceres/program.h | 128 ++++ .../ceres/internal/ceres/program_evaluator.h | 279 ++++++++ .../third_party/ceres/internal/ceres/random.h | 47 ++ .../ceres/internal/ceres/residual_block.cc | 212 ++++++ .../ceres/internal/ceres/residual_block.h | 124 ++++ .../ceres/internal/ceres/residual_block_utils.cc | 185 +++++ .../ceres/internal/ceres/residual_block_utils.h | 89 +++ .../ceres/runtime_numeric_diff_cost_function.cc | 218 ++++++ .../ceres/runtime_numeric_diff_cost_function.h | 87 +++ .../internal/ceres/schur_complement_solver.cc | 285 ++++++++ .../ceres/internal/ceres/schur_complement_solver.h | 182 +++++ .../ceres/internal/ceres/schur_eliminator.cc | 141 ++++ .../ceres/internal/ceres/schur_eliminator.h | 339 +++++++++ .../ceres/internal/ceres/schur_eliminator_impl.h | 702 +++++++++++++++++++ .../ceres/internal/ceres/schur_ordering.cc | 113 +++ .../ceres/internal/ceres/schur_ordering.h | 74 ++ .../internal/ceres/scratch_evaluate_preparer.cc | 78 +++ .../internal/ceres/scratch_evaluate_preparer.h | 69 ++ .../third_party/ceres/internal/ceres/solver.cc | 230 +++++++ .../ceres/internal/ceres/solver_impl.cc | 693 +++++++++++++++++++ .../third_party/ceres/internal/ceres/solver_impl.h | 111 +++ .../ceres/internal/ceres/sparse_matrix.cc | 40 ++ .../ceres/internal/ceres/sparse_matrix.h | 114 ++++ .../ceres/sparse_normal_cholesky_solver.cc | 129 ++++ .../internal/ceres/sparse_normal_cholesky_solver.h | 77 +++ .../third_party/ceres/internal/ceres/split.cc | 115 ++++ .../third_party/ceres/internal/ceres/stl_util.h | 75 ++ .../ceres/internal/ceres/stringprintf.cc | 126 ++++ .../ceres/internal/ceres/stringprintf.h | 89 +++ .../ceres/internal/ceres/suitesparse.cc | 193 ++++++ .../third_party/ceres/internal/ceres/suitesparse.h | 159 +++++ .../ceres/internal/ceres/triplet_sparse_matrix.cc | 306 +++++++++ .../ceres/internal/ceres/triplet_sparse_matrix.h | 137 ++++ .../third_party/ceres/internal/ceres/types.cc | 98 +++ .../third_party/ceres/internal/ceres/visibility.cc | 150 ++++ .../third_party/ceres/internal/ceres/visibility.h | 77 +++ .../ceres/visibility_based_preconditioner.cc | 611 +++++++++++++++++ .../ceres/visibility_based_preconditioner.h | 273 ++++++++ extern/libmv/third_party/ceres/mkfiles.sh | 4 + .../third_party/ceres/patches/msvc_isfinite.patch | 15 + extern/libmv/third_party/ceres/patches/series | 1 + source/blenderplayer/CMakeLists.txt | 1 + source/creator/CMakeLists.txt | 1 + 168 files changed, 25432 insertions(+), 7 deletions(-) create mode 100644 extern/libmv/third_party/CMakeLists.txt create mode 100644 extern/libmv/third_party/SConscript create mode 100644 extern/libmv/third_party/ceres/CMakeLists.txt create mode 100644 extern/libmv/third_party/ceres/ChangeLog create mode 100644 extern/libmv/third_party/ceres/LICENSE create mode 100644 extern/libmv/third_party/ceres/README create mode 100644 extern/libmv/third_party/ceres/SConscript create mode 100644 extern/libmv/third_party/ceres/bundle.sh create mode 100644 extern/libmv/third_party/ceres/files.txt create mode 100644 extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/ceres.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/eigen.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/macros.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/port.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/iteration_callback.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/jet.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/local_parameterization.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/loss_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/normal_prior.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/problem.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/rotation.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/solver.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/types.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_structure.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/block_structure.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/casts.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/collections_port.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/corrector.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/corrector.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/detect_structure.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/evaluator.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/evaluator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/file.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/file.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/graph.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/integral_types.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_operator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/linear_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/loss_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/map_util.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/minimizer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/mutex.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/parameter_block.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/problem.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/problem_impl.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/program.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/program.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/random.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/solver_impl.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/split.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/stl_util.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/stringprintf.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/suitesparse.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/types.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h create mode 100644 extern/libmv/third_party/ceres/mkfiles.sh create mode 100644 extern/libmv/third_party/ceres/patches/msvc_isfinite.patch create mode 100644 extern/libmv/third_party/ceres/patches/series diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 6be813883ec..cf0ad1102e0 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -32,6 +32,7 @@ set(INC third_party/ssba third_party/ldl/Include ../colamd/Include + third_party/ceres/include ) set(INC_SYS @@ -250,3 +251,5 @@ add_definitions( ) blender_add_lib(extern_libmv "${SRC}" "${INC}" "${INC_SYS}") + +add_subdirectory(third_party) diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index fbb6ee36f85..b47086f3e91 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -30,7 +30,7 @@ src += env.Glob('third_party/ldl/Source/*.c') src += env.Glob('third_party/ssba/Geometry/*.cpp') src += env.Glob('third_party/ssba/Math/*.cpp') -incs = '. ../Eigen3' +incs = '. ../Eigen3 third_party/ceres/include' incs += ' ' + env['BF_PNG_INC'] incs += ' ' + env['BF_ZLIB_INC'] @@ -65,3 +65,5 @@ else: incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv ) + +SConscript(['third_party/SConscript']) diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 3f58097b881..3f877508c46 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -25,7 +25,9 @@ for p in `cat ./patches/series`; do done find libmv -type f -not -iwholename '*.svn*' -exec rm -rf {} \; -find third_party -type f -not -iwholename '*.svn*' -exec rm -rf {} \; +find third_party -type f -not -iwholename '*.svn*' -not -iwholename '*third_party/ceres*' \ + -not -iwholename '*third_party/SConscript*' -not -iwholename '*third_party/CMakeLists.txt*' \ + -exec rm -rf {} \; cat "files.txt" | while read f; do mkdir -p `dirname $f` @@ -39,14 +41,14 @@ chmod 664 ./third_party/glog/src/windows/*.cc ./third_party/glog/src/windows/*.h sources=`find ./libmv -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d` headers=`find ./libmv -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` -third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d` -third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d` +third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d` +third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d` third_glog_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d` third_glog_headers=`find ./third_party -type f -iname '*.h' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d` src_dir=`find ./libmv -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` -src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` +src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d | uniq` src="" win_src="" for x in $src_dir $src_third_dir; do @@ -126,6 +128,7 @@ set(INC third_party/ssba third_party/ldl/Include ../colamd/Include + third_party/ceres/include ) set(INC_SYS @@ -220,6 +223,8 @@ add_definitions( ) blender_add_lib(extern_libmv "\${SRC}" "\${INC}" "\${INC_SYS}") + +add_subdirectory(third_party) EOF cat > SConscript << EOF @@ -246,7 +251,7 @@ defs.append('GOOGLE_GLOG_DLL_DECL=') src = env.Glob("*.cpp") $src -incs = '. ../Eigen3' +incs = '. ../Eigen3 third_party/ceres/include' incs += ' ' + env['BF_PNG_INC'] incs += ' ' + env['BF_ZLIB_INC'] @@ -281,4 +286,6 @@ else: incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include' env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv ) + +SConscript(['third_party/SConscript']) EOF diff --git a/extern/libmv/mkfiles.sh b/extern/libmv/mkfiles.sh index fe84c357de4..c7c8c33f725 100755 --- a/extern/libmv/mkfiles.sh +++ b/extern/libmv/mkfiles.sh @@ -1,4 +1,4 @@ #!/bin/sh find ./libmv/ -type f | sed -r 's/^\.\///' | sort > files.txt -find ./third_party/ -type f | sed -r 's/^\.\///' | sort >> files.txt +find ./third_party/ -mindepth 2 -type f | grep -v third_party/ceres | sed -r 's/^\.\///' | sort >> files.txt diff --git a/extern/libmv/third_party/CMakeLists.txt b/extern/libmv/third_party/CMakeLists.txt new file mode 100644 index 00000000000..6212fe480b1 --- /dev/null +++ b/extern/libmv/third_party/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(ceres) diff --git a/extern/libmv/third_party/SConscript b/extern/libmv/third_party/SConscript new file mode 100644 index 00000000000..b05692e385f --- /dev/null +++ b/extern/libmv/third_party/SConscript @@ -0,0 +1,3 @@ +#!/usr/bin/python + +SConscript(['ceres/SConscript']) diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt new file mode 100644 index 00000000000..5207bddec12 --- /dev/null +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -0,0 +1,218 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +set(INC + . + ../../../Eigen3 + include + internal + ../gflags +) + +set(INC_SYS +) + +set(SRC + internal/ceres/block_evaluate_preparer.cc + internal/ceres/block_jacobian_writer.cc + internal/ceres/block_jacobi_preconditioner.cc + internal/ceres/block_random_access_dense_matrix.cc + internal/ceres/block_random_access_matrix.cc + internal/ceres/block_random_access_sparse_matrix.cc + internal/ceres/block_sparse_matrix.cc + internal/ceres/block_structure.cc + internal/ceres/canonical_views_clustering.cc + internal/ceres/cgnr_solver.cc + internal/ceres/compressed_row_jacobian_writer.cc + internal/ceres/compressed_row_sparse_matrix.cc + internal/ceres/conditioned_cost_function.cc + internal/ceres/conjugate_gradients_solver.cc + internal/ceres/corrector.cc + internal/ceres/dense_qr_solver.cc + internal/ceres/dense_sparse_matrix.cc + internal/ceres/detect_structure.cc + internal/ceres/evaluator.cc + internal/ceres/file.cc + internal/ceres/generated/schur_eliminator_2_2_2.cc + internal/ceres/generated/schur_eliminator_2_2_3.cc + internal/ceres/generated/schur_eliminator_2_2_4.cc + internal/ceres/generated/schur_eliminator_2_2_d.cc + internal/ceres/generated/schur_eliminator_2_3_3.cc + internal/ceres/generated/schur_eliminator_2_3_4.cc + internal/ceres/generated/schur_eliminator_2_3_9.cc + internal/ceres/generated/schur_eliminator_2_3_d.cc + internal/ceres/generated/schur_eliminator_2_4_3.cc + internal/ceres/generated/schur_eliminator_2_4_4.cc + internal/ceres/generated/schur_eliminator_2_4_d.cc + internal/ceres/generated/schur_eliminator_4_4_2.cc + internal/ceres/generated/schur_eliminator_4_4_3.cc + internal/ceres/generated/schur_eliminator_4_4_4.cc + internal/ceres/generated/schur_eliminator_4_4_d.cc + internal/ceres/generated/schur_eliminator_d_d_d.cc + internal/ceres/gradient_checking_cost_function.cc + internal/ceres/implicit_schur_complement.cc + internal/ceres/iterative_schur_complement_solver.cc + internal/ceres/levenberg_marquardt.cc + internal/ceres/linear_least_squares_problems.cc + internal/ceres/linear_operator.cc + internal/ceres/linear_solver.cc + internal/ceres/local_parameterization.cc + internal/ceres/loss_function.cc + internal/ceres/normal_prior.cc + internal/ceres/partitioned_matrix_view.cc + internal/ceres/problem.cc + internal/ceres/problem_impl.cc + internal/ceres/program.cc + internal/ceres/residual_block.cc + internal/ceres/residual_block_utils.cc + internal/ceres/runtime_numeric_diff_cost_function.cc + internal/ceres/schur_complement_solver.cc + internal/ceres/schur_eliminator.cc + internal/ceres/schur_ordering.cc + internal/ceres/scratch_evaluate_preparer.cc + internal/ceres/solver.cc + internal/ceres/solver_impl.cc + internal/ceres/sparse_matrix.cc + internal/ceres/sparse_normal_cholesky_solver.cc + internal/ceres/split.cc + internal/ceres/stringprintf.cc + internal/ceres/suitesparse.cc + internal/ceres/triplet_sparse_matrix.cc + internal/ceres/types.cc + internal/ceres/visibility_based_preconditioner.cc + internal/ceres/visibility.cc + + include/ceres/autodiff_cost_function.h + include/ceres/ceres.h + include/ceres/conditioned_cost_function.h + include/ceres/cost_function.h + include/ceres/internal/autodiff.h + include/ceres/internal/eigen.h + include/ceres/internal/fixed_array.h + include/ceres/internal/macros.h + include/ceres/internal/manual_constructor.h + include/ceres/internal/port.h + include/ceres/internal/scoped_ptr.h + include/ceres/iteration_callback.h + include/ceres/jet.h + include/ceres/local_parameterization.h + include/ceres/loss_function.h + include/ceres/normal_prior.h + include/ceres/numeric_diff_cost_function.h + include/ceres/problem.h + include/ceres/rotation.h + include/ceres/sized_cost_function.h + include/ceres/solver.h + include/ceres/types.h + internal/ceres/block_evaluate_preparer.h + internal/ceres/block_jacobian_writer.h + internal/ceres/block_jacobi_preconditioner.h + internal/ceres/block_random_access_dense_matrix.h + internal/ceres/block_random_access_matrix.h + internal/ceres/block_random_access_sparse_matrix.h + internal/ceres/block_sparse_matrix.h + internal/ceres/block_structure.h + internal/ceres/canonical_views_clustering.h + internal/ceres/casts.h + internal/ceres/cgnr_linear_operator.h + internal/ceres/cgnr_solver.h + internal/ceres/collections_port.h + internal/ceres/compressed_row_jacobian_writer.h + internal/ceres/compressed_row_sparse_matrix.h + internal/ceres/conjugate_gradients_solver.h + internal/ceres/corrector.h + internal/ceres/dense_jacobian_writer.h + internal/ceres/dense_qr_solver.h + internal/ceres/dense_sparse_matrix.h + internal/ceres/detect_structure.h + internal/ceres/evaluator.h + internal/ceres/file.h + internal/ceres/gradient_checking_cost_function.h + internal/ceres/graph_algorithms.h + internal/ceres/graph.h + internal/ceres/implicit_schur_complement.h + internal/ceres/integral_types.h + internal/ceres/iterative_schur_complement_solver.h + internal/ceres/levenberg_marquardt.h + internal/ceres/linear_least_squares_problems.h + internal/ceres/linear_operator.h + internal/ceres/linear_solver.h + internal/ceres/map_util.h + internal/ceres/matrix_proto.h + internal/ceres/minimizer.h + internal/ceres/mutex.h + internal/ceres/parameter_block.h + internal/ceres/partitioned_matrix_view.h + internal/ceres/problem_impl.h + internal/ceres/program_evaluator.h + internal/ceres/program.h + internal/ceres/random.h + internal/ceres/residual_block.h + internal/ceres/residual_block_utils.h + internal/ceres/runtime_numeric_diff_cost_function.h + internal/ceres/schur_complement_solver.h + internal/ceres/schur_eliminator.h + internal/ceres/schur_eliminator_impl.h + internal/ceres/schur_ordering.h + internal/ceres/scratch_evaluate_preparer.h + internal/ceres/solver_impl.h + internal/ceres/sparse_matrix.h + internal/ceres/sparse_normal_cholesky_solver.h + internal/ceres/stl_util.h + internal/ceres/stringprintf.h + internal/ceres/suitesparse.h + internal/ceres/triplet_sparse_matrix.h + internal/ceres/visibility_based_preconditioner.h + internal/ceres/visibility.h +) + +if(WIN32) + list(APPEND INC + ../glog/src/windows + ) + + if(NOT MINGW) + list(APPEND INC + third_party/msinttypes + ) + endif() +else() + list(APPEND INC + ../glog/src + ) +endif() + +add_definitions( + -DCERES_HAVE_PTHREAD + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + -DCERES_NO_SUITESPARSE + -DCERES_DONT_HAVE_PROTOCOL_BUFFERS +) + +blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}") diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog new file mode 100644 index 00000000000..6e919658f13 --- /dev/null +++ b/extern/libmv/third_party/ceres/ChangeLog @@ -0,0 +1,324 @@ +commit ca72152362ae1f4b9928c012e74b4d49d094a4ca +Merge: d297f8d 0a04199 +Author: Keir Mierle +Date: Wed May 9 13:10:59 2012 -0700 + + Merge branch 'master' into windows + +commit 0a04199ef279cc9ea97f665fed8e7fae717813c3 +Merge: fdeb577 f2571f1 +Author: Keir Mierle +Date: Wed May 9 12:54:56 2012 -0700 + + Merge branch 'master' of https://code.google.com/p/ceres-solver + +commit fdeb5772cc5eeebca4d776d220d80cc91b6d0f74 +Author: Keir Mierle +Date: Wed May 9 07:38:07 2012 -0700 + + Support varying numbers of residuals in autodiff. + + This commit modifies the only function in autodiff that takes a + templated number of outputs (i.e. residuals) and makes that + template parameter a normal parameter. With that change, it + is a trivial matter to support a dynamic number of residuals. + + The API for dynamic residuals is to pass a fake number of + residuals as the second template argument to + AutoDiffCostFunction, and to pass the real number of + parameters as a second constructor argument. + +commit da3e0563cc12e08e7b3e0fbf11d9cc8cfe9658aa +Author: Sameer Agarwal +Date: Wed May 9 11:57:47 2012 -0700 + + Typo corrections in the documentation from Bing + +commit aa9526d8e8fb34c23d63e3af5bf9239b0c4ea603 +Author: Sameer Agarwal +Date: Tue May 8 21:22:09 2012 -0700 + + Share search paths across various library searches. + Fix typos in glog search. + Split the error messages for include and lib. + Enable building of tests by default. + Made building on homebrew installations a bit better. + Remove temporary variables for glog and gflags. + +commit f2571f186850ed3dd316236ac4be488979df7d30 +Author: Sameer Agarwal +Date: Wed May 9 11:57:47 2012 -0700 + + Typo corrections in the documentation from Bing + +commit 8f7f11ff7d07737435428a2620c52419cf99f98e +Merge: e6c17c4 eaccbb3 +Author: Sameer Agarwal +Date: Wed May 9 11:34:15 2012 -0700 + + Merge branch 'master' of https://code.google.com/p/ceres-solver + +commit e6c17c4c9d9307218f6f739cea39bc2d87733d4d +Author: Sameer Agarwal +Date: Tue May 8 21:22:09 2012 -0700 + + Share search paths across various library searches. + Fix typos in glog search. + Split the error messages for include and lib. + Enable building of tests by default. + Made building on homebrew installations a bit better. + Remove temporary variables for glog and gflags. + +commit eaccbb345614c0d24c5e21fa931f470cfda874df +Author: Keir Mierle +Date: Wed May 9 05:31:29 2012 -0700 + + Remove unused template parameter from VariadicEvaluate. + +commit 82f4b88c34b0b2cf85064e5fc20e374e978b2e3b +Author: Sameer Agarwal +Date: Sun May 6 21:05:28 2012 -0700 + + Extend support writing linear least squares problems to disk. + + 1. Make the mechanism for writing problems to disk, generic and + controllable using an enum DumpType visible in the API. + + 2. Instead of single file containing protocol buffers, now matrices can + be written in a matlab/octave friendly format. This is now the default. + + 3. The support for writing problems to disk is moved into + linear_least_squares_problem.cc/h + + 4. SparseMatrix now has a ToTextFile virtual method which is + implemented by each of its subclasses to write a (i,j,s) triplets. + + 5. Minor changes to simple_bundle_adjuster to enable logging at startup. + +commit d297f8d3d3f5025c24752f0f4c1ec2469a769f99 +Merge: 7e74d81 f8bd7fa +Author: Keir Mierle +Date: Tue May 8 05:39:56 2012 -0700 + + Merge branch 'master' into windows + +commit f8bd7fa9aa9dbf64b6165606630287cf8cf21194 +Author: Keir Mierle +Date: Tue May 8 05:39:32 2012 -0700 + + Small tweaks to the block jacobi preconditioner. + +commit 7e74d81ad57a159f14110eb5348b3bc7990b8bd4 +Merge: ecd7c8d e2a6cdc +Author: Keir Mierle +Date: Mon May 7 07:02:49 2012 -0700 + + Merge branch 'master' into windows + +commit e2a6cdc0816af9d0c77933f5017f137da3d52a35 +Author: Keir Mierle +Date: Mon May 7 06:39:56 2012 -0700 + + Address some of the comments on CGNR patch + + - Rename BlockDiagonalPreconditioner to BlockJacobiPreconditioner + - Include the diagonal in the block jacobi preconditioner. + - Better flag help for eta. + - Enable test for CGNR + - Rename CONJUGATE_GRADIENTS to CGNR. + - etc. + +commit 1b95dc580aa5d89be021c0915e26df83f18013bb +Merge: 211812a 7646039 +Author: Keir Mierle +Date: Mon May 7 04:34:10 2012 -0700 + + Merge branch 'master' of https://code.google.com/p/ceres-solver + +commit 211812a57360d2011cbcfd115cd55e0eb73600db +Author: Keir Mierle +Date: Mon May 7 04:33:50 2012 -0700 + + Better error handling in bundle_adjuster.cc + +commit 7646039ad9672b267495f5b31925473ad3022ac8 +Author: Sameer Agarwal +Date: Sun May 6 22:02:19 2012 -0700 + + Kashif's corrections to the docs + +commit 0d2d34148d10c5c7e924b3ca82ad2b237573ef64 +Author: Sameer Agarwal +Date: Sun May 6 21:16:03 2012 -0700 + + glog minimum version requirements + + Building Ceres requires version 0.3.1 or better of glog. + Fedora 16 ships with a busted version 0.3. + + issue 15 contains the gory details. + + Added a note to the build documentation to this effect. + +commit 39efc5ec4b64b8f5a2c5a3dbacdbc45421221547 +Author: Keir Mierle +Date: Sun May 6 16:09:52 2012 -0700 + + Fix tests broken by the CGNR change. + +commit 3faa08b7f7c4ac73661c6a15a6824c12080dfcb1 +Author: Sameer Agarwal +Date: Sun May 6 16:08:22 2012 -0700 + + Formatting fixed based on Keir's comments and extended the tests + +commit 4f21c68409bc478c431a9b6aedf9e5cfdf11d2f3 +Author: Sameer Agarwal +Date: Sun May 6 15:33:47 2012 -0700 + + Fix the struct weak ordering used by independent set ordering, tests for it + +commit 887b156b917ccd4c172484452b059d33ea45f4f0 +Author: Sameer Agarwal +Date: Sun May 6 15:14:47 2012 -0700 + + fix he degree ordering routine + +commit ecd7c8df2af19404dc394b36bbe96e9db3bce840 +Author: Keir Mierle +Date: Sun May 6 00:09:41 2012 -0700 + + First step towards windows compatibilty + + This adds some small changes to Ceres to make it mostly + compile on Windows. There are still issues with the + hash map use in schur_ordering.cc but I will fix those + shortly. + +commit f7898fba1b92f0e996571b5bfa22a37f5e3644de +Author: Keir Mierle +Date: Sat May 5 20:55:08 2012 -0700 + + Add a general sparse iterative solver: CGNR + + This adds a new LinearOperator which implements symmetric + products of a matrix, and a new CGNR solver to leverage + CG to directly solve the normal equations. This also + includes a block diagonal preconditioner. In experiments + on problem-16, the non-preconditioned version is about + 1/5 the speed of SPARSE_SCHUR, and the preconditioned + version using block cholesky is about 20% slower than + SPARSE_SCHUR. + +commit 0a359d6198d257776a8831c3eb98f64ee91cf836 +Author: Keir Mierle +Date: Sat May 5 20:33:46 2012 -0700 + + Comment formatting. + +commit db4ec9312bb2f1ca7b2337812f6bad6cdd75b227 +Author: Keir Mierle +Date: Sat May 5 20:33:16 2012 -0700 + + Comment formatting + +commit f10163aaf3e57f52551bcd60bbdae873890a49dd +Author: Keir Mierle +Date: Fri May 4 21:33:53 2012 -0700 + + Warn about disabled schur specializations. + + This commit brought to you from 30,000ft. + +commit ad7b2b4aaf3ccc51f2b854febd53a9df54686cfe +Author: Keir Mierle +Date: Fri May 4 20:15:28 2012 -0700 + + Add vim swapfiles to .gitignore + +commit 6447219826bf6e47b0c99d9ff0eaf5e2ba573d79 +Author: Sameer Agarwal +Date: Thu May 3 21:53:07 2012 -0700 + + 1. Changes the tutorial to refer to BriefReport. + 2. Some of the enums have commas at the end. + 3. Fix a bug in the default value of circle_fit.cc in the examples. + +commit 30c5f93c7f88dec49f76168663372772e06f17f5 +Author: Sameer Agarwal +Date: Thu May 3 10:44:43 2012 -0700 + + Rework the glog and gtest path checking to be consistent with the rest of the file and disable the dashboard support enabled by the earlier ctesting related patch. + +commit f10b033eb4aca77919987bc551d16d8a88b10110 +Merge: cc38774 e0a52a9 +Author: Sameer Agarwal +Date: Thu May 3 08:45:20 2012 -0700 + + Merge branch 'ctest' + +commit e0a52a993394e73bc7f7db8d520728926feab83e +Author: Sameer Agarwal +Date: Thu May 3 08:43:34 2012 -0700 + + Arnaus Gelas' patch to add better path searching for gflags and glog + +commit a9b8e815e1c026599734510399b10f4cf014c9cd +Author: Sameer Agarwal +Date: Thu May 3 08:41:52 2012 -0700 + + Arnaus Gelas' patch to add .gitignore + +commit a0cefc3347c32b2065053bbaff4f34d11529d931 +Author: Sameer Agarwal +Date: Thu May 3 08:38:33 2012 -0700 + + Arnaus Gelas' patch to move to Ctest + +commit cc38774d74e287704915282425fbd16818a72ec3 +Author: Keir Mierle +Date: Thu May 3 01:27:50 2012 -0700 + + Clarify ProgramEvaluator comments. + +commit 017c9530df557863f78212fb5ccd02814baa9fa8 +Author: Sameer Agarwal +Date: Wed May 2 08:21:59 2012 -0700 + + Mac OS X build instructions are much simpler, as homebrew takes care of gflags when glog is brought in. Also CMAKE does not need any flags to do the default thing + +commit 92d5ab5f8ae6fe355c30b606a5f230415ee0494b +Author: Keir Mierle +Date: Tue May 1 18:33:08 2012 -0700 + + Link BLAS explicitly on non-Mac platforms + + Fixes issue #3. + +commit df3e54eb4a6b001b7f0560a2da73a5bd7f18615e +Author: Keir Mierle +Date: Tue May 1 18:22:51 2012 -0700 + + Fix link order of CHOLMOD + + This was working by accident due to dynamic linking. Fixes issue #2. + +commit f477a3835329e2b48eb20c34c631a480b0f0d5bf +Author: Keir Mierle +Date: Tue May 1 18:10:48 2012 -0700 + + Fix Eigen search paths + + Fixes issue #1 on http://code.google.com/p/ceres-solver. + +commit 17fbc8ebb894c1d22bb3b0b02ea1394b580120f8 +Author: Sameer Agarwal +Date: Tue May 1 00:21:19 2012 -0700 + + Minor changes to the documentation. Formatting, and typos. + +commit 8ebb0730388045570f22b89fe8672c860cd2ad1b +Author: Keir Mierle +Date: Mon Apr 30 23:09:08 2012 -0700 + + Initial commit of Ceres Solver. diff --git a/extern/libmv/third_party/ceres/LICENSE b/extern/libmv/third_party/ceres/LICENSE new file mode 100644 index 00000000000..2e3ead5ed45 --- /dev/null +++ b/extern/libmv/third_party/ceres/LICENSE @@ -0,0 +1,27 @@ +Ceres Solver - A fast non-linear least squares minimizer +Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +http://code.google.com/p/ceres-solver/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/extern/libmv/third_party/ceres/README b/extern/libmv/third_party/ceres/README new file mode 100644 index 00000000000..8dd8ccf91a1 --- /dev/null +++ b/extern/libmv/third_party/ceres/README @@ -0,0 +1,3 @@ +Ceres Solver - A non-linear least squares minimizer +================================================== +Please see ceres.pdf in docs/ for a tutorial and reference. diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript new file mode 100644 index 00000000000..d8b2b8520d7 --- /dev/null +++ b/extern/libmv/third_party/ceres/SConscript @@ -0,0 +1,34 @@ +#!/usr/bin/python + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +import sys +import os + +Import('env') + +src = [] +defs = [] + +src += env.Glob('internal/ceres/*.cc') +src += env.Glob('internal/ceres/generated/*.cc') + +defs.append('CERES_HAVE_PTHREAD') +defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {') +defs.append('CERES_HASH_NAMESPACE_END=}}') +defs.append('CERES_NO_SUITESPARSE') +defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS') + +incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + incs += ' ../msinttypes' + + incs += ' ../glog/src/windows' +else: + incs += ' ../glog/src' + +env.BlenderLib ( libname = 'extern_ceres', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137]) diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh new file mode 100644 index 00000000000..f54342180db --- /dev/null +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -0,0 +1,185 @@ +#!/bin/sh + +if [ "x$1" = "x--i-really-know-what-im-doing" ] ; then + echo Proceeding as requested by command line ... +else + echo "*** Please run again with --i-really-know-what-im-doing ..." + exit 1 +fi + +repo="https://code.google.com/p/ceres-solver/" +branch="windows" +tmp=`mktemp -d` + +GIT="git --git-dir $tmp/ceres/.git --work-tree $tmp/ceres" + +git clone $repo $tmp/ceres + +if [ $branch != "master" ]; then + $GIT checkout -t remotes/origin/$branch +fi + +$GIT log -n 50 > ChangeLog + +for p in `cat ./patches/series`; do + echo "Applying patch $p..." + cat ./patches/$p | patch -d $tmp/ceres -p1 +done + +find include -type f -not -iwholename '*.svn*' -exec rm -rf {} \; +find internal -type f -not -iwholename '*.svn*' -exec rm -rf {} \; + +cat "files.txt" | while read f; do + mkdir -p `dirname $f` + cp $tmp/ceres/$f $f +done + +rm -rf $tmp + +sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d` +headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` + +src_dir=`find ./internal -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` +src="" +for x in $src_dir $src_third_dir; do + t="" + + if test `echo "$x" | grep -c glog ` -eq 1; then + continue; + fi + + if stat $x/*.cpp > /dev/null 2>&1; then + t="src += env.Glob('`echo $x'/*.cpp'`')" + fi + + if stat $x/*.c > /dev/null 2>&1; then + if [ -z "$t" ]; then + t="src += env.Glob('`echo $x'/*.c'`')" + else + t="$t + env.Glob('`echo $x'/*.c'`')" + fi + fi + + if stat $x/*.cc > /dev/null 2>&1; then + if [ -z "$t" ]; then + t="src += env.Glob('`echo $x'/*.cc'`')" + else + t="$t + env.Glob('`echo $x'/*.cc'`')" + fi + fi + + if [ -z "$src" ]; then + src=$t + else + src=`echo "$src\n$t"` + fi +done + +cat > CMakeLists.txt << EOF +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# Contributor(s): Blender Foundation, +# Sergey Sharybin +# +# ***** END GPL LICENSE BLOCK ***** + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +set(INC + . + ../../../Eigen3 + include + internal + ../gflags +) + +set(INC_SYS +) + +set(SRC +${sources} + +${headers} +) + +if(WIN32) + list(APPEND INC + ../glog/src/windows + ) + + if(NOT MINGW) + list(APPEND INC + third_party/msinttypes + ) + endif() +else() + list(APPEND INC + ../glog/src + ) +endif() + +add_definitions( + -DCERES_HAVE_PTHREAD + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + -DCERES_NO_SUITESPARSE + -DCERES_DONT_HAVE_PROTOCOL_BUFFERS +) + +blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}") +EOF + +cat > SConscript << EOF +#!/usr/bin/python + +# NOTE: This file is automatically generated by bundle.sh script +# If you're doing changes in this file, please update template +# in that script too + +import sys +import os + +Import('env') + +src = [] +defs = [] + +$src + +defs.append('CERES_HAVE_PTHREAD') +defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {') +defs.append('CERES_HASH_NAMESPACE_END=}}') +defs.append('CERES_NO_SUITESPARSE') +defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS') + +incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + incs += ' ../msinttypes' + + incs += ' ../glog/src/windows' +else: + incs += ' ../glog/src' + +env.BlenderLib ( libname = 'extern_ceres', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137]) +EOF diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt new file mode 100644 index 00000000000..e9d7f585260 --- /dev/null +++ b/extern/libmv/third_party/ceres/files.txt @@ -0,0 +1,150 @@ +include/ceres/autodiff_cost_function.h +include/ceres/ceres.h +include/ceres/conditioned_cost_function.h +include/ceres/cost_function.h +include/ceres/internal/autodiff.h +include/ceres/internal/eigen.h +include/ceres/internal/fixed_array.h +include/ceres/internal/macros.h +include/ceres/internal/manual_constructor.h +include/ceres/internal/port.h +include/ceres/internal/scoped_ptr.h +include/ceres/iteration_callback.h +include/ceres/jet.h +include/ceres/local_parameterization.h +include/ceres/loss_function.h +include/ceres/normal_prior.h +include/ceres/numeric_diff_cost_function.h +include/ceres/problem.h +include/ceres/rotation.h +include/ceres/sized_cost_function.h +include/ceres/solver.h +include/ceres/types.h +internal/ceres/block_evaluate_preparer.cc +internal/ceres/block_evaluate_preparer.h +internal/ceres/block_jacobian_writer.cc +internal/ceres/block_jacobian_writer.h +internal/ceres/block_jacobi_preconditioner.cc +internal/ceres/block_jacobi_preconditioner.h +internal/ceres/block_random_access_dense_matrix.cc +internal/ceres/block_random_access_dense_matrix.h +internal/ceres/block_random_access_matrix.cc +internal/ceres/block_random_access_matrix.h +internal/ceres/block_random_access_sparse_matrix.cc +internal/ceres/block_random_access_sparse_matrix.h +internal/ceres/block_sparse_matrix.cc +internal/ceres/block_sparse_matrix.h +internal/ceres/block_structure.cc +internal/ceres/block_structure.h +internal/ceres/canonical_views_clustering.cc +internal/ceres/canonical_views_clustering.h +internal/ceres/casts.h +internal/ceres/cgnr_linear_operator.h +internal/ceres/cgnr_solver.cc +internal/ceres/cgnr_solver.h +internal/ceres/collections_port.h +internal/ceres/compressed_row_jacobian_writer.cc +internal/ceres/compressed_row_jacobian_writer.h +internal/ceres/compressed_row_sparse_matrix.cc +internal/ceres/compressed_row_sparse_matrix.h +internal/ceres/conditioned_cost_function.cc +internal/ceres/conjugate_gradients_solver.cc +internal/ceres/conjugate_gradients_solver.h +internal/ceres/corrector.cc +internal/ceres/corrector.h +internal/ceres/dense_jacobian_writer.h +internal/ceres/dense_qr_solver.cc +internal/ceres/dense_qr_solver.h +internal/ceres/dense_sparse_matrix.cc +internal/ceres/dense_sparse_matrix.h +internal/ceres/detect_structure.cc +internal/ceres/detect_structure.h +internal/ceres/evaluator.cc +internal/ceres/evaluator.h +internal/ceres/file.cc +internal/ceres/file.h +internal/ceres/generated/schur_eliminator_2_2_2.cc +internal/ceres/generated/schur_eliminator_2_2_3.cc +internal/ceres/generated/schur_eliminator_2_2_4.cc +internal/ceres/generated/schur_eliminator_2_2_d.cc +internal/ceres/generated/schur_eliminator_2_3_3.cc +internal/ceres/generated/schur_eliminator_2_3_4.cc +internal/ceres/generated/schur_eliminator_2_3_9.cc +internal/ceres/generated/schur_eliminator_2_3_d.cc +internal/ceres/generated/schur_eliminator_2_4_3.cc +internal/ceres/generated/schur_eliminator_2_4_4.cc +internal/ceres/generated/schur_eliminator_2_4_d.cc +internal/ceres/generated/schur_eliminator_4_4_2.cc +internal/ceres/generated/schur_eliminator_4_4_3.cc +internal/ceres/generated/schur_eliminator_4_4_4.cc +internal/ceres/generated/schur_eliminator_4_4_d.cc +internal/ceres/generated/schur_eliminator_d_d_d.cc +internal/ceres/gradient_checking_cost_function.cc +internal/ceres/gradient_checking_cost_function.h +internal/ceres/graph_algorithms.h +internal/ceres/graph.h +internal/ceres/implicit_schur_complement.cc +internal/ceres/implicit_schur_complement.h +internal/ceres/integral_types.h +internal/ceres/iterative_schur_complement_solver.cc +internal/ceres/iterative_schur_complement_solver.h +internal/ceres/levenberg_marquardt.cc +internal/ceres/levenberg_marquardt.h +internal/ceres/linear_least_squares_problems.cc +internal/ceres/linear_least_squares_problems.h +internal/ceres/linear_operator.cc +internal/ceres/linear_operator.h +internal/ceres/linear_solver.cc +internal/ceres/linear_solver.h +internal/ceres/local_parameterization.cc +internal/ceres/loss_function.cc +internal/ceres/map_util.h +internal/ceres/matrix_proto.h +internal/ceres/minimizer.h +internal/ceres/mutex.h +internal/ceres/normal_prior.cc +internal/ceres/parameter_block.h +internal/ceres/partitioned_matrix_view.cc +internal/ceres/partitioned_matrix_view.h +internal/ceres/problem.cc +internal/ceres/problem_impl.cc +internal/ceres/problem_impl.h +internal/ceres/program.cc +internal/ceres/program_evaluator.h +internal/ceres/program.h +internal/ceres/random.h +internal/ceres/residual_block.cc +internal/ceres/residual_block.h +internal/ceres/residual_block_utils.cc +internal/ceres/residual_block_utils.h +internal/ceres/runtime_numeric_diff_cost_function.cc +internal/ceres/runtime_numeric_diff_cost_function.h +internal/ceres/schur_complement_solver.cc +internal/ceres/schur_complement_solver.h +internal/ceres/schur_eliminator.cc +internal/ceres/schur_eliminator.h +internal/ceres/schur_eliminator_impl.h +internal/ceres/schur_ordering.cc +internal/ceres/schur_ordering.h +internal/ceres/scratch_evaluate_preparer.cc +internal/ceres/scratch_evaluate_preparer.h +internal/ceres/solver.cc +internal/ceres/solver_impl.cc +internal/ceres/solver_impl.h +internal/ceres/sparse_matrix.cc +internal/ceres/sparse_matrix.h +internal/ceres/sparse_normal_cholesky_solver.cc +internal/ceres/sparse_normal_cholesky_solver.h +internal/ceres/split.cc +internal/ceres/stl_util.h +internal/ceres/stringprintf.cc +internal/ceres/stringprintf.h +internal/ceres/suitesparse.cc +internal/ceres/suitesparse.h +internal/ceres/triplet_sparse_matrix.cc +internal/ceres/triplet_sparse_matrix.h +internal/ceres/types.cc +internal/ceres/visibility_based_preconditioner.cc +internal/ceres/visibility_based_preconditioner.h +internal/ceres/visibility.cc +internal/ceres/visibility.h diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h new file mode 100644 index 00000000000..e86d6993864 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h @@ -0,0 +1,211 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Helpers for making CostFunctions as needed by the least squares framework, +// with Jacobians computed via automatic differentiation. For more information +// on automatic differentation, see the wikipedia article at +// http://en.wikipedia.org/wiki/Automatic_differentiation +// +// To get an auto differentiated cost function, you must define a class with a +// templated operator() (a functor) that computes the cost function in terms of +// the template parameter T. The autodiff framework substitutes appropriate +// "jet" objects for T in order to compute the derivative when necessary, but +// this is hidden, and you should write the function as if T were a scalar type +// (e.g. a double-precision floating point number). +// +// The function must write the computed value in the last argument (the only +// non-const one) and return true to indicate success. +// +// For example, consider a scalar error e = k - x'y, where both x and y are +// two-dimensional column vector parameters, the prime sign indicates +// transposition, and k is a constant. The form of this error, which is the +// difference between a constant and an expression, is a common pattern in least +// squares problems. For example, the value x'y might be the model expectation +// for a series of measurements, where there is an instance of the cost function +// for each measurement k. +// +// The actual cost added to the total problem is e^2, or (k - x'k)^2; however, +// the squaring is implicitly done by the optimization framework. +// +// To write an auto-differentiable cost function for the above model, first +// define the object +// +// class MyScalarCostFunction { +// MyScalarCostFunction(double k): k_(k) {} +// +// template +// bool operator()(const T* const x , const T* const y, T* e) const { +// e[0] = T(k_) - x[0] * y[0] + x[1] * y[1]; +// return true; +// } +// +// private: +// double k_; +// }; +// +// Note that in the declaration of operator() the input parameters x and y come +// first, and are passed as const pointers to arrays of T. If there were three +// input parameters, then the third input parameter would come after y. The +// output is always the last parameter, and is also a pointer to an array. In +// the example above, e is a scalar, so only e[0] is set. +// +// Then given this class definition, the auto differentiated cost function for +// it can be constructed as follows. +// +// CostFunction* cost_function +// = new AutoDiffCostFunction( +// new MyScalarCostFunction(1.0)); ^ ^ ^ +// | | | +// Dimension of residual ------+ | | +// Dimension of x ----------------+ | +// Dimension of y -------------------+ +// +// In this example, there is usually an instance for each measumerent of k. +// +// In the instantiation above, the template parameters following +// "MyScalarCostFunction", "1, 2, 2", describe the functor as computing a +// 1-dimensional output from two arguments, both 2-dimensional. +// +// The autodiff cost function also supports cost functions with a +// runtime-determined number of residuals. For example: +// +// CostFunction* cost_function +// = new AutoDiffCostFunction( +// new CostFunctionWithDynamicNumResiduals(1.0), ^ ^ ^ +// runtime_number_of_residuals); <----+ | | | +// | | | | +// | | | | +// Actual number of residuals ------+ | | | +// Indicate dynamic number of residuals ---------+ | | +// Dimension of x -------------------------------------+ | +// Dimension of y ----------------------------------------+ +// +// The framework can currently accommodate cost functions of up to 6 independent +// variables, and there is no limit on the dimensionality of each of them. +// +// WARNING #1: Since the functor will get instantiated with different types for +// T, you must to convert from other numeric types to T before mixing +// computations with other variables of type T. In the example above, this is +// seen where instead of using k_ directly, k_ is wrapped with T(k_). +// +// WARNING #2: A common beginner's error when first using autodiff cost +// functions is to get the sizing wrong. In particular, there is a tendency to +// set the template parameters to (dimension of residual, number of parameters) +// instead of passing a dimension parameter for *every parameter*. In the +// example above, that would be , which is missing +// the last '2' argument. Please be careful when setting the size parameters. + +#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_ +#define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_ + +#include +#include "ceres/internal/autodiff.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/sized_cost_function.h" +#include "ceres/types.h" + +namespace ceres { + +// A cost function which computes the derivative of the cost with respect to +// the parameters (a.k.a. the jacobian) using an autodifferentiation framework. +// The first template argument is the functor object, described in the header +// comment. The second argument is the dimension of the residual (or +// ceres::DYNAMIC to indicate it will be set at runtime), and subsequent +// arguments describe the size of the Nth parameter, one per parameter. +// +// The constructors take ownership of the cost functor. +// +// If the number of residuals (argument "M" below) is ceres::DYNAMIC, then the +// two-argument constructor must be used. The second constructor takes a number +// of residuals (in addition to the templated number of residuals). This allows +// for varying the number of residuals for a single autodiff cost function at +// runtime. +template // Number of parameters in block 5. +class AutoDiffCostFunction : + public SizedCostFunction { + public: + // Takes ownership of functor. Uses the template-provided value for the + // number of residuals ("M"). + explicit AutoDiffCostFunction(CostFunctor* functor) + : functor_(functor) { + CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the " + << "number of residuals is set to ceres::DYNAMIC."; + } + + // Takes ownership of functor. Ignores the template-provided number of + // residuals ("M") in favor of the "num_residuals" argument provided. + // + // This allows for having autodiff cost functions which return varying + // numbers of residuals at runtime. + AutoDiffCostFunction(CostFunctor* functor, int num_residuals) + : functor_(functor) { + CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the " + << "number of residuals is not ceres::DYNAMIC."; + SizedCostFunction::set_num_residuals(num_residuals); + } + + virtual ~AutoDiffCostFunction() {} + + // Implementation details follow; clients of the autodiff cost function should + // not have to examine below here. + // + // To handle varardic cost functions, some template magic is needed. It's + // mostly hidden inside autodiff.h. + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + if (!jacobians) { + return internal::VariadicEvaluate< + CostFunctor, double, N0, N1, N2, N3, N4, N5> + ::Call(*functor_, parameters, residuals); + } + return internal::AutoDiff::Differentiate( + *functor_, + parameters, + SizedCostFunction::num_residuals(), + residuals, + jacobians); + } + + private: + internal::scoped_ptr functor_; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/ceres.h b/extern/libmv/third_party/ceres/include/ceres/ceres.h new file mode 100644 index 00000000000..22aaf8ff21a --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/ceres.h @@ -0,0 +1,48 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// This is a forwarding header containing the public symbols exported from +// Ceres. Anything in the "ceres" namespace is available for use. + +#ifndef CERES_PUBLIC_CERES_H_ +#define CERES_PUBLIC_CERES_H_ + +#include "ceres/autodiff_cost_function.h" +#include "ceres/cost_function.h" +#include "ceres/iteration_callback.h" +#include "ceres/local_parameterization.h" +#include "ceres/loss_function.h" +#include "ceres/numeric_diff_cost_function.h" +#include "ceres/problem.h" +#include "ceres/sized_cost_function.h" +#include "ceres/solver.h" +#include "ceres/types.h" + +#endif // CERES_PUBLIC_CERES_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h new file mode 100644 index 00000000000..498d36ee55a --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h @@ -0,0 +1,97 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: wjr@google.com (William Rucklidge) +// +// This file contains a cost function that can apply a transformation to +// each residual value before they are square-summed. + +#ifndef CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ +#define CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ + +#include + +#include "ceres/cost_function.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +// This class allows you to apply different conditioning to the residual +// values of a wrapped cost function. An example where this is useful is +// where you have an existing cost function that produces N values, but you +// want the total cost to be something other than just the sum of these +// squared values - maybe you want to apply a different scaling to some +// values, to change their contribution to the cost. +// +// Usage: +// +// // my_cost_function produces N residuals +// CostFunction* my_cost_function = ... +// CHECK_EQ(N, my_cost_function->num_residuals()); +// vector conditioners; +// +// // Make N 1x1 cost functions (1 parameter, 1 residual) +// CostFunction* f_1 = ... +// conditioners.push_back(f_1); +// ... +// CostFunction* f_N = ... +// conditioners.push_back(f_N); +// ConditionedCostFunction* ccf = +// new ConditionedCostFunction(my_cost_function, conditioners); +// +// Now ccf's residual i (i=0..N-1) will be passed though the i'th conditioner. +// +// ccf_residual[i] = f_i(my_cost_function_residual[i]) +// +// and the Jacobian will be affected appropriately. +class ConditionedCostFunction : public CostFunction { + public: + // Builds a cost function based on a wrapped cost function, and a + // per-residual conditioner. Takes ownership of all of the wrapped cost + // functions, or not, depending on the ownership parameter. Conditioners + // may be NULL, in which case the corresponding residual is not modified. + ConditionedCostFunction(CostFunction* wrapped_cost_function, + const vector& conditioners, + Ownership ownership); + virtual ~ConditionedCostFunction(); + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const; + + private: + internal::scoped_ptr wrapped_cost_function_; + vector conditioners_; + Ownership ownership_; +}; + +} // namespace ceres + + +#endif // CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function.h b/extern/libmv/third_party/ceres/include/ceres/cost_function.h new file mode 100644 index 00000000000..84403d90636 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/cost_function.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.m (Keir Mierle) +// +// This is the interface through which the least squares solver accesses the +// residual and Jacobian of the least squares problem. Users are expected to +// subclass CostFunction to define their own terms in the least squares problem. +// +// It is recommended that users define templated residual functors for use as +// arguments for AutoDiffCostFunction (see autodiff_cost_function.h), instead of +// directly implementing the CostFunction interface. This often results in both +// shorter code and faster execution than hand-coded derivatives. However, +// specialized cases may demand direct implementation of the lower-level +// CostFunction interface; for example, this is true when calling legacy code +// which is not templated on numeric types. + +#ifndef CERES_PUBLIC_COST_FUNCTION_H_ +#define CERES_PUBLIC_COST_FUNCTION_H_ + +#include +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { + +// This class implements the computation of the cost (a.k.a. residual) terms as +// a function of the input (control) variables, and is the interface for users +// to describe their least squares problem to Ceres. In other words, this is the +// modelling layer between users and the Ceres optimizer. The signature of the +// function (number and sizes of input parameter blocks and number of outputs) +// is stored in parameter_block_sizes_ and num_residuals_ respectively. User +// code inheriting from this class is expected to set these two members with the +// corresponding accessors. This information will be verified by the Problem +// when added with AddResidualBlock(). +class CostFunction { + public: + CostFunction() : num_residuals_(0) {} + + virtual ~CostFunction() {} + + // Inputs: + // + // parameters is an array of pointers to arrays containing the + // various parameter blocks. parameters has the same number of + // elements as parameter_block_sizes_. Parameter blocks are in the + // same order as parameter_block_sizes_.i.e., + // + // parameters_[i] = double[parameter_block_sizes_[i]] + // + // Outputs: + // + // residuals is an array of size num_residuals_. + // + // jacobians is an array of size parameter_block_sizes_ containing + // pointers to storage for jacobian blocks corresponding to each + // parameter block. Jacobian blocks are in the same order as + // parameter_block_sizes, i.e. jacobians[i], is an + // array that contains num_residuals_* parameter_block_sizes_[i] + // elements. Each jacobian block is stored in row-major order, i.e., + // + // jacobians[i][r*parameter_block_size_[i] + c] = + // d residual[r] / d parameters[i][c] + // + // If jacobians is NULL, then no derivatives are returned; this is + // the case when computing cost only. If jacobians[i] is NULL, then + // the jacobian block corresponding to the i'th parameter block must + // not to be returned. + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const = 0; + + const vector& parameter_block_sizes() const { + return parameter_block_sizes_; + } + + int num_residuals() const { + return num_residuals_; + } + + protected: + vector* mutable_parameter_block_sizes() { + return ¶meter_block_sizes_; + } + + void set_num_residuals(int num_residuals) { + num_residuals_ = num_residuals; + } + + private: + // Cost function signature metadata: number of inputs & their sizes, + // number of outputs (residuals). + vector parameter_block_sizes_; + int num_residuals_; + DISALLOW_COPY_AND_ASSIGN(CostFunction); +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h new file mode 100644 index 00000000000..4f5081f8f66 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h @@ -0,0 +1,370 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Computation of the Jacobian matrix for vector-valued functions of multiple +// variables, using automatic differentiation based on the implementation of +// dual numbers in jet.h. Before reading the rest of this file, it is adivsable +// to read jet.h's header comment in detail. +// +// The helper wrapper AutoDiff::Differentiate() computes the jacobian of +// functors with templated operator() taking this form: +// +// struct F { +// template +// bool operator(const T *x, const T *y, ..., T *z) { +// // Compute z[] based on x[], y[], ... +// // return true if computation succeeded, false otherwise. +// } +// }; +// +// All inputs and outputs may be vector-valued. +// +// To understand how jets are used to compute the jacobian, a +// picture may help. Consider a vector-valued function, F, returning 3 +// dimensions and taking a vector-valued parameter of 4 dimensions: +// +// y x +// [ * ] F [ * ] +// [ * ] <--- [ * ] +// [ * ] [ * ] +// [ * ] +// +// Similar to the 2-parameter example for f described in jet.h, computing the +// jacobian dy/dx is done by substutiting a suitable jet object for x and all +// intermediate steps of the computation of F. Since x is has 4 dimensions, use +// a Jet. +// +// Before substituting a jet object for x, the dual components are set +// appropriately for each dimension of x: +// +// y x +// [ * | * * * * ] f [ * | 1 0 0 0 ] x0 +// [ * | * * * * ] <--- [ * | 0 1 0 0 ] x1 +// [ * | * * * * ] [ * | 0 0 1 0 ] x2 +// ---+--- [ * | 0 0 0 1 ] x3 +// | ^ ^ ^ ^ +// dy/dx | | | +----- infinitesimal for x3 +// | | +------- infinitesimal for x2 +// | +--------- infinitesimal for x1 +// +----------- infinitesimal for x0 +// +// The reason to set the internal 4x4 submatrix to the identity is that we wish +// to take the derivative of y separately with respect to each dimension of x. +// Each column of the 4x4 identity is therefore for a single component of the +// independent variable x. +// +// Then the jacobian of the mapping, dy/dx, is the 3x4 sub-matrix of the +// extended y vector, indicated in the above diagram. +// +// Functors with multiple parameters +// --------------------------------- +// In practice, it is often convenient to use a function f of two or more +// vector-valued parameters, for example, x[3] and z[6]. Unfortunately, the jet +// framework is designed for a single-parameter vector-valued input. The wrapper +// in this file addresses this issue adding support for functions with one or +// more parameter vectors. +// +// To support multiple parameters, all the parameter vectors are concatenated +// into one and treated as a single parameter vector, except that since the +// functor expects different inputs, we need to construct the jets as if they +// were part of a single parameter vector. The extended jets are passed +// separately for each parameter. +// +// For example, consider a functor F taking two vector parameters, p[2] and +// q[3], and producing an output y[4]: +// +// struct F { +// template +// bool operator(const T *p, const T *q, T *z) { +// // ... +// } +// }; +// +// In this case, the necessary jet type is Jet. Here is a +// visualization of the jet objects in this case: +// +// Dual components for p ----+ +// | +// -+- +// y [ * | 1 0 | 0 0 0 ] --- p[0] +// [ * | 0 1 | 0 0 0 ] --- p[1] +// [ * | . . | + + + ] | +// [ * | . . | + + + ] v +// [ * | . . | + + + ] <--- F(p, q) +// [ * | . . | + + + ] ^ +// ^^^ ^^^^^ | +// dy/dp dy/dq [ * | 0 0 | 1 0 0 ] --- q[0] +// [ * | 0 0 | 0 1 0 ] --- q[1] +// [ * | 0 0 | 0 0 1 ] --- q[2] +// --+-- +// | +// Dual components for q --------------+ +// +// where the 4x2 submatrix (marked with ".") and 4x3 submatrix (marked with "+" +// of y in the above diagram are the derivatives of y with respect to p and q +// respectively. This is how autodiff works for functors taking multiple vector +// valued arguments (up to 6). +// +// Jacobian NULL pointers +// ---------------------- +// In general, the functions below will accept NULL pointers for all or some of +// the Jacobian parameters, meaning that those Jacobians will not be computed. + +#ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_ +#define CERES_PUBLIC_INTERNAL_AUTODIFF_H_ + +#include + +#include +#include "ceres/jet.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/fixed_array.h" + +namespace ceres { +namespace internal { + +// Extends src by a 1st order pertubation for every dimension and puts it in +// dst. The size of src is N. Since this is also used for perturbations in +// blocked arrays, offset is used to shift which part of the jet the +// perturbation occurs. This is used to set up the extended x augmented by an +// identity matrix. The JetT type should be a Jet type, and T should be a +// numeric type (e.g. double). For example, +// +// 0 1 2 3 4 5 6 7 8 +// dst[0] [ * | . . | 1 0 0 | . . . ] +// dst[1] [ * | . . | 0 1 0 | . . . ] +// dst[2] [ * | . . | 0 0 1 | . . . ] +// +// is what would get put in dst if N was 3, offset was 3, and the jet type JetT +// was 8-dimensional. +template +inline void Make1stOrderPerturbation(int offset, int N, const T *src, + JetT *dst) { + DCHECK(src); + DCHECK(dst); + for (int j = 0; j < N; ++j) { + dst[j] = JetT(src[j], offset + j); + } +} + +// Takes the 0th order part of src, assumed to be a Jet type, and puts it in +// dst. This is used to pick out the "vector" part of the extended y. +template +inline void Take0thOrderPart(int M, const JetT *src, T dst) { + DCHECK(src); + for (int i = 0; i < M; ++i) { + dst[i] = src[i].a; + } +} + +// Takes N 1st order parts, starting at index N0, and puts them in the M x N +// matrix 'dst'. This is used to pick out the "matrix" parts of the extended y. +template +inline void Take1stOrderPart(const int M, const JetT *src, T *dst) { + DCHECK(src); + DCHECK(dst); + for (int i = 0; i < M; ++i) { + Eigen::Map >(dst + N * i, N) = src[i].v.template segment(N0); + } +} + +// This block of quasi-repeated code calls the user-supplied functor, which may +// take a variable number of arguments. This is accomplished by specializing the +// struct based on the size of the trailing parameters; parameters with 0 size +// are assumed missing. +// +// Supporting variadic functions is the primary source of complexity in the +// autodiff implementation. + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + input[3], + input[4], + input[5], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + input[3], + input[4], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + input[3], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + input[2], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + input[1], + output); + } +}; + +template +struct VariadicEvaluate { + static bool Call(const Functor& functor, T const *const *input, T* output) { + return functor(input[0], + output); + } +}; + +// This is in a struct because default template parameters on a function are not +// supported in C++03 (though it is available in C++0x). N0 through N5 are the +// dimension of the input arguments to the user supplied functor. +template +struct AutoDiff { + static bool Differentiate(const Functor& functor, + T const *const *parameters, + int num_outputs, + T *function_value, + T **jacobians) { + typedef Jet JetT; + + DCHECK_GT(N0, 0) + << "Cost functions must have at least one parameter block."; + DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0))) + << "Zero block cannot precede a non-zero block. Block sizes are " + << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", " + << N3 << ", " << N4 << ", " << N5; + + DCHECK_GT(num_outputs, 0); + + FixedArray x( + N0 + N1 + N2 + N3 + N4 + N5 + num_outputs); + + // It's ugly, but it works. + const int jet0 = 0; + const int jet1 = N0; + const int jet2 = N0 + N1; + const int jet3 = N0 + N1 + N2; + const int jet4 = N0 + N1 + N2 + N3; + const int jet5 = N0 + N1 + N2 + N3 + N4; + const int jet6 = N0 + N1 + N2 + N3 + N4 + N5; + + const JetT *unpacked_parameters[6] = { + x.get() + jet0, + x.get() + jet1, + x.get() + jet2, + x.get() + jet3, + x.get() + jet4, + x.get() + jet5, + }; + JetT *output = x.get() + jet6; + +#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \ + if (N ## i) { \ + internal::Make1stOrderPerturbation(jet ## i, \ + N ## i, \ + parameters[i], \ + x.get() + jet ## i); \ + } + CERES_MAKE_1ST_ORDER_PERTURBATION(0); + CERES_MAKE_1ST_ORDER_PERTURBATION(1); + CERES_MAKE_1ST_ORDER_PERTURBATION(2); + CERES_MAKE_1ST_ORDER_PERTURBATION(3); + CERES_MAKE_1ST_ORDER_PERTURBATION(4); + CERES_MAKE_1ST_ORDER_PERTURBATION(5); +#undef CERES_MAKE_1ST_ORDER_PERTURBATION + + if (!VariadicEvaluate::Call( + functor, unpacked_parameters, output)) { + return false; + } + + internal::Take0thOrderPart(num_outputs, output, function_value); + +#define CERES_TAKE_1ST_ORDER_PERTURBATION(i) \ + if (N ## i) { \ + if (jacobians[i]) { \ + internal::Take1stOrderPart(num_outputs, \ + output, \ + jacobians[i]); \ + } \ + } + CERES_TAKE_1ST_ORDER_PERTURBATION(0); + CERES_TAKE_1ST_ORDER_PERTURBATION(1); + CERES_TAKE_1ST_ORDER_PERTURBATION(2); + CERES_TAKE_1ST_ORDER_PERTURBATION(3); + CERES_TAKE_1ST_ORDER_PERTURBATION(4); + CERES_TAKE_1ST_ORDER_PERTURBATION(5); +#undef CERES_TAKE_1ST_ORDER_PERTURBATION + return true; + } +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_AUTODIFF_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h b/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h new file mode 100644 index 00000000000..be76f9eff98 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h @@ -0,0 +1,80 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_EIGEN_H_ +#define CERES_INTERNAL_EIGEN_H_ + +#include "Eigen/Core" + +namespace ceres { + +using Eigen::Dynamic; +using Eigen::RowMajor; + +typedef Eigen::Matrix Vector; +typedef Eigen::Matrix Matrix; +typedef Eigen::Map VectorRef; +typedef Eigen::Map MatrixRef; +typedef Eigen::Map AlignedMatrixRef; +typedef Eigen::Map ConstVectorRef; +typedef Eigen::Map ConstAlignedMatrixRef; +typedef Eigen::Map ConstMatrixRef; + +// C++ does not support templated typdefs, thus the need for this +// struct so that we can support statically sized Matrix and Maps. +template +struct EigenTypes { + typedef Eigen::Matrix + Matrix; + + typedef Eigen::Map< + Eigen::Matrix > + MatrixRef; + + typedef Eigen::Matrix + Vector; + + typedef Eigen::Map < + Eigen::Matrix > + VectorRef; + + + typedef Eigen::Map< + const Eigen::Matrix > + ConstMatrixRef; + + typedef Eigen::Map < + const Eigen::Matrix > + ConstVectorRef; +}; + +} // namespace ceres + +#endif // CERES_INTERNAL_EIGEN_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h new file mode 100644 index 00000000000..30cc5fc4a6c --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h @@ -0,0 +1,193 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: rennie@google.com (Jeffrey Rennie) +// Author: sanjay@google.com (Sanjay Ghemawat) -- renamed to FixedArray + +#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_ +#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_ + +#include +#include +#include "ceres/internal/manual_constructor.h" + +namespace ceres { +namespace internal { + +// A FixedArray represents a non-resizable array of T where the +// length of the array does not need to be a compile time constant. +// +// FixedArray allocates small arrays inline, and large arrays on +// the heap. It is a good replacement for non-standard and deprecated +// uses of alloca() and variable length arrays (a GCC extension). +// +// FixedArray keeps performance fast for small arrays, because it +// avoids heap operations. It also helps reduce the chances of +// accidentally overflowing your stack if large input is passed to +// your function. +// +// Also, FixedArray is useful for writing portable code. Not all +// compilers support arrays of dynamic size. + +// Most users should not specify an inline_elements argument and let +// FixedArray<> automatically determine the number of elements +// to store inline based on sizeof(T). +// +// If inline_elements is specified, the FixedArray<> implementation +// will store arrays of length <= inline_elements inline. +// +// Finally note that unlike vector FixedArray will not zero-initialize +// simple types like int, double, bool, etc. +// +// Non-POD types will be default-initialized just like regular vectors or +// arrays. + +#if defined(_WIN64) + typedef __int64 ssize_t; +#elif defined(_WIN32) + typedef __int32 ssize_t; +#endif + +template +class FixedArray { + public: + // For playing nicely with stl: + typedef T value_type; + typedef T* iterator; + typedef T const* const_iterator; + typedef T& reference; + typedef T const& const_reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + typedef size_t size_type; + + // REQUIRES: n >= 0 + // Creates an array object that can store "n" elements. + // + // FixedArray will not zero-initialiaze POD (simple) types like int, + // double, bool, etc. + // Non-POD types will be default-initialized just like regular vectors or + // arrays. + explicit FixedArray(size_type n); + + // Releases any resources. + ~FixedArray(); + + // Returns the length of the array. + inline size_type size() const { return size_; } + + // Returns the memory size of the array in bytes. + inline size_t memsize() const { return size_ * sizeof(T); } + + // Returns a pointer to the underlying element array. + inline const T* get() const { return &array_[0].element; } + inline T* get() { return &array_[0].element; } + + // REQUIRES: 0 <= i < size() + // Returns a reference to the "i"th element. + inline T& operator[](size_type i) { + DCHECK_GE(i, 0); + DCHECK_LT(i, size_); + return array_[i].element; + } + + // REQUIRES: 0 <= i < size() + // Returns a reference to the "i"th element. + inline const T& operator[](size_type i) const { + DCHECK_GE(i, 0); + DCHECK_LT(i, size_); + return array_[i].element; + } + + inline iterator begin() { return &array_[0].element; } + inline iterator end() { return &array_[size_].element; } + + inline const_iterator begin() const { return &array_[0].element; } + inline const_iterator end() const { return &array_[size_].element; } + + private: + // Container to hold elements of type T. This is necessary to handle + // the case where T is a a (C-style) array. The size of InnerContainer + // and T must be the same, otherwise callers' assumptions about use + // of this code will be broken. + struct InnerContainer { + T element; + }; + + // How many elements should we store inline? + // a. If not specified, use a default of 256 bytes (256 bytes + // seems small enough to not cause stack overflow or unnecessary + // stack pollution, while still allowing stack allocation for + // reasonably long character arrays. + // b. Never use 0 length arrays (not ISO C++) + static const size_type S1 = ((inline_elements < 0) + ? (256/sizeof(T)) : inline_elements); + static const size_type S2 = (S1 <= 0) ? 1 : S1; + static const size_type kInlineElements = S2; + + size_type const size_; + InnerContainer* const array_; + + // Allocate some space, not an array of elements of type T, so that we can + // skip calling the T constructors and destructors for space we never use. + ManualConstructor inline_space_[kInlineElements]; +}; + +// Implementation details follow + +template +inline FixedArray::FixedArray(typename FixedArray::size_type n) + : size_(n), + array_((n <= kInlineElements + ? reinterpret_cast(inline_space_) + : new InnerContainer[n])) { + DCHECK_GE(n, 0); + + // Construct only the elements actually used. + if (array_ == reinterpret_cast(inline_space_)) { + for (int i = 0; i != size_; ++i) { + inline_space_[i].Init(); + } + } +} + +template +inline FixedArray::~FixedArray() { + if (array_ != reinterpret_cast(inline_space_)) { + delete[] array_; + } else { + for (int i = 0; i != size_; ++i) { + inline_space_[i].Destroy(); + } + } +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h new file mode 100644 index 00000000000..0cfd773bcca --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h @@ -0,0 +1,154 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// +// Various Google-specific macros. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. + +#ifndef CERES_PUBLIC_INTERNAL_MACROS_H_ +#define CERES_PUBLIC_INTERNAL_MACROS_H_ + +#include // For size_t. + +// A macro to disallow the copy constructor and operator= functions +// This should be used in the private: declarations for a class +// +// For disallowing only assign or copy, write the code directly, but declare +// the intend in a comment, for example: +// void operator=(const TypeName&); // DISALLOW_ASSIGN +// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken +// semantically, one should either use disallow both or neither. Try to +// avoid these in new code. +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template +char (&ArraySizeHelper(T (&array)[N]))[N]; + +// That gcc wants both of these prototypes seems mysterious. VC, for +// its part, can't decide which to use (another mystery). Matching of +// template overloads: the final frontier. +#ifndef _WIN32 +template +char (&ArraySizeHelper(const T (&array)[N]))[N]; +#endif + +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +// ARRAYSIZE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +// +// Kudos to Jorg Brown for this simple and elegant implementation. +// +// - wan 2005-11-16 +// +// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE. However, +// the definition comes from the over-broad windows.h header that +// introduces a macro, ERROR, that conflicts with the logging framework +// that Ceres uses. Instead, rename ARRAYSIZE to CERES_ARRAYSIZE. +#define CERES_ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast(!(sizeof(a) % sizeof(*(a))))) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() MUST_USE_RESULT; +// +#undef MUST_USE_RESULT +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ + && !defined(COMPILER_ICC) +#define MUST_USE_RESULT __attribute__ ((warn_unused_result)) +#else +#define MUST_USE_RESULT +#endif + +#endif // CERES_PUBLIC_INTERNAL_MACROS_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h new file mode 100644 index 00000000000..a1d1f444e36 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h @@ -0,0 +1,214 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: kenton@google.com (Kenton Varda) +// +// ManualConstructor statically-allocates space in which to store some +// object, but does not initialize it. You can then call the constructor +// and destructor for the object yourself as you see fit. This is useful +// for memory management optimizations, where you want to initialize and +// destroy an object multiple times but only allocate it once. +// +// (When I say ManualConstructor statically allocates space, I mean that +// the ManualConstructor object itself is forced to be the right size.) + +#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_ +#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_ + +#include + +namespace ceres { +namespace internal { + +// ------- Define ALIGNED_CHAR_ARRAY -------------------------------- + +#ifndef ALIGNED_CHAR_ARRAY + +// Because MSVC and older GCCs require that the argument to their alignment +// construct to be a literal constant integer, we use a template instantiated +// at all the possible powers of two. +template struct AlignType { }; +template struct AlignType<0, size> { typedef char result[size]; }; +#if defined(_MSC_VER) +#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __declspec(align(X)) +#define BASE_PORT_H_ALIGN_OF(T) __alignof(T) +#elif defined(__GNUC__) +#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X))) +#define BASE_PORT_H_ALIGN_OF(T) __alignof__(T) +#endif + +#if defined(BASE_PORT_H_ALIGN_ATTRIBUTE) + +#define BASE_PORT_H_ALIGNTYPE_TEMPLATE(X) \ + template struct AlignType { \ + typedef BASE_PORT_H_ALIGN_ATTRIBUTE(X) char result[size]; \ + } + +BASE_PORT_H_ALIGNTYPE_TEMPLATE(1); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(2); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(4); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(8); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(16); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(32); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(64); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(128); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(256); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(512); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(1024); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(2048); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(4096); +BASE_PORT_H_ALIGNTYPE_TEMPLATE(8192); +// Any larger and MSVC++ will complain. + +#define ALIGNED_CHAR_ARRAY(T, Size) \ + typename AlignType::result + +#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE +#undef BASE_PORT_H_ALIGN_ATTRIBUTE + +#else // defined(BASE_PORT_H_ALIGN_ATTRIBUTE) +#define ALIGNED_CHAR_ARRAY you_must_define_ALIGNED_CHAR_ARRAY_for_your_compiler +#endif // defined(BASE_PORT_H_ALIGN_ATTRIBUTE) + +#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE +#undef BASE_PORT_H_ALIGN_ATTRIBUTE + +#endif // ALIGNED_CHAR_ARRAY + +template +class ManualConstructor { + public: + // No constructor or destructor because one of the most useful uses of + // this class is as part of a union, and members of a union cannot have + // constructors or destructors. And, anyway, the whole point of this + // class is to bypass these. + + inline Type* get() { + return reinterpret_cast(space_); + } + inline const Type* get() const { + return reinterpret_cast(space_); + } + + inline Type* operator->() { return get(); } + inline const Type* operator->() const { return get(); } + + inline Type& operator*() { return *get(); } + inline const Type& operator*() const { return *get(); } + + // You can pass up to four constructor arguments as arguments of Init(). + inline void Init() { + new(space_) Type; + } + + template + inline void Init(const T1& p1) { + new(space_) Type(p1); + } + + template + inline void Init(const T1& p1, const T2& p2) { + new(space_) Type(p1, p2); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3) { + new(space_) Type(p1, p2, p3); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { + new(space_) Type(p1, p2, p3, p4); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5) { + new(space_) Type(p1, p2, p3, p4, p5); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6) { + new(space_) Type(p1, p2, p3, p4, p5, p6); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8, + const T9& p9) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8, + const T9& p9, const T10& p10) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + } + + template + inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, + const T5& p5, const T6& p6, const T7& p7, const T8& p8, + const T9& p9, const T10& p10, const T11& p11) { + new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + } + + inline void Destroy() { + get()->~Type(); + } + + private: + ALIGNED_CHAR_ARRAY(Type, 1) space_; +}; + +#undef ALIGNED_CHAR_ARRAY + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/port.h b/extern/libmv/third_party/ceres/include/ceres/internal/port.h new file mode 100644 index 00000000000..9a3e5cced58 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/port.h @@ -0,0 +1,44 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_PUBLIC_INTERNAL_PORT_H_ +#define CERES_PUBLIC_INTERNAL_PORT_H_ + +namespace ceres { + +// It is unfortunate that this import of the entire standard namespace is +// necessary. The reasons are historical and won't be explained here, but +// suffice to say it is not a mistake and can't be removed without breaking +// things outside of the Ceres optimization package. +using namespace std; + +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_PORT_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h b/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h new file mode 100644 index 00000000000..44f198b339d --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h @@ -0,0 +1,311 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: jorg@google.com (Jorg Brown) +// +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class, and its closely-related brethren, +// scoped_array, scoped_ptr_malloc, and make_scoped_ptr. + +#ifndef CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_ +#define CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_ + +#include +#include +#include + +namespace ceres { +namespace internal { + +template class scoped_ptr; +template class scoped_ptr_malloc; +template class scoped_array; + +template +scoped_ptr make_scoped_ptr(C *); + +// A scoped_ptr is like a T*, except that the destructor of scoped_ptr +// automatically deletes the pointer it holds (if any). That is, scoped_ptr +// owns the T object that it points to. Like a T*, a scoped_ptr may hold +// either NULL or a pointer to a T object. Also like T*, scoped_ptr is +// thread-compatible, and once you dereference it, you get the threadsafety +// guarantees of T. +// +// The size of a scoped_ptr is small: sizeof(scoped_ptr) == sizeof(C*) +template +class scoped_ptr { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_ptr. + // The input parameter must be allocated with new. + explicit scoped_ptr(C* p = NULL) : ptr_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + ptr_ = p; + } + } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + C* get() const { return ptr_; } + + // Comparison operators. + // These return whether a scoped_ptr and a raw pointer refer to + // the same object, not just to two different but equal objects. + bool operator==(const C* p) const { return ptr_ == p; } + bool operator!=(const C* p) const { return ptr_ != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + C* tmp = ptr_; + ptr_ = p2.ptr_; + p2.ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + + private: + C* ptr_; + + // google3 friend class that can access copy ctor (although if it actually + // calls a copy ctor, there will be a problem) see below + friend scoped_ptr make_scoped_ptr(C *p); + + // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different scoped_ptrs. + template bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; + + // Disallow evil constructors + scoped_ptr(const scoped_ptr&); + void operator=(const scoped_ptr&); +}; + +// Free functions +template +inline void swap(scoped_ptr& p1, scoped_ptr& p2) { + p1.swap(p2); +} + +template +inline bool operator==(const C* p1, const scoped_ptr& p2) { + return p1 == p2.get(); +} + +template +inline bool operator==(const C* p1, const scoped_ptr& p2) { + return p1 == p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_ptr& p2) { + return p1 != p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_ptr& p2) { + return p1 != p2.get(); +} + +template +scoped_ptr make_scoped_ptr(C *p) { + // This does nothing but to return a scoped_ptr of the type that the passed + // pointer is of. (This eliminates the need to specify the name of T when + // making a scoped_ptr that is used anonymously/temporarily.) From an + // access control point of view, we construct an unnamed scoped_ptr here + // which we return and thus copy-construct. Hence, we need to have access + // to scoped_ptr::scoped_ptr(scoped_ptr const &). However, it is guaranteed + // that we never actually call the copy constructor, which is a good thing + // as we would call the temporary's object destructor (and thus delete p) + // if we actually did copy some object, here. + return scoped_ptr(p); +} + +// scoped_array is like scoped_ptr, except that the caller must allocate +// with new [] and the destructor deletes objects with delete []. +// +// As with scoped_ptr, a scoped_array either points to an object +// or is NULL. A scoped_array owns the object that it points to. +// scoped_array is thread-compatible, and once you index into it, +// the returned objects have only the threadsafety guarantees of T. +// +// Size: sizeof(scoped_array) == sizeof(C*) +template +class scoped_array { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_array. + // The input parameter must be allocated with new []. + explicit scoped_array(C* p = NULL) : array_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_array() { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != array_) { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + array_ = p; + } + } + + // Get one element of the current object. + // Will assert() if there is no current object, or index i is negative. + C& operator[](std::ptrdiff_t i) const { + assert(i >= 0); + assert(array_ != NULL); + return array_[i]; + } + + // Get a pointer to the zeroth element of the current object. + // If there is no current object, return NULL. + C* get() const { + return array_; + } + + // Comparison operators. + // These return whether a scoped_array and a raw pointer refer to + // the same array, not just to two different but equal arrays. + bool operator==(const C* p) const { return array_ == p; } + bool operator!=(const C* p) const { return array_ != p; } + + // Swap two scoped arrays. + void swap(scoped_array& p2) { + C* tmp = array_; + array_ = p2.array_; + p2.array_ = tmp; + } + + // Release an array. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = array_; + array_ = NULL; + return retVal; + } + + private: + C* array_; + + // Forbid comparison of different scoped_array types. + template bool operator==(scoped_array const& p2) const; + template bool operator!=(scoped_array const& p2) const; + + // Disallow evil constructors + scoped_array(const scoped_array&); + void operator=(const scoped_array&); +}; + +// Free functions +template +inline void swap(scoped_array& p1, scoped_array& p2) { + p1.swap(p2); +} + +template +inline bool operator==(const C* p1, const scoped_array& p2) { + return p1 == p2.get(); +} + +template +inline bool operator==(const C* p1, const scoped_array& p2) { + return p1 == p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_array& p2) { + return p1 != p2.get(); +} + +template +inline bool operator!=(const C* p1, const scoped_array& p2) { + return p1 != p2.get(); +} + +// This class wraps the c library function free() in a class that can be +// passed as a template argument to scoped_ptr_malloc below. +class ScopedPtrMallocFree { + public: + inline void operator()(void* x) const { + free(x); + } +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h new file mode 100644 index 00000000000..88da992d0c5 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h @@ -0,0 +1,159 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// When an iteration callback is specified, Ceres calls the callback after each +// optimizer step and pass it an IterationSummary object, defined below. + +#ifndef CERES_PUBLIC_ITERATION_CALLBACK_H_ +#define CERES_PUBLIC_ITERATION_CALLBACK_H_ + +#include "ceres/types.h" + +namespace ceres { + +// This struct describes the state of the optimizer after each +// iteration of the minimization. +struct IterationSummary { + // Current iteration number. + int32 iteration; + + // Whether or not the algorithm made progress in this iteration. + bool step_is_successful; + + // Value of the objective function. + double cost; + + // Change in the value of the objective function in this + // iteration. This can be positive or negative. Negative change + // means that the step was not successful. + double cost_change; + + // Infinity norm of the gradient vector. + double gradient_max_norm; + + // 2-norm of the size of the step computed by the optimization + // algorithm. + double step_norm; + + // For trust region algorithms, the ratio of the actual change in + // cost and the change in the cost of the linearized approximation. + double relative_decrease; + + // Value of the regularization parameter for Levenberg-Marquardt + // algorithm at the end of the current iteration. + double mu; + + // For the inexact step Levenberg-Marquardt algorithm, this is the + // relative accuracy with which the Newton(LM) step is solved. This + // number affects only the iterative solvers capable of solving + // linear systems inexactly. Factorization-based exact solvers + // ignore it. + double eta; + + // Number of iterations taken by the linear solver to solve for the + // Newton step. + int linear_solver_iterations; + + // TODO(sameeragarwal): Change to use a higher precision timer using + // clock_gettime. + // Time (in seconds) spent inside the linear least squares solver. + int iteration_time_sec; + + // Time (in seconds) spent inside the linear least squares solver. + int linear_solver_time_sec; +}; + +// Interface for specifying callbacks that are executed at the end of +// each iteration of the Minimizer. The solver uses the return value +// of operator() to decide whether to continue solving or to +// terminate. The user can return three values. +// +// SOLVER_ABORT indicates that the callback detected an abnormal +// situation. The solver returns without updating the parameter blocks +// (unless Solver::Options::update_state_every_iteration is set +// true). Solver returns with Solver::Summary::termination_type set to +// USER_ABORT. +// +// SOLVER_TERMINATE_SUCCESSFULLY indicates that there is no need to +// optimize anymore (some user specified termination criterion has +// been met). Solver returns with Solver::Summary::termination_type +// set to USER_SUCCESS. +// +// SOLVER_CONTINUE indicates that the solver should continue +// optimizing. +// +// For example, the following Callback is used internally by Ceres to +// log the progress of the optimization. +// +// Callback for logging the state of the minimizer to STDERR or STDOUT +// depending on the user's preferences and logging level. +// +// class LoggingCallback : public IterationCallback { +// public: +// explicit LoggingCallback(bool log_to_stdout) +// : log_to_stdout_(log_to_stdout) {} +// +// ~LoggingCallback() {} +// +// CallbackReturnType operator()(const IterationSummary& summary) { +// const char* kReportRowFormat = +// "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " +// "rho:% 3.2e mu:% 3.2e eta:% 3.2e li:% 3d"; +// string output = StringPrintf(kReportRowFormat, +// summary.iteration, +// summary.cost, +// summary.cost_change, +// summary.gradient_max_norm, +// summary.step_norm, +// summary.relative_decrease, +// summary.mu, +// summary.eta, +// summary.linear_solver_iterations); +// if (log_to_stdout_) { +// cout << output << endl; +// } else { +// VLOG(1) << output; +// } +// return SOLVER_CONTINUE; +// } +// +// private: +// const bool log_to_stdout_; +// }; +// +class IterationCallback { + public: + virtual ~IterationCallback() {} + virtual CallbackReturnType operator()(const IterationSummary& summary) = 0; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_ITERATION_CALLBACK_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h new file mode 100644 index 00000000000..264861735ed --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/jet.h @@ -0,0 +1,755 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A simple implementation of N-dimensional dual numbers, for automatically +// computing exact derivatives of functions. +// +// While a complete treatment of the mechanics of automatic differentation is +// beyond the scope of this header (see +// http://en.wikipedia.org/wiki/Automatic_differentiation for details), the +// basic idea is to extend normal arithmetic with an extra element, "e," often +// denoted with the greek symbol epsilon, such that e != 0 but e^2 = 0. Dual +// numbers are extensions of the real numbers analogous to complex numbers: +// whereas complex numbers augment the reals by introducing an imaginary unit i +// such that i^2 = -1, dual numbers introduce an "infinitesimal" unit e such +// that e^2 = 0. Dual numbers have two components: the "real" component and the +// "infinitesimal" component, generally written as x + y*e. Surprisingly, this +// leads to a convenient method for computing exact derivatives without needing +// to manipulate complicated symbolic expressions. +// +// For example, consider the function +// +// f(x) = x^2 , +// +// evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20. +// Next, augument 10 with an infinitesimal to get: +// +// f(10 + e) = (10 + e)^2 +// = 100 + 2 * 10 * e + e^2 +// = 100 + 20 * e -+- +// -- | +// | +--- This is zero, since e^2 = 0 +// | +// +----------------- This is df/dx! +// +// Note that the derivative of f with respect to x is simply the infinitesimal +// component of the value of f(x + e). So, in order to take the derivative of +// any function, it is only necessary to replace the numeric "object" used in +// the function with one extended with infinitesimals. The class Jet, defined in +// this header, is one such example of this, where substitution is done with +// templates. +// +// To handle derivatives of functions taking multiple arguments, different +// infinitesimals are used, one for each variable to take the derivative of. For +// example, consider a scalar function of two scalar parameters x and y: +// +// f(x, y) = x^2 + x * y +// +// Following the technique above, to compute the derivatives df/dx and df/dy for +// f(1, 3) involves doing two evaluations of f, the first time replacing x with +// x + e, the second time replacing y with y + e. +// +// For df/dx: +// +// f(1 + e, y) = (1 + e)^2 + (1 + e) * 3 +// = 1 + 2 * e + 3 + 3 * e +// = 4 + 5 * e +// +// --> df/dx = 5 +// +// For df/dy: +// +// f(1, 3 + e) = 1^2 + 1 * (3 + e) +// = 1 + 3 + e +// = 4 + e +// +// --> df/dy = 1 +// +// To take the gradient of f with the implementation of dual numbers ("jets") in +// this file, it is necessary to create a single jet type which has components +// for the derivative in x and y, and passing them to a templated version of f: +// +// template +// T f(const T &x, const T &y) { +// return x * x + x * y; +// } +// +// // The "2" means there should be 2 dual number components. +// Jet x(0); // Pick the 0th dual number for x. +// Jet y(1); // Pick the 1st dual number for y. +// Jet z = f(x, y); +// +// LG << "df/dx = " << z.a[0] +// << "df/dy = " << z.a[1]; +// +// Most users should not use Jet objects directly; a wrapper around Jet objects, +// which makes computing the derivative, gradient, or jacobian of templated +// functors simple, is in autodiff.h. Even autodiff.h should not be used +// directly; instead autodiff_cost_function.h is typically the file of interest. +// +// For the more mathematically inclined, this file implements first-order +// "jets". A 1st order jet is an element of the ring +// +// T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2 +// +// which essentially means that each jet consists of a "scalar" value 'a' from T +// and a 1st order perturbation vector 'v' of length N: +// +// x = a + \sum_i v[i] t_i +// +// A shorthand is to write an element as x = a + u, where u is the pertubation. +// Then, the main point about the arithmetic of jets is that the product of +// perturbations is zero: +// +// (a + u) * (b + v) = ab + av + bu + uv +// = ab + (av + bu) + 0 +// +// which is what operator* implements below. Addition is simpler: +// +// (a + u) + (b + v) = (a + b) + (u + v). +// +// The only remaining question is how to evaluate the function of a jet, for +// which we use the chain rule: +// +// f(a + u) = f(a) + f'(a) u +// +// where f'(a) is the (scalar) derivative of f at a. +// +// By pushing these things through sufficiently and suitably templated +// functions, we can do automatic differentiation. Just be sure to turn on +// function inlining and common-subexpression elimination, or it will be very +// slow! +// +// WARNING: Most Ceres users should not directly include this file or know the +// details of how jets work. Instead the suggested method for automatic +// derivatives is to use autodiff_cost_function.h, which is a wrapper around +// both jets.h and autodiff.h to make taking derivatives of cost functions for +// use in Ceres easier. + +#ifndef CERES_PUBLIC_JET_H_ +#define CERES_PUBLIC_JET_H_ + +#include +#include +#include // NOLINT +#include + +#include "Eigen/Core" + +// Visual Studio 2010 or older version +#if defined(_MSC_VER) && _MSC_VER <= 1600 +namespace std { +inline bool isfinite(double x) { return _finite(x); } +inline bool isinf (double x) { return !_finite(x) && !_isnan(x); } +inline bool isnan (double x) { return _isnan(x); } +inline bool isnormal(double x) { return _finite(x) && x != 0.0; } +} // namespace std +#endif + +namespace ceres { + +template +struct Jet { + enum { DIMENSION = N }; + + // Default-construct "a" because otherwise this can lead to false errors about + // uninitialized uses when other classes relying on default constructed T + // (where T is a Jet). This usually only happens in opt mode. Note that + // the C++ standard mandates that e.g. default constructed doubles are + // initialized to 0.0; see sections 8.5 of the C++03 standard. + Jet() : a() {} + + // Constructor from scalar: a + 0. + explicit Jet(const T& value) { + a = value; + v.setZero(); + } + + // Constructor from scalar plus variable: a + t_i. + Jet(const T& value, int k) { + a = value; + v.setZero(); + v[k] = T(1.0); + } + + /* + + // Construct from an array where the first element is the scalar. + // This is templated to support converting from other data types. + template + Jet(const D* scalar_and_derivatives) { + a = T(scalar_and_derivatives[0]); + v = Eigen::Map >( + scalar_and_derivatives + 1, N).cast(); + } + */ + + // Compound operators + Jet& operator+=(const Jet &y) { + *this = *this + y; + return *this; + } + + Jet& operator-=(const Jet &y) { + *this = *this - y; + return *this; + } + + Jet& operator*=(const Jet &y) { + *this = *this * y; + return *this; + } + + Jet& operator/=(const Jet &y) { + *this = *this / y; + return *this; + } + + T a; // The scalar part. + Eigen::Matrix v; // The infinitesimal part. +}; + +// Unary + +template inline +Jet const& operator+(const Jet& f) { + return f; +} + +// TODO(keir): Try adding __attribute__((always_inline)) to these functions to +// see if it causes a performance increase. + +// Unary - +template inline +Jet operator-(const Jet&f) { + Jet g; + g.a = -f.a; + g.v = -f.v; + return g; +} + +// Binary + +template inline +Jet operator+(const Jet& f, + const Jet& g) { + Jet h; + h.a = f.a + g.a; + h.v = f.v + g.v; + return h; +} + +// Binary + with a scalar: x + s +template inline +Jet operator+(const Jet& f, T s) { + Jet h; + h.a = f.a + s; + h.v = f.v; + return h; +} + +// Binary + with a scalar: s + x +template inline +Jet operator+(T s, const Jet& f) { + Jet h; + h.a = f.a + s; + h.v = f.v; + return h; +} + +// Binary - +template inline +Jet operator-(const Jet& f, + const Jet& g) { + Jet h; + h.a = f.a - g.a; + h.v = f.v - g.v; + return h; +} + +// Binary - with a scalar: x - s +template inline +Jet operator-(const Jet& f, T s) { + Jet h; + h.a = f.a - s; + h.v = f.v; + return h; +} + +// Binary - with a scalar: s - x +template inline +Jet operator-(T s, const Jet& f) { + Jet h; + h.a = s - f.a; + h.v = -f.v; + return h; +} + +// Binary * +template inline +Jet operator*(const Jet& f, + const Jet& g) { + Jet h; + h.a = f.a * g.a; + h.v = f.a * g.v + f.v * g.a; + return h; +} + +// Binary * with a scalar: x * s +template inline +Jet operator*(const Jet& f, T s) { + Jet h; + h.a = f.a * s; + h.v = f.v * s; + return h; +} + +// Binary * with a scalar: s * x +template inline +Jet operator*(T s, const Jet& f) { + Jet h; + h.a = f.a * s; + h.v = f.v * s; + return h; +} + +// Binary / +template inline +Jet operator/(const Jet& f, + const Jet& g) { + Jet h; + // This uses: + // + // a + u (a + u)(b - v) (a + u)(b - v) + // ----- = -------------- = -------------- + // b + v (b + v)(b - v) b^2 + // + // which holds because v*v = 0. + h.a = f.a / g.a; + h.v = (f.v - f.a / g.a * g.v) / g.a; + return h; +} + +// Binary / with a scalar: s / x +template inline +Jet operator/(T s, const Jet& g) { + Jet h; + h.a = s / g.a; + h.v = - s * g.v / (g.a * g.a); + return h; +} + +// Binary / with a scalar: x / s +template inline +Jet operator/(const Jet& f, T s) { + Jet h; + h.a = f.a / s; + h.v = f.v / s; + return h; +} + +// Binary comparison operators for both scalars and jets. +#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \ +template inline \ +bool operator op(const Jet& f, const Jet& g) { \ + return f.a op g.a; \ +} \ +template inline \ +bool operator op(const T& s, const Jet& g) { \ + return s op g.a; \ +} \ +template inline \ +bool operator op(const Jet& f, const T& s) { \ + return f.a op s; \ +} +CERES_DEFINE_JET_COMPARISON_OPERATOR( < ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( <= ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( > ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( >= ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( == ) // NOLINT +CERES_DEFINE_JET_COMPARISON_OPERATOR( != ) // NOLINT +#undef CERES_DEFINE_JET_COMPARISON_OPERATOR + +// Pull some functions from namespace std. +// +// This is necessary because we want to use the same name (e.g. 'sqrt') for +// double-valued and Jet-valued functions, but we are not allowed to put +// Jet-valued functions inside namespace std. +// +// Missing: cosh, sinh, tanh, tan +// TODO(keir): Switch to "using". +inline double abs (double x) { return std::abs(x); } +inline double log (double x) { return std::log(x); } +inline double exp (double x) { return std::exp(x); } +inline double sqrt (double x) { return std::sqrt(x); } +inline double cos (double x) { return std::cos(x); } +inline double acos (double x) { return std::acos(x); } +inline double sin (double x) { return std::sin(x); } +inline double asin (double x) { return std::asin(x); } +inline bool isfinite(double x) { return std::isfinite(x); } +inline bool isinf (double x) { return std::isinf(x); } +inline bool isnan (double x) { return std::isnan(x); } +inline bool isnormal(double x) { return std::isnormal(x); } +inline double pow (double x, double y) { return std::pow(x, y); } +inline double atan2(double y, double x) { return std::atan2(y, x); } + +// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule. + +// abs(x + h) ~= x + h or -(x + h) +template inline +Jet abs(const Jet& f) { + return f.a < T(0.0) ? -f : f; +} + +// log(a + h) ~= log(a) + h / a +template inline +Jet log(const Jet& f) { + Jet g; + g.a = log(f.a); + g.v = f.v / f.a; + return g; +} + +// exp(a + h) ~= exp(a) + exp(a) h +template inline +Jet exp(const Jet& f) { + Jet g; + g.a = exp(f.a); + g.v = g.a * f.v; + return g; +} + +// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a)) +template inline +Jet sqrt(const Jet& f) { + Jet g; + g.a = sqrt(f.a); + g.v = f.v / (T(2.0) * g.a); + return g; +} + +// cos(a + h) ~= cos(a) - sin(a) h +template inline +Jet cos(const Jet& f) { + Jet g; + g.a = cos(f.a); + T sin_a = sin(f.a); + g.v = - sin_a * f.v; + return g; +} + +// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h +template inline +Jet acos(const Jet& f) { + Jet g; + g.a = acos(f.a); + g.v = - T(1.0) / sqrt(T(1.0) - f.a * f.a) * f.v; + return g; +} + +// sin(a + h) ~= sin(a) + cos(a) h +template inline +Jet sin(const Jet& f) { + Jet g; + g.a = sin(f.a); + T cos_a = cos(f.a); + g.v = cos_a * f.v; + return g; +} + +// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h +template inline +Jet asin(const Jet& f) { + Jet g; + g.a = asin(f.a); + g.v = T(1.0) / sqrt(T(1.0) - f.a * f.a) * f.v; + return g; +} + +// Jet Classification. It is not clear what the appropriate semantics are for +// these classifications. This picks that isfinite and isnormal are "all" +// operations, i.e. all elements of the jet must be finite for the jet itself to +// be finite (or normal). For isnan and isinf, the answer is less clear. This +// takes a "any" approach for isnan and isinf such that if any part of a jet is +// nan or inf, then the entire jet is nan or inf. This leads to strange +// situations like a jet can be both isinf and isnan, but in practice the "any" +// semantics are the most useful for e.g. checking that derivatives are sane. + +// The jet is finite if all parts of the jet are finite. +template inline +bool isfinite(const Jet& f) { + if (!isfinite(f.a)) { + return false; + } + for (int i = 0; i < N; ++i) { + if (!isfinite(f.v[i])) { + return false; + } + } + return true; +} + +// The jet is infinite if any part of the jet is infinite. +template inline +bool isinf(const Jet& f) { + if (isinf(f.a)) { + return true; + } + for (int i = 0; i < N; i++) { + if (isinf(f.v[i])) { + return true; + } + } + return false; +} + +// The jet is NaN if any part of the jet is NaN. +template inline +bool isnan(const Jet& f) { + if (isnan(f.a)) { + return true; + } + for (int i = 0; i < N; ++i) { + if (isnan(f.v[i])) { + return true; + } + } + return false; +} + +// The jet is normal if all parts of the jet are normal. +template inline +bool isnormal(const Jet& f) { + if (!isnormal(f.a)) { + return false; + } + for (int i = 0; i < N; ++i) { + if (!isnormal(f.v[i])) { + return false; + } + } + return true; +} + +// atan2(b + db, a + da) ~= atan2(b, a) + (- b da + a db) / (a^2 + b^2) +// +// In words: the rate of change of theta is 1/r times the rate of +// change of (x, y) in the positive angular direction. +template inline +Jet atan2(const Jet& g, const Jet& f) { + // Note order of arguments: + // + // f = a + da + // g = b + db + + Jet out; + + out.a = atan2(g.a, f.a); + + T const temp = T(1.0) / (f.a * f.a + g.a * g.a); + out.v = temp * (- g.a * f.v + f.a * g.v); + return out; +} + + +// pow -- base is a differentiatble function, exponent is a constant. +// (a+da)^p ~= a^p + p*a^(p-1) da +template inline +Jet pow(const Jet& f, double g) { + Jet out; + out.a = pow(f.a, g); + T const temp = g * pow(f.a, g - T(1.0)); + out.v = temp * f.v; + return out; +} + +// pow -- base is a constant, exponent is a differentiable function. +// (a)^(p+dp) ~= a^p + a^p log(a) dp +template inline +Jet pow(double f, const Jet& g) { + Jet out; + out.a = pow(f, g.a); + T const temp = log(f) * out.a; + out.v = temp * g.v; + return out; +} + + +// pow -- both base and exponent are differentiable functions. +// (a+da)^(b+db) ~= a^b + b * a^(b-1) da + a^b log(a) * db +template inline +Jet pow(const Jet& f, const Jet& g) { + Jet out; + + T const temp1 = pow(f.a, g.a); + T const temp2 = g.a * pow(f.a, g.a - T(1.0)); + T const temp3 = temp1 * log(f.a); + + out.a = temp1; + out.v = temp2 * f.v + temp3 * g.v; + return out; +} + +// Define the helper functions Eigen needs to embed Jet types. +// +// NOTE(keir): machine_epsilon() and precision() are missing, because they don't +// work with nested template types (e.g. where the scalar is itself templated). +// Among other things, this means that decompositions of Jet's does not work, +// for example +// +// Matrix ... > A, x, b; +// ... +// A.solve(b, &x) +// +// does not work and will fail with a strange compiler error. +// +// TODO(keir): This is an Eigen 2.0 limitation that is lifted in 3.0. When we +// switch to 3.0, also add the rest of the specialization functionality. +template inline const Jet& ei_conj(const Jet& x) { return x; } // NOLINT +template inline const Jet& ei_real(const Jet& x) { return x; } // NOLINT +template inline Jet ei_imag(const Jet& ) { return Jet(0.0); } // NOLINT +template inline Jet ei_abs (const Jet& x) { return fabs(x); } // NOLINT +template inline Jet ei_abs2(const Jet& x) { return x * x; } // NOLINT +template inline Jet ei_sqrt(const Jet& x) { return sqrt(x); } // NOLINT +template inline Jet ei_exp (const Jet& x) { return exp(x); } // NOLINT +template inline Jet ei_log (const Jet& x) { return log(x); } // NOLINT +template inline Jet ei_sin (const Jet& x) { return sin(x); } // NOLINT +template inline Jet ei_cos (const Jet& x) { return cos(x); } // NOLINT +template inline Jet ei_pow (const Jet& x, Jet y) { return pow(x, y); } // NOLINT + +// Note: This has to be in the ceres namespace for argument dependent lookup to +// function correctly. Otherwise statements like CHECK_LE(x, 2.0) fail with +// strange compile errors. +template +inline std::ostream &operator<<(std::ostream &s, const Jet& z) { + return s << "[" << z.a << " ; " << z.v.transpose() << "]"; +} + +// A jet traits class to make it easier to work with mixed auto / numeric diff. +template +struct JetOps { + static bool IsScalar() { + return true; + } + static T GetScalar(const T& t) { + return t; + } + static void SetScalar(const T& scalar, T* t) { + *t = scalar; + } + static void ScaleDerivative(double scale_by, T *value) { + // For double, there is no derivative to scale. + } +}; + +template +struct JetOps > { + static bool IsScalar() { + return false; + } + static T GetScalar(const Jet& t) { + return t.a; + } + static void SetScalar(const T& scalar, Jet* t) { + t->a = scalar; + } + static void ScaleDerivative(double scale_by, Jet *value) { + value->v *= scale_by; + } +}; + +template +struct Chain { + static ArgumentType Rule(const FunctionType &f, + const FunctionType dfdx[kNumArgs], + const ArgumentType x[kNumArgs]) { + // In the default case of scalars, there's nothing to do since there are no + // derivatives to propagate. + return f; + } +}; + +// XXX Add documentation here! +template +struct Chain > { + static Jet Rule(const FunctionType &f, + const FunctionType dfdx[kNumArgs], + const Jet x[kNumArgs]) { + // x is itself a function of another variable ("z"); what this function + // needs to return is "f", but with the derivative with respect to z + // attached to the jet. So combine the derivative part of x's jets to form + // a Jacobian matrix between x and z (i.e. dx/dz). + Eigen::Matrix dxdz; + for (int i = 0; i < kNumArgs; ++i) { + dxdz.row(i) = x[i].v.transpose(); + } + + // Map the input gradient dfdx into an Eigen row vector. + Eigen::Map > + vector_dfdx(dfdx, 1, kNumArgs); + + // Now apply the chain rule to obtain df/dz. Combine the derivative with + // the scalar part to obtain f with full derivative information. + Jet jet_f; + jet_f.a = f; + jet_f.v = vector_dfdx.template cast() * dxdz; // Also known as dfdz. + return jet_f; + } +}; + +} // namespace ceres + +namespace Eigen { + +// Creating a specialization of NumTraits enables placing Jet objects inside +// Eigen arrays, getting all the goodness of Eigen combined with autodiff. +template +struct NumTraits > { + typedef ceres::Jet Real; + typedef ceres::Jet NonInteger; + typedef ceres::Jet Nested; + + static typename ceres::Jet dummy_precision() { + return ceres::Jet(1e-12); + } + + enum { + IsComplex = 0, + IsInteger = 0, + IsSigned, + ReadCost = 1, + AddCost = 1, + // For Jet types, multiplication is more expensive than addition. + MulCost = 3, + HasFloatingPoint = 1 + }; +}; + +} // namespace Eigen + +#endif // CERES_PUBLIC_JET_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h b/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h new file mode 100644 index 00000000000..c0f7dc77a57 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h @@ -0,0 +1,189 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ +#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// Purpose: Sometimes parameter blocks x can overparameterize a problem +// +// min f(x) +// x +// +// In that case it is desirable to choose a parameterization for the +// block itself to remove the null directions of the cost. More +// generally, if x lies on a manifold of a smaller dimension than the +// ambient space that it is embedded in, then it is numerically and +// computationally more effective to optimize it using a +// parameterization that lives in the tangent space of that manifold +// at each point. +// +// For example, a sphere in three dimensions is a 2 dimensional +// manifold, embedded in a three dimensional space. At each point on +// the sphere, the plane tangent to it defines a two dimensional +// tangent space. For a cost function defined on this sphere, given a +// point x, moving in the direction normal to the sphere at that point +// is not useful. Thus a better way to do a local optimization is to +// optimize over two dimensional vector delta in the tangent space at +// that point and then "move" to the point x + delta, where the move +// operation involves projecting back onto the sphere. Doing so +// removes a redundent dimension from the optimization, making it +// numerically more robust and efficient. +// +// More generally we can define a function +// +// x_plus_delta = Plus(x, delta), +// +// where x_plus_delta has the same size as x, and delta is of size +// less than or equal to x. The function Plus, generalizes the +// definition of vector addition. Thus it satisfies the identify +// +// Plus(x, 0) = x, for all x. +// +// A trivial version of Plus is when delta is of the same size as x +// and +// +// Plus(x, delta) = x + delta +// +// A more interesting case if x is two dimensional vector, and the +// user wishes to hold the first coordinate constant. Then, delta is a +// scalar and Plus is defined as +// +// Plus(x, delta) = x + [0] * delta +// [1] +// +// An example that occurs commonly in Structure from Motion problems +// is when camera rotations are parameterized using Quaternion. There, +// it is useful only make updates orthogonal to that 4-vector defining +// the quaternion. One way to do this is to let delta be a 3 +// dimensional vector and define Plus to be +// +// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x +// +// The multiplication between the two 4-vectors on the RHS is the +// standard quaternion product. +// +// Given g and a point x, optimizing f can now be restated as +// +// min f(Plus(x, delta)) +// delta +// +// Given a solution delta to this problem, the optimal value is then +// given by +// +// x* = Plus(x, delta) +// +// The class LocalParameterization defines the function Plus and its +// Jacobian which is needed to compute the Jacobian of f w.r.t delta. +class LocalParameterization { + public: + virtual ~LocalParameterization() {} + + // Generalization of the addition operation, + // + // x_plus_delta = Plus(x, delta) + // + // with the condition that Plus(x, 0) = x. + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const = 0; + + // The jacobian of Plus(x, delta) w.r.t delta at delta = 0. + virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0; + + // Size of x. + virtual int GlobalSize() const = 0; + + // Size of delta. + virtual int LocalSize() const = 0; +}; + +// Some basic parameterizations + +// Identity Parameterization: Plus(x, delta) = x + delta +class IdentityParameterization : public LocalParameterization { + public: + explicit IdentityParameterization(int size); + virtual ~IdentityParameterization() {} + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const; + virtual bool ComputeJacobian(const double* x, + double* jacobian) const; + virtual int GlobalSize() const { return size_; } + virtual int LocalSize() const { return size_; } + + private: + const int size_; +}; + +// Hold a subset of the parameters inside a parameter block constant. +class SubsetParameterization : public LocalParameterization { + public: + explicit SubsetParameterization(int size, + const vector& constant_parameters); + virtual ~SubsetParameterization() {} + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const; + virtual bool ComputeJacobian(const double* x, + double* jacobian) const; + virtual int GlobalSize() const { return constancy_mask_.size(); } + virtual int LocalSize() const { return local_size_; } + + private: + const int local_size_; + vector constancy_mask_; +}; + +// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x +// with * being the quaternion multiplication operator. Here we assume +// that the first element of the quaternion vector is the real (cos +// theta) part. +class QuaternionParameterization : public LocalParameterization { + public: + virtual ~QuaternionParameterization() {} + virtual bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const; + virtual bool ComputeJacobian(const double* x, + double* jacobian) const; + virtual int GlobalSize() const { return 4; } + virtual int LocalSize() const { return 3; } +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/loss_function.h b/extern/libmv/third_party/ceres/include/ceres/loss_function.h new file mode 100644 index 00000000000..81add02cdee --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/loss_function.h @@ -0,0 +1,322 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// The LossFunction interface is the way users describe how residuals +// are converted to cost terms for the overall problem cost function. +// For the exact manner in which loss functions are converted to the +// overall cost for a problem, see problem.h. +// +// For least squares problem where there are no outliers and standard +// squared loss is expected, it is not necessary to create a loss +// function; instead passing a NULL to the problem when adding +// residuals implies a standard squared loss. +// +// For least squares problems where the minimization may encounter +// input terms that contain outliers, that is, completely bogus +// measurements, it is important to use a loss function that reduces +// their associated penalty. +// +// Consider a structure from motion problem. The unknowns are 3D +// points and camera parameters, and the measurements are image +// coordinates describing the expected reprojected position for a +// point in a camera. For example, we want to model the geometry of a +// street scene with fire hydrants and cars, observed by a moving +// camera with unknown parameters, and the only 3D points we care +// about are the pointy tippy-tops of the fire hydrants. Our magic +// image processing algorithm, which is responsible for producing the +// measurements that are input to Ceres, has found and matched all +// such tippy-tops in all image frames, except that in one of the +// frame it mistook a car's headlight for a hydrant. If we didn't do +// anything special (i.e. if we used a basic quadratic loss), the +// residual for the erroneous measurement will result in extreme error +// due to the quadratic nature of squared loss. This results in the +// entire solution getting pulled away from the optimimum to reduce +// the large error that would otherwise be attributed to the wrong +// measurement. +// +// Using a robust loss function, the cost for large residuals is +// reduced. In the example above, this leads to outlier terms getting +// downweighted so they do not overly influence the final solution. +// +// What cost function is best? +// +// In general, there isn't a principled way to select a robust loss +// function. The authors suggest starting with a non-robust cost, then +// only experimenting with robust loss functions if standard squared +// loss doesn't work. + +#ifndef CERES_PUBLIC_LOSS_FUNCTION_H_ +#define CERES_PUBLIC_LOSS_FUNCTION_H_ + +#include +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +class LossFunction { + public: + virtual ~LossFunction() {} + + // For a residual vector with squared 2-norm 'sq_norm', this method + // is required to fill in the value and derivatives of the loss + // function (rho in this example): + // + // out[0] = rho(sq_norm), + // out[1] = rho'(sq_norm), + // out[2] = rho''(sq_norm), + // + // Here the convention is that the contribution of a term to the + // cost function is given by 1/2 rho(s), where + // + // s = ||residuals||^2. + // + // Calling the method with a negative value of 's' is an error and + // the implementations are not required to handle that case. + // + // Most sane choices of rho() satisfy: + // + // rho(0) = 0, + // rho'(0) = 1, + // rho'(s) < 1 in outlier region, + // rho''(s) < 0 in outlier region, + // + // so that they mimic the least squares cost for small residuals. + virtual void Evaluate(double sq_norm, double out[3]) const = 0; +}; + +// Some common implementations follow below. +// +// Note: in the region of interest (i.e. s < 3) we have: +// TrivialLoss >= HuberLoss >= SoftLOneLoss >= CauchyLoss + + +// This corresponds to no robustification. +// +// rho(s) = s +// +// At s = 0: rho = [0, 1, 0]. +// +// It is not normally necessary to use this, as passing NULL for the +// loss function when building the problem accomplishes the same +// thing. +class TrivialLoss : public LossFunction { + public: + virtual void Evaluate(double, double*) const; +}; + +// Scaling +// ------- +// Given one robustifier +// s -> rho(s) +// one can change the length scale at which robustification takes +// place, by adding a scale factor 'a' as follows: +// +// s -> a^2 rho(s / a^2). +// +// The first and second derivatives are: +// +// s -> rho'(s / a^2), +// s -> (1 / a^2) rho''(s / a^2), +// +// but the behaviour near s = 0 is the same as the original function, +// i.e. +// +// rho(s) = s + higher order terms, +// a^2 rho(s / a^2) = s + higher order terms. +// +// The scalar 'a' should be positive. +// +// The reason for the appearance of squaring is that 'a' is in the +// units of the residual vector norm whereas 's' is a squared +// norm. For applications it is more convenient to specify 'a' than +// its square. The commonly used robustifiers below are described in +// un-scaled format (a = 1) but their implementations work for any +// non-zero value of 'a'. + +// Huber. +// +// rho(s) = s for s <= 1, +// rho(s) = 2 sqrt(s) - 1 for s >= 1. +// +// At s = 0: rho = [0, 1, 0]. +// +// The scaling parameter 'a' corresponds to 'delta' on this page: +// http://en.wikipedia.org/wiki/Huber_Loss_Function +class HuberLoss : public LossFunction { + public: + explicit HuberLoss(double a) : a_(a), b_(a * a) { } + virtual void Evaluate(double, double*) const; + private: + const double a_; + // b = a^2. + const double b_; +}; + +// Soft L1, similar to Huber but smooth. +// +// rho(s) = 2 (sqrt(1 + s) - 1). +// +// At s = 0: rho = [0, 1, -1/2]. +class SoftLOneLoss : public LossFunction { + public: + explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) { } + virtual void Evaluate(double, double*) const; + private: + // b = a^2. + const double b_; + // c = 1 / a^2. + const double c_; +}; + +// Inspired by the Cauchy distribution +// +// rho(s) = log(1 + s). +// +// At s = 0: rho = [0, 1, -1]. +class CauchyLoss : public LossFunction { + public: + explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) { } + virtual void Evaluate(double, double*) const; + private: + // b = a^2. + const double b_; + // c = 1 / a^2. + const double c_; +}; + +// The discussion above has to do with length scaling: it affects the space +// in which s is measured. Sometimes you want to simply scale the output +// value of the robustifier. For example, you might want to weight +// different error terms differently (e.g., weight pixel reprojection +// errors differently from terrain errors). +// +// If rho is the wrapped robustifier, then this simply outputs +// s -> a * rho(s) +// +// The first and second derivatives are, not surprisingly +// s -> a * rho'(s) +// s -> a * rho''(s) +// +// Since we treat the a NULL Loss function as the Identity loss +// function, rho = NULL is a valid input and will result in the input +// being scaled by a. This provides a simple way of implementing a +// scaled ResidualBlock. +class ScaledLoss : public LossFunction { + public: + // Constructs a ScaledLoss wrapping another loss function. Takes + // ownership of the wrapped loss function or not depending on the + // ownership parameter. + ScaledLoss(const LossFunction* rho, double a, Ownership ownership) : + rho_(rho), a_(a), ownership_(ownership) { } + + virtual ~ScaledLoss() { + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + rho_.release(); + } + } + virtual void Evaluate(double, double*) const; + + private: + internal::scoped_ptr rho_; + const double a_; + const Ownership ownership_; + DISALLOW_COPY_AND_ASSIGN(ScaledLoss); +}; + +// Sometimes after the optimization problem has been constructed, we +// wish to mutate the scale of the loss function. For example, when +// performing estimation from data which has substantial outliers, +// convergence can be improved by starting out with a large scale, +// optimizing the problem and then reducing the scale. This can have +// better convergence behaviour than just using a loss function with a +// small scale. +// +// This templated class allows the user to implement a loss function +// whose scale can be mutated after an optimization problem has been +// constructed. +// +// Example usage +// +// Problem problem; +// +// // Add parameter blocks +// +// CostFunction* cost_function = +// new AutoDiffCostFunction < UW_Camera_Mapper, 2, 9, 3>( +// new UW_Camera_Mapper(data->observations[2*i + 0], +// data->observations[2*i + 1])); +// +// LossFunctionWrapper* loss_function(new HuberLoss(1.0), TAKE_OWNERSHIP); +// +// problem.AddResidualBlock(cost_function, loss_function, parameters); +// +// Solver::Options options; +// scoped_ptr summary1(Solve(problem, options)); +// +// loss_function->Reset(new HuberLoss(1.0), TAKE_OWNERSHIP); +// +// scoped_ptr summary2(Solve(problem, options)); +// +class LossFunctionWrapper : public LossFunction { + public: + LossFunctionWrapper(LossFunction* rho, Ownership ownership) + : rho_(rho), ownership_(ownership) { + } + + virtual ~LossFunctionWrapper() { + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + rho_.release(); + } + } + + virtual void Evaluate(double sq_norm, double out[3]) const { + CHECK_NOTNULL(rho_.get()); + rho_->Evaluate(sq_norm, out); + } + + void Reset(LossFunction* rho, Ownership ownership) { + if (ownership_ == DO_NOT_TAKE_OWNERSHIP) { + rho_.release(); + } + rho_.reset(rho); + ownership_ = ownership; + } + + private: + internal::scoped_ptr rho_; + Ownership ownership_; + DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper); +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_LOSS_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/normal_prior.h b/extern/libmv/third_party/ceres/include/ceres/normal_prior.h new file mode 100644 index 00000000000..480a07474a7 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/normal_prior.h @@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Cost term that implements a prior on a parameter block using a +// normal distribution. + +#ifndef CERES_PUBLIC_NORMAL_PRIOR_H_ +#define CERES_PUBLIC_NORMAL_PRIOR_H_ + +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" + +namespace ceres { + +// Implements a cost function of the form +// +// cost(x) = ||A(x - b)||^2 +// +// where, the matrix A and the vector b are fixed and x is the +// variable. In case the user is interested in implementing a cost +// function of the form +// +// cost(x) = (x - mu)^T S^{-1} (x - mu) +// +// where, mu is a vector and S is a covariance matrix, then, A = +// S^{-1/2}, i.e the matrix A is the square root of the inverse of the +// covariance, also known as the stiffness matrix. There are however +// no restrictions on the shape of A. It is free to be rectangular, +// which would be the case if the covariance matrix S is rank +// deficient. + +class NormalPrior: public CostFunction { + public: + // Check that the number of rows in the vector b are the same as the + // number of columns in the matrix A, crash otherwise. + NormalPrior(const Matrix& A, const Vector& b); + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const; + private: + Matrix A_; + Vector b_; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_NORMAL_PRIOR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h new file mode 100644 index 00000000000..bbaefca5b6c --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h @@ -0,0 +1,283 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Create CostFunctions as needed by the least squares framework with jacobians +// computed via numeric (a.k.a. finite) differentiation. For more details see +// http://en.wikipedia.org/wiki/Numerical_differentiation. +// +// To get a numerically differentiated cost function, define a subclass of +// CostFunction such that the Evaluate() function ignores the jacobian +// parameter. The numeric differentiation wrapper will fill in the jacobian +// parameter if nececssary by repeatedly calling the Evaluate() function with +// small changes to the appropriate parameters, and computing the slope. For +// performance, the numeric differentiation wrapper class is templated on the +// concrete cost function, even though it could be implemented only in terms of +// the virtual CostFunction interface. +// +// The numerically differentiated version of a cost function for a cost function +// can be constructed as follows: +// +// CostFunction* cost_function +// = new NumericDiffCostFunction( +// new MyCostFunction(...), TAKE_OWNERSHIP); +// +// where MyCostFunction has 1 residual and 2 parameter blocks with sizes 4 and 8 +// respectively. Look at the tests for a more detailed example. +// +// The central difference method is considerably more accurate at the cost of +// twice as many function evaluations than forward difference. Consider using +// central differences begin with, and only after that works, trying forward +// difference to improve performance. +// +// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives. + +#ifndef CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_ +#define CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_ + +#include +#include +#include "Eigen/Dense" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/sized_cost_function.h" +#include "ceres/types.h" + +namespace ceres { + +enum NumericDiffMethod { + CENTRAL, + FORWARD +}; + +// This is split from the main class because C++ doesn't allow partial template +// specializations for member functions. The alternative is to repeat the main +// class for differing numbers of parameters, which is also unfortunate. +template +struct Differencer { + // Mutates parameters but must restore them before return. + static bool EvaluateJacobianForParameterBlock( + const CostFunctionNoJacobian *function, + double const* residuals_at_eval_point, + double **parameters, + double **jacobians) { + using Eigen::Map; + using Eigen::Matrix; + using Eigen::RowMajor; + + typedef Matrix ResidualVector; + typedef Matrix ParameterVector; + typedef Matrix + JacobianMatrix; + + Map parameter_jacobian(jacobians[parameter_block], + num_residuals, + parameter_block_size); + + // Mutate 1 element at a time and then restore. + Map x_plus_delta(parameters[parameter_block], + parameter_block_size); + ParameterVector x(x_plus_delta); + + // TODO(keir): Pick a smarter number! In theory a good choice is sqrt(eps) * + // x, which for doubles means about 1e-8 * x. However, I have found this + // number too optimistic. This number should be exposed for users to change. + const double kRelativeStepSize = 1e-6; + + ParameterVector step_size = x.array().abs() * kRelativeStepSize; + + // To handle cases where a parameter is exactly zero, instead use the mean + // step_size for the other dimensions. + double fallback_step_size = step_size.sum() / step_size.rows(); + if (fallback_step_size == 0.0) { + // If all the parameters are zero, there's no good answer. Take + // kRelativeStepSize as a guess and hope for the best. + fallback_step_size = kRelativeStepSize; + } + + // For each parameter in the parameter block, use finite differences to + // compute the derivative for that parameter. + for (int j = 0; j < parameter_block_size; ++j) { + if (step_size(j) == 0.0) { + // The parameter is exactly zero, so compromise and use the mean + // step_size from the other parameters. This can break in many cases, + // but it's hard to pick a good number without problem specific + // knowledge. + step_size(j) = fallback_step_size; + } + x_plus_delta(j) = x(j) + step_size(j); + + double residuals[num_residuals]; // NOLINT + if (!function->Evaluate(parameters, residuals, NULL)) { + // Something went wrong; bail. + return false; + } + + // Compute this column of the jacobian in 3 steps: + // 1. Store residuals for the forward part. + // 2. Subtract residuals for the backward (or 0) part. + // 3. Divide out the run. + parameter_jacobian.col(j) = + Map(residuals, num_residuals); + + double one_over_h = 1 / step_size(j); + if (method == CENTRAL) { + // Compute the function on the other side of x(j). + x_plus_delta(j) = x(j) - step_size(j); + + if (!function->Evaluate(parameters, residuals, NULL)) { + // Something went wrong; bail. + return false; + } + parameter_jacobian.col(j) -= + Map(residuals, num_residuals, 1); + one_over_h /= 2; + } else { + // Forward difference only; reuse existing residuals evaluation. + parameter_jacobian.col(j) -= + Map(residuals_at_eval_point, num_residuals); + } + x_plus_delta(j) = x(j); // Restore x_plus_delta. + + // Divide out the run to get slope. + parameter_jacobian.col(j) *= one_over_h; + } + return true; + } +}; + +// Prevent invalid instantiations. +template +struct Differencer { + static bool EvaluateJacobianForParameterBlock( + const CostFunctionNoJacobian *function, + double const* residuals_at_eval_point, + double **parameters, + double **jacobians) { + LOG(FATAL) << "Shouldn't get here."; + return true; + } +}; + +template +class NumericDiffCostFunction + : public SizedCostFunction { + public: + NumericDiffCostFunction(CostFunctionNoJacobian* function, + Ownership ownership) + : function_(function), ownership_(ownership) {} + + virtual ~NumericDiffCostFunction() { + if (ownership_ != TAKE_OWNERSHIP) { + function_.release(); + } + } + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + // Get the function value (residuals) at the the point to evaluate. + bool success = function_->Evaluate(parameters, residuals, NULL); + if (!success) { + // Something went wrong; ignore the jacobian. + return false; + } + if (!jacobians) { + // Nothing to do; just forward. + return true; + } + + // Create a copy of the parameters which will get mutated. + const int kParametersSize = N0 + N1 + N2 + N3 + N4 + N5; + double parameters_copy[kParametersSize]; + double *parameters_references_copy[6]; + parameters_references_copy[0] = ¶meters_copy[0]; + parameters_references_copy[1] = ¶meters_copy[0] + N0; + parameters_references_copy[2] = ¶meters_copy[0] + N0 + N1; + parameters_references_copy[3] = ¶meters_copy[0] + N0 + N1 + N2; + parameters_references_copy[4] = ¶meters_copy[0] + N0 + N1 + N2 + N3; + parameters_references_copy[5] = + ¶meters_copy[0] + N0 + N1 + N2 + N3 + N4; + +#define COPY_PARAMETER_BLOCK(block) \ + if (N ## block) memcpy(parameters_references_copy[block], \ + parameters[block], \ + sizeof(double) * N ## block); // NOLINT + COPY_PARAMETER_BLOCK(0); + COPY_PARAMETER_BLOCK(1); + COPY_PARAMETER_BLOCK(2); + COPY_PARAMETER_BLOCK(3); + COPY_PARAMETER_BLOCK(4); + COPY_PARAMETER_BLOCK(5); +#undef COPY_PARAMETER_BLOCK + +#define EVALUATE_JACOBIAN_FOR_BLOCK(block) \ + if (N ## block && jacobians[block]) { \ + if (!Differencer::EvaluateJacobianForParameterBlock( \ + function_.get(), \ + residuals, \ + parameters_references_copy, \ + jacobians)) { \ + return false; \ + } \ + } + EVALUATE_JACOBIAN_FOR_BLOCK(0); + EVALUATE_JACOBIAN_FOR_BLOCK(1); + EVALUATE_JACOBIAN_FOR_BLOCK(2); + EVALUATE_JACOBIAN_FOR_BLOCK(3); + EVALUATE_JACOBIAN_FOR_BLOCK(4); + EVALUATE_JACOBIAN_FOR_BLOCK(5); +#undef EVALUATE_JACOBIAN_FOR_BLOCK + return true; + } + + private: + internal::scoped_ptr function_; + Ownership ownership_; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h new file mode 100644 index 00000000000..0ca61006bdb --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/problem.h @@ -0,0 +1,265 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) +// +// The Problem object is used to build and hold least squares problems. + +#ifndef CERES_PUBLIC_PROBLEM_H_ +#define CERES_PUBLIC_PROBLEM_H_ + +#include +#include +#include +#include + +#include +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +class CostFunction; +class LossFunction; +class LocalParameterization; + +namespace internal { +class Preprocessor; +class ProblemImpl; +class ParameterBlock; +class ResidualBlock; +class SolverImpl; +} // namespace internal + +// A ResidualBlockId is a handle clients can use to delete residual +// blocks after creating them. They are opaque for any purposes other +// than that. +typedef const internal::ResidualBlock* ResidualBlockId; + +// A class to represent non-linear least squares problems. Such +// problems have a cost function that is a sum of error terms (known +// as "residuals"), where each residual is a function of some subset +// of the parameters. The cost function takes the form +// +// N 1 +// SUM --- loss( || r_i1, r_i2,..., r_ik ||^2 ), +// i=1 2 +// +// where +// +// r_ij is residual number i, component j; the residual is a +// function of some subset of the parameters x1...xk. For +// example, in a structure from motion problem a residual +// might be the difference between a measured point in an +// image and the reprojected position for the matching +// camera, point pair. The residual would have two +// components, error in x and error in y. +// +// loss(y) is the loss function; for example, squared error or +// Huber L1 loss. If loss(y) = y, then the cost function is +// non-robustified least squares. +// +// This class is specifically designed to address the important subset +// of "sparse" least squares problems, where each component of the +// residual depends only on a small number number of parameters, even +// though the total number of residuals and parameters may be very +// large. This property affords tremendous gains in scale, allowing +// efficient solving of large problems that are otherwise +// inaccessible. +// +// The canonical example of a sparse least squares problem is +// "structure-from-motion" (SFM), where the parameters are points and +// cameras, and residuals are reprojection errors. Typically a single +// residual will depend only on 9 parameters (3 for the point, 6 for +// the camera). +// +// To create a least squares problem, use the AddResidualBlock() and +// AddParameterBlock() methods, documented below. Here is an example least +// squares problem containing 3 parameter blocks of sizes 3, 4 and 5 +// respectively and two residual terms of size 2 and 6: +// +// double x1[] = { 1.0, 2.0, 3.0 }; +// double x2[] = { 1.0, 2.0, 3.0, 5.0 }; +// double x3[] = { 1.0, 2.0, 3.0, 6.0, 7.0 }; +// +// Problem problem; +// +// problem.AddResidualBlock(new MyUnaryCostFunction(...), x1); +// problem.AddResidualBlock(new MyBinaryCostFunction(...), x2, x3); +// +// Please see cost_function.h for details of the CostFunction object. +class Problem { + public: + struct Options { + Options() + : cost_function_ownership(TAKE_OWNERSHIP), + loss_function_ownership(TAKE_OWNERSHIP), + local_parameterization_ownership(TAKE_OWNERSHIP) {} + + // These flags control whether the Problem object owns the cost + // functions, loss functions, and parameterizations passed into + // the Problem. If set to TAKE_OWNERSHIP, then the problem object + // will delete the corresponding cost or loss functions on + // destruction. The destructor is careful to delete the pointers + // only once, since sharing cost/loss/parameterizations is + // allowed. + Ownership cost_function_ownership; + Ownership loss_function_ownership; + Ownership local_parameterization_ownership; + }; + + // The default constructor is equivalent to the + // invocation Problem(Problem::Options()). + Problem(); + explicit Problem(const Options& options); + + ~Problem(); + + // Add a residual block to the overall cost function. The cost + // function carries with it information about the sizes of the + // parameter blocks it expects. The function checks that these match + // the sizes of the parameter blocks listed in parameter_blocks. The + // program aborts if a mismatch is detected. loss_function can be + // NULL, in which case the cost of the term is just the squared norm + // of the residuals. + // + // The user has the option of explicitly adding the parameter blocks + // using AddParameterBlock. This causes additional correctness + // checking; however, AddResidualBlock implicitly adds the parameter + // blocks if they are not present, so calling AddParameterBlock + // explicitly is not required. + // + // The Problem object by default takes ownership of the + // cost_function and loss_function pointers. These objects remain + // live for the life of the Problem object. If the user wishes to + // keep control over the destruction of these objects, then they can + // do this by setting the corresponding enums in the Options struct. + // + // Note: Even though the Problem takes ownership of cost_function + // and loss_function, it does not preclude the user from re-using + // them in another residual block. The destructor takes care to call + // delete on each cost_function or loss_function pointer only once, + // regardless of how many residual blocks refer to them. + // + // Example usage: + // + // double x1[] = {1.0, 2.0, 3.0}; + // double x2[] = {1.0, 2.0, 5.0, 6.0}; + // double x3[] = {3.0, 6.0, 2.0, 5.0, 1.0}; + // + // Problem problem; + // + // problem.AddResidualBlock(new MyUnaryCostFunction(...), NULL, x1); + // problem.AddResidualBlock(new MyBinaryCostFunction(...), NULL, x2, x1); + // + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks); + + // Convenience methods for adding residuals with a small number of + // parameters. This is the common case. Instead of specifying the + // parameter block arguments as a vector, list them as pointers. + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4, double* x5); + + // Add a parameter block with appropriate size to the problem. + // Repeated calls with the same arguments are ignored. Repeated + // calls with the same double pointer but a different size results + // in undefined behaviour. + void AddParameterBlock(double* values, int size); + + // Add a parameter block with appropriate size and parameterization + // to the problem. Repeated calls with the same arguments are + // ignored. Repeated calls with the same double pointer but a + // different size results in undefined behaviour. + void AddParameterBlock(double* values, + int size, + LocalParameterization* local_parameterization); + + // Hold the indicated parameter block constant during optimization. + void SetParameterBlockConstant(double* values); + + // Allow the indicated parameter to vary during optimization. + void SetParameterBlockVariable(double* values); + + // Set the local parameterization for one of the parameter blocks. + // The local_parameterization is owned by the Problem by default. It + // is acceptable to set the same parameterization for multiple + // parameters; the destructor is careful to delete local + // parameterizations only once. The local parameterization can only + // be set once per parameter, and cannot be changed once set. + void SetParameterization(double* values, + LocalParameterization* local_parameterization); + + // Number of parameter blocks in the problem. Always equals + // parameter_blocks().size() and parameter_block_sizes().size(). + int NumParameterBlocks() const; + + // The size of the parameter vector obtained by summing over the + // sizes of all the parameter blocks. + int NumParameters() const; + + // Number of residual blocks in the problem. Always equals + // residual_blocks().size(). + int NumResidualBlocks() const; + + // The size of the residual vector obtained by summing over the + // sizes of all of the residual blocks. + int NumResiduals() const; + + private: + friend class internal::SolverImpl; + internal::scoped_ptr problem_impl_; + DISALLOW_COPY_AND_ASSIGN(Problem); +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_PROBLEM_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/rotation.h b/extern/libmv/third_party/ceres/include/ceres/rotation.h new file mode 100644 index 00000000000..e4227e78b9a --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/rotation.h @@ -0,0 +1,526 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) +// +// Templated functions for manipulating rotations. The templated +// functions are useful when implementing functors for automatic +// differentiation. +// +// In the following, the Quaternions are laid out as 4-vectors, thus: +// +// q[0] scalar part. +// q[1] coefficient of i. +// q[2] coefficient of j. +// q[3] coefficient of k. +// +// where: i*i = j*j = k*k = -1 and i*j = k, j*k = i, k*i = j. + +#ifndef CERES_PUBLIC_ROTATION_H_ +#define CERES_PUBLIC_ROTATION_H_ + +#include +#include + +namespace ceres { + +// Convert a value in combined axis-angle representation to a quaternion. +// The value angle_axis is a triple whose norm is an angle in radians, +// and whose direction is aligned with the axis of rotation, +// and quaternion is a 4-tuple that will contain the resulting quaternion. +// The implementation may be used with auto-differentiation up to the first +// derivative, higher derivatives may have unexpected results near the origin. +template +void AngleAxisToQuaternion(T const* angle_axis, T* quaternion); + +// Convert a quaternion to the equivalent combined axis-angle representation. +// The value quaternion must be a unit quaternion - it is not normalized first, +// and angle_axis will be filled with a value whose norm is the angle of +// rotation in radians, and whose direction is the axis of rotation. +// The implemention may be used with auto-differentiation up to the first +// derivative, higher derivatives may have unexpected results near the origin. +template +void QuaternionToAngleAxis(T const* quaternion, T* angle_axis); + +// Conversions between 3x3 rotation matrix (in column major order) and +// axis-angle rotation representations. Templated for use with +// autodifferentiation. +template +void RotationMatrixToAngleAxis(T const * R, T * angle_axis); +template +void AngleAxisToRotationMatrix(T const * angle_axis, T * R); + +// Conversions between 3x3 rotation matrix (in row major order) and +// Euler angle (in degrees) rotation representations. +// +// The {pitch,roll,yaw} Euler angles are rotations around the {x,y,z} +// axes, respectively. They are applied in that same order, so the +// total rotation R is Rz * Ry * Rx. +template +void EulerAnglesToRotationMatrix(const T* euler, int row_stride, T* R); + +// Convert a 4-vector to a 3x3 scaled rotation matrix. +// +// The choice of rotation is such that the quaternion [1 0 0 0] goes to an +// identity matrix and for small a, b, c the quaternion [1 a b c] goes to +// the matrix +// +// [ 0 -c b ] +// I + 2 [ c 0 -a ] + higher order terms +// [ -b a 0 ] +// +// which corresponds to a Rodrigues approximation, the last matrix being +// the cross-product matrix of [a b c]. Together with the property that +// R(q1 * q2) = R(q1) * R(q2) this uniquely defines the mapping from q to R. +// +// The rotation matrix is row-major. +// +// No normalization of the quaternion is performed, i.e. +// R = ||q||^2 * Q, where Q is an orthonormal matrix +// such that det(Q) = 1 and Q*Q' = I +template inline +void QuaternionToScaledRotation(const T q[4], T R[3 * 3]); + +// Same as above except that the rotation matrix is normalized by the +// Frobenius norm, so that R * R' = I (and det(R) = 1). +template inline +void QuaternionToRotation(const T q[4], T R[3 * 3]); + +// Rotates a point pt by a quaternion q: +// +// result = R(q) * pt +// +// Assumes the quaternion is unit norm. This assumption allows us to +// write the transform as (something)*pt + pt, as is clear from the +// formula below. If you pass in a quaternion with |q|^2 = 2 then you +// WILL NOT get back 2 times the result you get for a unit quaternion. +template inline +void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]); + +// With this function you do not need to assume that q has unit norm. +// It does assume that the norm is non-zero. +template inline +void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]); + +// zw = z * w, where * is the Quaternion product between 4 vectors. +template inline +void QuaternionProduct(const T z[4], const T w[4], T zw[4]); + +// xy = x cross y; +template inline +void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]); + +template inline +T DotProduct(const T x[3], const T y[3]); + +// y = R(angle_axis) * x; +template inline +void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]); + +// --- IMPLEMENTATION + +// Duplicate rather than decorate every use of cmath with _USE_MATH_CONSTANTS. +// Necessitated by Windows. +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#define CERES_NEED_M_PI_UNDEF +#endif + +template +inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) { + const T &a0 = angle_axis[0]; + const T &a1 = angle_axis[1]; + const T &a2 = angle_axis[2]; + const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2; + + // For points not at the origin, the full conversion is numerically stable. + if (theta_squared > T(0.0)) { + const T theta = sqrt(theta_squared); + const T half_theta = theta * T(0.5); + const T k = sin(half_theta) / theta; + quaternion[0] = cos(half_theta); + quaternion[1] = a0 * k; + quaternion[2] = a1 * k; + quaternion[3] = a2 * k; + } else { + // At the origin, sqrt() will produce NaN in the derivative since + // the argument is zero. By approximating with a Taylor series, + // and truncating at one term, the value and first derivatives will be + // computed correctly when Jets are used. + const T k(0.5); + quaternion[0] = T(1.0); + quaternion[1] = a0 * k; + quaternion[2] = a1 * k; + quaternion[3] = a2 * k; + } +} + +template +inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) { + const T &q1 = quaternion[1]; + const T &q2 = quaternion[2]; + const T &q3 = quaternion[3]; + const T sin_squared = q1 * q1 + q2 * q2 + q3 * q3; + + // For quaternions representing non-zero rotation, the conversion + // is numerically stable. + if (sin_squared > T(0.0)) { + const T sin_theta = sqrt(sin_squared); + const T k = T(2.0) * atan2(sin_theta, quaternion[0]) / sin_theta; + angle_axis[0] = q1 * k; + angle_axis[1] = q2 * k; + angle_axis[2] = q3 * k; + } else { + // For zero rotation, sqrt() will produce NaN in the derivative since + // the argument is zero. By approximating with a Taylor series, + // and truncating at one term, the value and first derivatives will be + // computed correctly when Jets are used. + const T k(2.0); + angle_axis[0] = q1 * k; + angle_axis[1] = q2 * k; + angle_axis[2] = q3 * k; + } +} + +// The conversion of a rotation matrix to the angle-axis form is +// numerically problematic when then rotation angle is close to zero +// or to Pi. The following implementation detects when these two cases +// occurs and deals with them by taking code paths that are guaranteed +// to not perform division by a small number. +template +inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) { + // x = k * 2 * sin(theta), where k is the axis of rotation. + angle_axis[0] = R[5] - R[7]; + angle_axis[1] = R[6] - R[2]; + angle_axis[2] = R[1] - R[3]; + + static const T kOne = T(1.0); + static const T kTwo = T(2.0); + + // Since the right hand side may give numbers just above 1.0 or + // below -1.0 leading to atan misbehaving, we threshold. + T costheta = std::min(std::max((R[0] + R[4] + R[8] - kOne) / kTwo, + T(-1.0)), + kOne); + + // sqrt is guaranteed to give non-negative results, so we only + // threshold above. + T sintheta = std::min(sqrt(angle_axis[0] * angle_axis[0] + + angle_axis[1] * angle_axis[1] + + angle_axis[2] * angle_axis[2]) / kTwo, + kOne); + + // Use the arctan2 to get the right sign on theta + const T theta = atan2(sintheta, costheta); + + // Case 1: sin(theta) is large enough, so dividing by it is not a + // problem. We do not use abs here, because while jets.h imports + // std::abs into the namespace, here in this file, abs resolves to + // the int version of the function, which returns zero always. + // + // We use a threshold much larger then the machine epsilon, because + // if sin(theta) is small, not only do we risk overflow but even if + // that does not occur, just dividing by a small number will result + // in numerical garbage. So we play it safe. + static const double kThreshold = 1e-12; + if ((sintheta > kThreshold) || (sintheta < -kThreshold)) { + const T r = theta / (kTwo * sintheta); + for (int i = 0; i < 3; ++i) { + angle_axis[i] *= r; + } + return; + } + + // Case 2: theta ~ 0, means sin(theta) ~ theta to a good + // approximation. + if (costheta > 0) { + const T kHalf = T(0.5); + for (int i = 0; i < 3; ++i) { + angle_axis[i] *= kHalf; + } + return; + } + + // Case 3: theta ~ pi, this is the hard case. Since theta is large, + // and sin(theta) is small. Dividing by theta by sin(theta) will + // either give an overflow or worse still numerically meaningless + // results. Thus we use an alternate more complicated formula + // here. + + // Since cos(theta) is negative, division by (1-cos(theta)) cannot + // overflow. + const T inv_one_minus_costheta = kOne / (kOne - costheta); + + // We now compute the absolute value of coordinates of the axis + // vector using the diagonal entries of R. To resolve the sign of + // these entries, we compare the sign of angle_axis[i]*sin(theta) + // with the sign of sin(theta). If they are the same, then + // angle_axis[i] should be positive, otherwise negative. + for (int i = 0; i < 3; ++i) { + angle_axis[i] = theta * sqrt((R[i*4] - costheta) * inv_one_minus_costheta); + if (((sintheta < 0) && (angle_axis[i] > 0)) || + ((sintheta > 0) && (angle_axis[i] < 0))) { + angle_axis[i] = -angle_axis[i]; + } + } +} + +template +inline void AngleAxisToRotationMatrix(const T * angle_axis, T * R) { + static const T kOne = T(1.0); + const T theta2 = DotProduct(angle_axis, angle_axis); + if (theta2 > 0.0) { + // We want to be careful to only evaluate the square root if the + // norm of the angle_axis vector is greater than zero. Otherwise + // we get a division by zero. + const T theta = sqrt(theta2); + const T wx = angle_axis[0] / theta; + const T wy = angle_axis[1] / theta; + const T wz = angle_axis[2] / theta; + + const T costheta = cos(theta); + const T sintheta = sin(theta); + + R[0] = costheta + wx*wx*(kOne - costheta); + R[1] = wz*sintheta + wx*wy*(kOne - costheta); + R[2] = -wy*sintheta + wx*wz*(kOne - costheta); + R[3] = wx*wy*(kOne - costheta) - wz*sintheta; + R[4] = costheta + wy*wy*(kOne - costheta); + R[5] = wx*sintheta + wy*wz*(kOne - costheta); + R[6] = wy*sintheta + wx*wz*(kOne - costheta); + R[7] = -wx*sintheta + wy*wz*(kOne - costheta); + R[8] = costheta + wz*wz*(kOne - costheta); + } else { + // At zero, we switch to using the first order Taylor expansion. + R[0] = kOne; + R[1] = -angle_axis[2]; + R[2] = angle_axis[1]; + R[3] = angle_axis[2]; + R[4] = kOne; + R[5] = -angle_axis[0]; + R[6] = -angle_axis[1]; + R[7] = angle_axis[0]; + R[8] = kOne; + } +} + +template +inline void EulerAnglesToRotationMatrix(const T* euler, + const int row_stride, + T* R) { + const T degrees_to_radians(M_PI / 180.0); + + const T pitch(euler[0] * degrees_to_radians); + const T roll(euler[1] * degrees_to_radians); + const T yaw(euler[2] * degrees_to_radians); + + const T c1 = cos(yaw); + const T s1 = sin(yaw); + const T c2 = cos(roll); + const T s2 = sin(roll); + const T c3 = cos(pitch); + const T s3 = sin(pitch); + + // Rows of the rotation matrix. + T* R1 = R; + T* R2 = R1 + row_stride; + T* R3 = R2 + row_stride; + + R1[0] = c1*c2; + R1[1] = -s1*c3 + c1*s2*s3; + R1[2] = s1*s3 + c1*s2*c3; + + R2[0] = s1*c2; + R2[1] = c1*c3 + s1*s2*s3; + R2[2] = -c1*s3 + s1*s2*c3; + + R3[0] = -s2; + R3[1] = c2*s3; + R3[2] = c2*c3; +} + +template inline +void QuaternionToScaledRotation(const T q[4], T R[3 * 3]) { + // Make convenient names for elements of q. + T a = q[0]; + T b = q[1]; + T c = q[2]; + T d = q[3]; + // This is not to eliminate common sub-expression, but to + // make the lines shorter so that they fit in 80 columns! + T aa = a * a; + T ab = a * b; + T ac = a * c; + T ad = a * d; + T bb = b * b; + T bc = b * c; + T bd = b * d; + T cc = c * c; + T cd = c * d; + T dd = d * d; + + R[0] = aa + bb - cc - dd; R[1] = T(2) * (bc - ad); R[2] = T(2) * (ac + bd); // NOLINT + R[3] = T(2) * (ad + bc); R[4] = aa - bb + cc - dd; R[5] = T(2) * (cd - ab); // NOLINT + R[6] = T(2) * (bd - ac); R[7] = T(2) * (ab + cd); R[8] = aa - bb - cc + dd; // NOLINT +} + +template inline +void QuaternionToRotation(const T q[4], T R[3 * 3]) { + QuaternionToScaledRotation(q, R); + + T normalizer = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]; + CHECK_NE(normalizer, T(0)); + normalizer = T(1) / normalizer; + + for (int i = 0; i < 9; ++i) { + R[i] *= normalizer; + } +} + +template inline +void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) { + const T t2 = q[0] * q[1]; + const T t3 = q[0] * q[2]; + const T t4 = q[0] * q[3]; + const T t5 = -q[1] * q[1]; + const T t6 = q[1] * q[2]; + const T t7 = q[1] * q[3]; + const T t8 = -q[2] * q[2]; + const T t9 = q[2] * q[3]; + const T t1 = -q[3] * q[3]; + result[0] = T(2) * ((t8 + t1) * pt[0] + (t6 - t4) * pt[1] + (t3 + t7) * pt[2]) + pt[0]; // NOLINT + result[1] = T(2) * ((t4 + t6) * pt[0] + (t5 + t1) * pt[1] + (t9 - t2) * pt[2]) + pt[1]; // NOLINT + result[2] = T(2) * ((t7 - t3) * pt[0] + (t2 + t9) * pt[1] + (t5 + t8) * pt[2]) + pt[2]; // NOLINT +} + + +template inline +void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) { + // 'scale' is 1 / norm(q). + const T scale = T(1) / sqrt(q[0] * q[0] + + q[1] * q[1] + + q[2] * q[2] + + q[3] * q[3]); + + // Make unit-norm version of q. + const T unit[4] = { + scale * q[0], + scale * q[1], + scale * q[2], + scale * q[3], + }; + + UnitQuaternionRotatePoint(unit, pt, result); +} + +template inline +void QuaternionProduct(const T z[4], const T w[4], T zw[4]) { + zw[0] = z[0] * w[0] - z[1] * w[1] - z[2] * w[2] - z[3] * w[3]; + zw[1] = z[0] * w[1] + z[1] * w[0] + z[2] * w[3] - z[3] * w[2]; + zw[2] = z[0] * w[2] - z[1] * w[3] + z[2] * w[0] + z[3] * w[1]; + zw[3] = z[0] * w[3] + z[1] * w[2] - z[2] * w[1] + z[3] * w[0]; +} + +// xy = x cross y; +template inline +void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]) { + x_cross_y[0] = x[1] * y[2] - x[2] * y[1]; + x_cross_y[1] = x[2] * y[0] - x[0] * y[2]; + x_cross_y[2] = x[0] * y[1] - x[1] * y[0]; +} + +template inline +T DotProduct(const T x[3], const T y[3]) { + return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]); +} + +template inline +void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) { + T w[3]; + T sintheta; + T costheta; + + const T theta2 = DotProduct(angle_axis, angle_axis); + if (theta2 > 0.0) { + // Away from zero, use the rodriguez formula + // + // result = pt costheta + + // (w x pt) * sintheta + + // w (w . pt) (1 - costheta) + // + // We want to be careful to only evaluate the square root if the + // norm of the angle_axis vector is greater than zero. Otherwise + // we get a division by zero. + // + const T theta = sqrt(theta2); + w[0] = angle_axis[0] / theta; + w[1] = angle_axis[1] / theta; + w[2] = angle_axis[2] / theta; + costheta = cos(theta); + sintheta = sin(theta); + T w_cross_pt[3]; + CrossProduct(w, pt, w_cross_pt); + T w_dot_pt = DotProduct(w, pt); + for (int i = 0; i < 3; ++i) { + result[i] = pt[i] * costheta + + w_cross_pt[i] * sintheta + + w[i] * (T(1.0) - costheta) * w_dot_pt; + } + } else { + // Near zero, the first order Taylor approximation of the rotation + // matrix R corresponding to a vector w and angle w is + // + // R = I + hat(w) * sin(theta) + // + // But sintheta ~ theta and theta * w = angle_axis, which gives us + // + // R = I + hat(w) + // + // and actually performing multiplication with the point pt, gives us + // R * pt = pt + w x pt. + // + // Switching to the Taylor expansion at zero helps avoid all sorts + // of numerical nastiness. + T w_cross_pt[3]; + CrossProduct(angle_axis, pt, w_cross_pt); + for (int i = 0; i < 3; ++i) { + result[i] = pt[i] + w_cross_pt[i]; + } + } +} + +} // namespace ceres + +// Clean define pollution. +#ifdef CERES_NEED_M_PI_UNDEF +#undef CERES_NEED_M_PI_UNDEF +#undef M_PI +#endif + +#endif // CERES_PUBLIC_ROTATION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h new file mode 100644 index 00000000000..2894a9fba5c --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h @@ -0,0 +1,88 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A convenience class for cost functions which are statically sized. +// Compared to the dynamically-sized base class, this reduces boilerplate. +// +// The kNumResiduals template parameter can be a constant such as 2 or 5, or it +// can be ceres::DYNAMIC. If kNumResiduals is ceres::DYNAMIC, then subclasses +// are responsible for calling set_num_residuals() at runtime. + +#ifndef CERES_PUBLIC_SIZED_COST_FUNCTION_H_ +#define CERES_PUBLIC_SIZED_COST_FUNCTION_H_ + +#include +#include "ceres/types.h" +#include "ceres/cost_function.h" + +namespace ceres { + +template +class SizedCostFunction : public CostFunction { + public: + SizedCostFunction() { + // Sanity checking. + CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC) + << "Cost functions must have at least one residual block."; + + CHECK_GT(N0, 0) + << "Cost functions must have at least one parameter block."; + CHECK((!N1 && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && !N2 && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) || + ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0))) + << "Zero block cannot precede a non-zero block. Block sizes are " + << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", " + << N3 << ", " << N4 << ", " << N5; + + set_num_residuals(kNumResiduals); + +#define ADD_PARAMETER_BLOCK(N) \ + if (N) mutable_parameter_block_sizes()->push_back(N); + ADD_PARAMETER_BLOCK(N0); + ADD_PARAMETER_BLOCK(N1); + ADD_PARAMETER_BLOCK(N2); + ADD_PARAMETER_BLOCK(N3); + ADD_PARAMETER_BLOCK(N4); + ADD_PARAMETER_BLOCK(N5); +#undef ADD_PARAMETER_BLOCK + } + + virtual ~SizedCostFunction() { } + + // Subclasses must implement Evaluate(). +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_SIZED_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h new file mode 100644 index 00000000000..bd669272023 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/solver.h @@ -0,0 +1,376 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_SOLVER_H_ +#define CERES_PUBLIC_SOLVER_H_ + +#include +#include +#include + +#include "ceres/iteration_callback.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { + +class Problem; + +// Interface for non-linear least squares solvers. +class Solver { + public: + virtual ~Solver(); + + // The options structure contains, not surprisingly, options that control how + // the solver operates. The defaults should be suitable for a wide range of + // problems; however, better performance is often obtainable with tweaking. + // + // The constants are defined inside types.h + struct Options { + // Default constructor that sets up a generic sparse problem. + Options() { + minimizer_type = LEVENBERG_MARQUARDT; + max_num_iterations = 50; + max_solver_time_sec = 1.0e9; + num_threads = 1; + tau = 1e-4; + min_relative_decrease = 1e-3; + function_tolerance = 1e-6; + gradient_tolerance = 1e-10; + parameter_tolerance = 1e-8; +#ifndef CERES_NO_SUITESPARSE + linear_solver_type = SPARSE_NORMAL_CHOLESKY; +#else + linear_solver_type = DENSE_QR; +#endif // CERES_NO_SUITESPARSE + preconditioner_type = JACOBI; + num_linear_solver_threads = 1; + num_eliminate_blocks = 0; + ordering_type = NATURAL; + linear_solver_min_num_iterations = 1; + linear_solver_max_num_iterations = 500; + eta = 1e-1; + jacobi_scaling = true; + logging_type = PER_MINIMIZER_ITERATION; + minimizer_progress_to_stdout = false; + return_initial_residuals = false; + return_final_residuals = false; + lsqp_dump_directory = "/tmp"; + lsqp_dump_format_type = TEXTFILE; + crash_and_dump_lsqp_on_failure = false; + check_gradients = false; + gradient_check_relative_precision = 1e-8; + numeric_derivative_relative_step_size = 1e-6; + update_state_every_iteration = false; + } + + // Minimizer options ---------------------------------------- + + MinimizerType minimizer_type; + + // Maximum number of iterations for the minimizer to run for. + int max_num_iterations; + + // Maximum time for which the minimizer should run for. + double max_solver_time_sec; + + // Number of threads used by Ceres for evaluating the cost and + // jacobians. + int num_threads; + + // For Levenberg-Marquardt, the initial value for the + // regularizer. This is the inversely related to the size of the + // initial trust region. + double tau; + + // For trust region methods, this is lower threshold for the + // relative decrease before a step is accepted. + double min_relative_decrease; + + // Minimizer terminates when + // + // (new_cost - old_cost) < function_tolerance * old_cost; + // + double function_tolerance; + + // Minimizer terminates when + // + // max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i| + // + // This value should typically be 1e-4 * function_tolerance. + double gradient_tolerance; + + // Minimizer terminates when + // + // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance) + // + double parameter_tolerance; + + // Linear least squares solver options ------------------------------------- + + LinearSolverType linear_solver_type; + + // Type of preconditioner to use with the iterative linear solvers. + PreconditionerType preconditioner_type; + + // Number of threads used by Ceres to solve the Newton + // step. Currently only the SPARSE_SCHUR solver is capable of + // using this setting. + int num_linear_solver_threads; + + // For Schur reduction based methods, the first 0 to num blocks are + // eliminated using the Schur reduction. For example, when solving + // traditional structure from motion problems where the parameters are in + // two classes (cameras and points) then num_eliminate_blocks would be the + // number of points. + // + // This parameter is used in conjunction with the ordering. + // Applies to: Preprocessor and linear least squares solver. + int num_eliminate_blocks; + + // Internally Ceres reorders the parameter blocks to help the + // various linear solvers. This parameter allows the user to + // influence the re-ordering strategy used. For structure from + // motion problems use SCHUR, for other problems NATURAL (default) + // is a good choice. In case you wish to specify your own ordering + // scheme, for example in conjunction with num_eliminate_blocks, + // use USER. + OrderingType ordering_type; + + // The ordering of the parameter blocks. The solver pays attention + // to it if the ordering_type is set to USER and the vector is + // non-empty. + vector ordering; + + + // Minimum number of iterations for which the linear solver should + // run, even if the convergence criterion is satisfied. + int linear_solver_min_num_iterations; + + // Maximum number of iterations for which the linear solver should + // run. If the solver does not converge in less than + // linear_solver_max_num_iterations, then it returns + // MAX_ITERATIONS, as its termination type. + int linear_solver_max_num_iterations; + + // Forcing sequence parameter. The truncated Newton solver uses + // this number to control the relative accuracy with which the + // Newton step is computed. + // + // This constant is passed to ConjugateGradientsSolver which uses + // it to terminate the iterations when + // + // (Q_i - Q_{i-1})/Q_i < eta/i + double eta; + + // Normalize the jacobian using Jacobi scaling before calling + // the linear least squares solver. + bool jacobi_scaling; + + // Logging options --------------------------------------------------------- + + LoggingType logging_type; + + // By default the Minimizer progress is logged to VLOG(1), which + // is sent to STDERR depending on the vlog level. If this flag is + // set to true, and logging_type is not SILENT, the logging output + // is sent to STDOUT. + bool minimizer_progress_to_stdout; + + bool return_initial_residuals; + bool return_final_residuals; + + // List of iterations at which the optimizer should dump the + // linear least squares problem to disk. Useful for testing and + // benchmarking. If empty (default), no problems are dumped. + // + // This is ignored if protocol buffers are disabled. + vector lsqp_iterations_to_dump; + string lsqp_dump_directory; + DumpFormatType lsqp_dump_format_type; + + // Dump the linear least squares problem to disk if the minimizer + // fails due to NUMERICAL_FAILURE and crash the process. This flag + // is useful for generating debugging information. The problem is + // dumped in a file whose name is determined by + // Solver::Options::lsqp_dump_format. + // + // Note: This requires a version of Ceres built with protocol buffers. + bool crash_and_dump_lsqp_on_failure; + + // Finite differences options ---------------------------------------------- + + // Check all jacobians computed by each residual block with finite + // differences. This is expensive since it involves computing the + // derivative by normal means (e.g. user specified, autodiff, + // etc), then also computing it using finite differences. The + // results are compared, and if they differ substantially, details + // are printed to the log. + bool check_gradients; + + // Relative precision to check for in the gradient checker. If the + // relative difference between an element in a jacobian exceeds + // this number, then the jacobian for that cost term is dumped. + double gradient_check_relative_precision; + + // Relative shift used for taking numeric derivatives. For finite + // differencing, each dimension is evaluated at slightly shifted + // values; for the case of central difference, this is what gets + // evaluated: + // + // delta = numeric_derivative_relative_step_size; + // f_initial = f(x) + // f_forward = f((1 + delta) * x) + // f_backward = f((1 - delta) * x) + // + // The finite differencing is done along each dimension. The + // reason to use a relative (rather than absolute) step size is + // that this way, numeric differentation works for functions where + // the arguments are typically large (e.g. 1e9) and when the + // values are small (e.g. 1e-5). It is possible to construct + // "torture cases" which break this finite difference heuristic, + // but they do not come up often in practice. + // + // TODO(keir): Pick a smarter number than the default above! In + // theory a good choice is sqrt(eps) * x, which for doubles means + // about 1e-8 * x. However, I have found this number too + // optimistic. This number should be exposed for users to change. + double numeric_derivative_relative_step_size; + + // If true, the user's parameter blocks are updated at the end of + // every Minimizer iteration, otherwise they are updated when the + // Minimizer terminates. This is useful if, for example, the user + // wishes to visualize the state of the optimization every + // iteration. + bool update_state_every_iteration; + + // Callbacks that are executed at the end of each iteration of the + // Minimizer. They are executed in the order that they are + // specified in this vector. By default, parameter blocks are + // updated only at the end of the optimization, i.e when the + // Minimizer terminates. This behaviour is controlled by + // update_state_every_variable. If the user wishes to have access + // to the update parameter blocks when his/her callbacks are + // executed, then set update_state_every_iteration to true. + // + // The solver does NOT take ownership of these pointers. + vector callbacks; + }; + + struct Summary { + Summary(); + + // A brief one line description of the state of the solver after + // termination. + string BriefReport() const; + + // A full multiline description of the state of the solver after + // termination. + string FullReport() const; + + // Minimizer summary ------------------------------------------------- + SolverTerminationType termination_type; + + // If the solver did not run, or there was a failure, a + // description of the error. + string error; + + // Cost of the problem before and after the optimization. See + // problem.h for definition of the cost of a problem. + double initial_cost; + double final_cost; + + // The part of the total cost that comes from residual blocks that + // were held fixed by the preprocessor because all the parameter + // blocks that they depend on were fixed. + double fixed_cost; + + // Residuals before and after the optimization. Each vector + // contains problem.NumResiduals() elements. Residuals are in the + // same order in which they were added to the problem object when + // constructing this problem. + vector initial_residuals; + vector final_residuals; + + vector iterations; + + int num_successful_steps; + int num_unsuccessful_steps; + + double preprocessor_time_in_seconds; + double minimizer_time_in_seconds; + double total_time_in_seconds; + + // Preprocessor summary. + int num_parameter_blocks; + int num_parameters; + int num_residual_blocks; + int num_residuals; + + int num_parameter_blocks_reduced; + int num_parameters_reduced; + int num_residual_blocks_reduced; + int num_residuals_reduced; + + int num_eliminate_blocks_given; + int num_eliminate_blocks_used; + + int num_threads_given; + int num_threads_used; + + int num_linear_solver_threads_given; + int num_linear_solver_threads_used; + + LinearSolverType linear_solver_type_given; + LinearSolverType linear_solver_type_used; + + PreconditionerType preconditioner_type; + OrderingType ordering_type; + }; + + // Once a least squares problem has been built, this function takes + // the problem and optimizes it based on the values of the options + // parameters. Upon return, a detailed summary of the work performed + // by the preprocessor, the non-linear minmizer and the linear + // solver are reported in the summary object. + virtual void Solve(const Options& options, + Problem* problem, + Solver::Summary* summary); +}; + +// Helper function which avoids going through the interface. +void Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary); + +} // namespace ceres + +#endif // CERES_PUBLIC_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h new file mode 100644 index 00000000000..a30c79029ac --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/types.h @@ -0,0 +1,258 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Enums and other top level class definitions. +// +// Note: internal/types.cc defines stringification routines for some +// of these enums. Please update those routines if you extend or +// remove enums from here. + +#ifndef CERES_PUBLIC_TYPES_H_ +#define CERES_PUBLIC_TYPES_H_ + +namespace ceres { + +// Basic integer types. These typedefs are in the Ceres namespace to avoid +// conflicts with other packages having similar typedefs. +typedef short int16; +typedef int int32; + +// Argument type used in interfaces that can optionally take ownership +// of a passed in argument. If TAKE_OWNERSHIP is passed, the called +// object takes ownership of the pointer argument, and will call +// delete on it upon completion. +enum Ownership { + DO_NOT_TAKE_OWNERSHIP, + TAKE_OWNERSHIP +}; + +// TODO(keir): Considerably expand the explanations of each solver type. +enum LinearSolverType { + // These solvers are for general rectangular systems formed from the + // normal equations A'A x = A'b. They are direct solvers and do not + // assume any special problem structure. + + // Solve the normal equations using a sparse cholesky solver; based + // on CHOLMOD. + SPARSE_NORMAL_CHOLESKY, + + // Solve the normal equations using a dense QR solver; based on + // Eigen. + DENSE_QR, + + // Specialized solvers, specific to problems with a generalized + // bi-partitite structure. + + // Solves the reduced linear system using a dense Cholesky solver; + // based on Eigen. + DENSE_SCHUR, + + // Solves the reduced linear system using a sparse Cholesky solver; + // based on CHOLMOD. + SPARSE_SCHUR, + + // Solves the reduced linear system using Conjugate Gradients, based + // on a new Ceres implementation. Suitable for large scale + // problems. + ITERATIVE_SCHUR, + + // Conjugate gradients on the normal equations. + CGNR +}; + +enum PreconditionerType { + // Trivial preconditioner - the identity matrix. + IDENTITY, + + // Block diagonal of the Gauss-Newton Hessian. + JACOBI, + + // Block diagonal of the Schur complement. This preconditioner may + // only be used with the ITERATIVE_SCHUR solver. Requires + // SuiteSparse/CHOLMOD. + SCHUR_JACOBI, + + // Visibility clustering based preconditioners. + // + // These preconditioners are well suited for Structure from Motion + // problems, particularly problems arising from community photo + // collections. These preconditioners use the visibility structure + // of the scene to determine the sparsity structure of the + // preconditioner. Requires SuiteSparse/CHOLMOD. + CLUSTER_JACOBI, + CLUSTER_TRIDIAGONAL +}; + +enum LinearSolverTerminationType { + // Termination criterion was met. For factorization based solvers + // the tolerance is assumed to be zero. Any user provided values are + // ignored. + TOLERANCE, + + // Solver ran for max_num_iterations and terminated before the + // termination tolerance could be satified. + MAX_ITERATIONS, + + // Solver is stuck and further iterations will not result in any + // measurable progress. + STAGNATION, + + // Solver failed. Solver was terminated due to numerical errors. The + // exact cause of failure depends on the particular solver being + // used. + FAILURE +}; + +enum OrderingType { + // The order in which the parameter blocks were defined. + NATURAL, + + // Use the ordering specificed in the vector ordering. + USER, + + // Automatically figure out the best ordering to use the schur + // complement based solver. + SCHUR +}; + +// Logging options +// The options get progressively noisier. +enum LoggingType { + SILENT, + PER_MINIMIZER_ITERATION +}; + +enum MinimizerType { + LEVENBERG_MARQUARDT +}; + +enum SolverTerminationType { + // The minimizer did not run at all; usually due to errors in the user's + // Problem or the solver options. + DID_NOT_RUN, + + // The solver ran for maximum number of iterations specified by the + // user, but none of the convergence criterion specified by the user + // were met. + NO_CONVERGENCE, + + // Minimizer terminated because + // (new_cost - old_cost) < function_tolerance * old_cost; + FUNCTION_TOLERANCE, + + // Minimizer terminated because + // max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i| + GRADIENT_TOLERANCE, + + // Minimized terminated because + // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance) + PARAMETER_TOLERANCE, + + // The minimizer terminated because it encountered a numerical error + // that it could not recover from. + NUMERICAL_FAILURE, + + // Using an IterationCallback object, user code can control the + // minimizer. The following enums indicate that the user code was + // responsible for termination. + + // User's IterationCallback returned SOLVER_ABORT. + USER_ABORT, + + // User's IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY + USER_SUCCESS +}; + +// Enums used by the IterationCallback instances to indicate to the +// solver whether it should continue solving, the user detected an +// error or the solution is good enough and the solver should +// terminate. +enum CallbackReturnType { + // Continue solving to next iteration. + SOLVER_CONTINUE, + + // Terminate solver, and do not update the parameter blocks upon + // return. Unless the user has set + // Solver:Options:::update_state_every_iteration, in which case the + // state would have been updated every iteration + // anyways. Solver::Summary::termination_type is set to USER_ABORT. + SOLVER_ABORT, + + // Terminate solver, update state and + // return. Solver::Summary::termination_type is set to USER_SUCCESS. + SOLVER_TERMINATE_SUCCESSFULLY +}; + +// The format in which linear least squares problems should be logged +// when Solver::Options::lsqp_iterations_to_dump is non-empty. +enum DumpFormatType { + // Print the linear least squares problem in a human readable format + // to stderr. The Jacobian is printed as a dense matrix. The vectors + // D, x and f are printed as dense vectors. This should only be used + // for small problems. + CONSOLE, + + // Write out the linear least squares problem to the directory + // pointed to by Solver::Options::lsqp_dump_directory as a protocol + // buffer. linear_least_squares_problems.h/cc contains routines for + // loading these problems. For details on the on disk format used, + // see matrix.proto. The files are named lm_iteration_???.lsqp. + PROTOBUF, + + // Write out the linear least squares problem to the directory + // pointed to by Solver::Options::lsqp_dump_directory as text files + // which can be read into MATLAB/Octave. The Jacobian is dumped as a + // text file containing (i,j,s) triplets, the vectors D, x and f are + // dumped as text files containing a list of their values. + // + // A MATLAB/octave script called lm_iteration_???.m is also output, + // which can be used to parse and load the problem into memory. + TEXTFILE +}; + +// For SizedCostFunction and AutoDiffCostFunction, DYNAMIC can be specified for +// the number of residuals. If specified, then the number of residuas for that +// cost function can vary at runtime. +enum DimensionType { + DYNAMIC = -1 +}; + +const char* LinearSolverTypeToString(LinearSolverType type); +const char* PreconditionerTypeToString(PreconditionerType type); +const char* LinearSolverTerminationTypeToString( + LinearSolverTerminationType type); +const char* OrderingTypeToString(OrderingType type); +const char* SolverTerminationTypeToString(SolverTerminationType type); + +bool IsSchurType(LinearSolverType type); + +} // namespace ceres + +#endif // CERES_PUBLIC_TYPES_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc new file mode 100644 index 00000000000..05e63eb560b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc @@ -0,0 +1,73 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/block_evaluate_preparer.h" + +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/casts.h" +#include "ceres/parameter_block.h" +#include "ceres/residual_block.h" +#include "ceres/sparse_matrix.h" + +namespace ceres { +namespace internal { + +void BlockEvaluatePreparer::Init(int** jacobian_layout) { + jacobian_layout_ = jacobian_layout; +} + +// Point the jacobian blocks directly into the block sparse matrix. +void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block, + int residual_block_index, + SparseMatrix* jacobian, + double** jacobians) const { + CHECK(jacobian != NULL); + double* jacobian_values = + down_cast(jacobian)->mutable_values(); + + const int* jacobian_block_offset = jacobian_layout_[residual_block_index]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + if (!residual_block->parameter_blocks()[j]->IsConstant()) { + jacobians[j] = jacobian_values + *jacobian_block_offset; + + // The jacobian_block_offset can't be indexed with 'j' since the code + // that creates the layout strips out any blocks for inactive + // parameters. Instead, bump the pointer for active parameters only. + jacobian_block_offset++; + } else { + jacobians[j] = NULL; + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h new file mode 100644 index 00000000000..a7869311e6e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h @@ -0,0 +1,67 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A evaluate preparer which puts jacobian the evaluated jacobian blocks +// directly into their final resting place in an overall block sparse matrix. +// The evaluator takes care to avoid evaluating the jacobian for fixed +// parameters. + +#ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ +#define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ + +namespace ceres { +namespace internal { + +class ResidualBlock; +class SparseMatrix; + +class BlockEvaluatePreparer { + public: + // Using Init() instead of a constructor allows for allocating this structure + // with new[]. This is because C++ doesn't allow passing arguments to objects + // constructed with new[] (as opposed to plain 'new'). + void Init(int** jacobian_layout); + + // EvaluatePreparer interface + + // Point the jacobian blocks directly into the block sparse matrix. + void Prepare(const ResidualBlock* residual_block, + int residual_block_index, + SparseMatrix* jacobian, + double** jacobians) const; + + private: + int const* const* jacobian_layout_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc new file mode 100644 index 00000000000..1a5001f9c71 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc @@ -0,0 +1,136 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/block_jacobi_preconditioner.h" + +#include "Eigen/Cholesky" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/casts.h" +#include "ceres/integral_types.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +BlockJacobiPreconditioner::BlockJacobiPreconditioner( + const LinearOperator& A) + : block_structure_( + *(down_cast(&A)->block_structure())), + num_rows_(A.num_rows()) { + // Calculate the amount of storage needed. + int storage_needed = 0; + for (int c = 0; c < block_structure_.cols.size(); ++c) { + int size = block_structure_.cols[c].size; + storage_needed += size * size; + } + + // Size the offsets and storage. + blocks_.resize(block_structure_.cols.size()); + block_storage_.resize(storage_needed); + + // Put pointers to the storage in the offsets. + double* block_cursor = &block_storage_[0]; + for (int c = 0; c < block_structure_.cols.size(); ++c) { + int size = block_structure_.cols[c].size; + blocks_[c] = block_cursor; + block_cursor += size * size; + } +} + +BlockJacobiPreconditioner::~BlockJacobiPreconditioner() { +} + +void BlockJacobiPreconditioner::Update(const LinearOperator& matrix, const double* D) { + const BlockSparseMatrix& A = *(down_cast(&matrix)); + const CompressedRowBlockStructure* bs = A.block_structure(); + + // Compute the diagonal blocks by block inner products. + std::fill(block_storage_.begin(), block_storage_.end(), 0.0); + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_size = bs->rows[r].block.size; + const vector& cells = bs->rows[r].cells; + const double* row_values = A.RowBlockValues(r); + for (int c = 0; c < cells.size(); ++c) { + const int col_block_size = bs->cols[cells[c].block_id].size; + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + + MatrixRef(blocks_[cells[c].block_id], + col_block_size, + col_block_size).noalias() += m.transpose() * m; + + // TODO(keir): Figure out when the below expression is actually faster + // than doing the full rank update. The issue is that for smaller sizes, + // the rankUpdate() function is slower than the full product done above. + // + // On the typical bundling problems, the above product is ~5% faster. + // + // MatrixRef(blocks_[cells[c].block_id], + // col_block_size, + // col_block_size).selfadjointView().rankUpdate(m); + // + } + } + + // Add the diagonal and invert each block. + for (int c = 0; c < bs->cols.size(); ++c) { + const int size = block_structure_.cols[c].size; + const int position = block_structure_.cols[c].position; + MatrixRef block(blocks_[c], size, size); + + if (D != NULL) { + block.diagonal() += ConstVectorRef(D + position, size).array().square().matrix(); + } + + block = block.selfadjointView() + .ldlt() + .solve(Matrix::Identity(size, size)); + } +} + +void BlockJacobiPreconditioner::RightMultiply(const double* x, double* y) const { + for (int c = 0; c < block_structure_.cols.size(); ++c) { + const int size = block_structure_.cols[c].size; + const int position = block_structure_.cols[c].position; + ConstMatrixRef D(blocks_[c], size, size); + ConstVectorRef x_block(x + position, size); + VectorRef y_block(y + position, size); + y_block += D * x_block; + } +} + +void BlockJacobiPreconditioner::LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h new file mode 100644 index 00000000000..91cfeddb688 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h @@ -0,0 +1,84 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ +#define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ + +#include +#include "ceres/linear_operator.h" + +namespace ceres { +namespace internal { + +class CompressedRowBlockStructure; +class LinearOperator; +class SparseMatrix; + +// A block Jacobi preconditioner. This is intended for use with conjugate +// gradients, or other iterative symmetric solvers. To use the preconditioner, +// create one by passing a BlockSparseMatrix as the linear operator "A" to the +// constructor. This fixes the sparsity pattern to the pattern of the matrix +// A^TA. +// +// Before each use of the preconditioner in a solve with conjugate gradients, +// update the matrix by running Update(A, D). The values of the matrix A are +// inspected to construct the preconditioner. The vector D is applied as the +// D^TD diagonal term. +class BlockJacobiPreconditioner : public LinearOperator { + public: + // A must remain valid while the BlockJacobiPreconditioner is. + BlockJacobiPreconditioner(const LinearOperator& A); + virtual ~BlockJacobiPreconditioner(); + + // Update the preconditioner with the values found in A. The sparsity pattern + // must match that of the A passed to the constructor. D is a vector that + // must have the same number of rows as A, and is applied as a diagonal in + // addition to the block diagonals of A. + void Update(const LinearOperator& A, const double* D); + + // LinearOperator interface. + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_rows_; } + + private: + std::vector blocks_; + std::vector block_storage_; + int num_rows_; + + // The block structure of the matrix this preconditioner is for (e.g. J). + const CompressedRowBlockStructure& block_structure_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc new file mode 100644 index 00000000000..52a58bb43a6 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc @@ -0,0 +1,209 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/block_jacobian_writer.h" + +#include "ceres/block_evaluate_preparer.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { +namespace { + +// Given the residual block ordering, build a lookup table to determine which +// per-parameter jacobian goes where in the overall program jacobian. +// +// Since we expect to use a Schur type linear solver to solve the LM step, take +// extra care to place the E blocks and the F blocks contiguously. E blocks are +// the first num_eliminate_blocks parameter blocks as indicated by the parameter +// block ordering. The remaining parameter blocks are the F blocks. +// +// TODO(keir): Consider if we should use a boolean for each parameter block +// instead of num_eliminate_blocks. +void BuildJacobianLayout(const Program& program, + int num_eliminate_blocks, + vector* jacobian_layout, + vector* jacobian_layout_storage) { + const vector& residual_blocks = program.residual_blocks(); + + // Iterate over all the active residual blocks and determine how many E blocks + // are there. This will determine where the F blocks start in the jacobian + // matrix. Also compute the number of jacobian blocks. + int f_block_pos = 0; + int num_jacobian_blocks = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + ResidualBlock* residual_block = residual_blocks[i]; + const int num_residuals = residual_block->NumResiduals(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Advance f_block_pos over each E block for this residual. + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + // Only count blocks for active parameters. + num_jacobian_blocks++; + if (parameter_block->index() < num_eliminate_blocks) { + f_block_pos += num_residuals * parameter_block->LocalSize(); + } + } + } + } + + // We now know that the E blocks are laid out starting at zero, and the F + // blocks are laid out starting at f_block_pos. Iterate over the residual + // blocks again, and this time fill the jacobian_layout array with the + // position information. + + jacobian_layout->resize(program.NumResidualBlocks()); + jacobian_layout_storage->resize(num_jacobian_blocks); + + int e_block_pos = 0; + int* jacobian_pos = &(*jacobian_layout_storage)[0]; + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + const int num_residuals = residual_block->NumResiduals(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + + (*jacobian_layout)[i] = jacobian_pos; + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + const int parameter_block_index = parameter_block->index(); + if (parameter_block->IsConstant()) { + continue; + } + const int jacobian_block_size = + num_residuals * parameter_block->LocalSize(); + if (parameter_block_index < num_eliminate_blocks) { + *jacobian_pos = e_block_pos; + e_block_pos += jacobian_block_size; + } else { + *jacobian_pos = f_block_pos; + f_block_pos += jacobian_block_size; + } + jacobian_pos++; + } + } +} + +} // namespace + +BlockJacobianWriter::BlockJacobianWriter(const Evaluator::Options& options, + Program* program) + : program_(program) { + CHECK_GE(options.num_eliminate_blocks, 0) + << "num_eliminate_blocks must be greater than 0."; + + BuildJacobianLayout(*program, + options.num_eliminate_blocks, + &jacobian_layout_, + &jacobian_layout_storage_); +} + +// Create evaluate prepareres that point directly into the final jacobian. This +// makes the final Write() a nop. +BlockEvaluatePreparer* BlockJacobianWriter::CreateEvaluatePreparers( + int num_threads) { + BlockEvaluatePreparer* preparers = new BlockEvaluatePreparer[num_threads]; + for (int i = 0; i < num_threads; i++) { + preparers[i].Init(&jacobian_layout_[0]); + } + return preparers; +} + +SparseMatrix* BlockJacobianWriter::CreateJacobian() const { + CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; + + const vector& parameter_blocks = + program_->parameter_blocks(); + + // Construct the column blocks. + bs->cols.resize(parameter_blocks.size()); + for (int i = 0, cursor = 0; i < parameter_blocks.size(); ++i) { + CHECK_NE(parameter_blocks[i]->index(), -1); + CHECK(!parameter_blocks[i]->IsConstant()); + bs->cols[i].size = parameter_blocks[i]->LocalSize(); + bs->cols[i].position = cursor; + cursor += bs->cols[i].size; + } + + // Construct the cells in each row. + const vector& residual_blocks = + program_->residual_blocks(); + int row_block_position = 0; + bs->rows.resize(residual_blocks.size()); + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + CompressedRow* row = &bs->rows[i]; + + row->block.size = residual_block->NumResiduals(); + row->block.position = row_block_position; + row_block_position += row->block.size; + + // Size the row by the number of active parameters in this residual. + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + int num_active_parameter_blocks = 0; + for (int j = 0; j < num_parameter_blocks; ++j) { + if (residual_block->parameter_blocks()[j]->index() != -1) { + num_active_parameter_blocks++; + } + } + row->cells.resize(num_active_parameter_blocks); + + // Add layout information for the active parameters in this row. + for (int j = 0, k = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + Cell& cell = row->cells[k]; + cell.block_id = parameter_block->index(); + cell.position = jacobian_layout_[i][k]; + + // Only increment k for active parameters, since there is only layout + // information for active parameters. + k++; + } + } + + sort(row->cells.begin(), row->cells.end(), CellLessThan); + } + + BlockSparseMatrix* jacobian = new BlockSparseMatrix(bs); + CHECK_NOTNULL(jacobian); + return jacobian; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h new file mode 100644 index 00000000000..140c7211129 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A jacobian writer that writes to block sparse matrices. The "writer" name is +// misleading, since the Write() operation on the block jacobian writer does not +// write anything. Instead, the Prepare() method on the BlockEvaluatePreparers +// makes a jacobians array which has direct pointers into the block sparse +// jacobian. When the cost function is evaluated, the jacobian blocks get placed +// directly in their final location. + +#ifndef CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ +#define CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ + +#include +#include "ceres/evaluator.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class BlockEvaluatePreparer; +class Program; +class SparseMatrix; + +class BlockJacobianWriter { + public: + BlockJacobianWriter(const Evaluator::Options& options, + Program* program); + + // JacobianWriter interface. + + // Create evaluate prepareres that point directly into the final jacobian. + // This makes the final Write() a nop. + BlockEvaluatePreparer* CreateEvaluatePreparers(int num_threads); + + SparseMatrix* CreateJacobian() const; + + void Write(int /* residual_id */, + int /* residual_offset */, + double** /* jacobians */, + SparseMatrix* /* jacobian */) { + // This is a noop since the blocks were written directly into their final + // position by the outside evaluate call, thanks to the jacobians array + // prepared by the BlockEvaluatePreparers. + } + + private: + Program* program_; + + // Stores the position of each residual / parameter jacobian. + // + // The block sparse matrix that this writer writes to is stored as a set of + // contiguos dense blocks, one after each other; see BlockSparseMatrix. The + // "double* values_" member of the block sparse matrix contains all of these + // blocks. Given a pointer to the first element of a block and the size of + // that block, it's possible to write to it. + // + // In the case of a block sparse jacobian, the jacobian writer needs a way to + // find the offset in the values_ array of each residual/parameter jacobian + // block. + // + // That is the purpose of jacobian_layout_. + // + // In particular, jacobian_layout_[i][j] is the offset in the values_ array of + // the derivative of residual block i with respect to the parameter block at + // active argument position j. + // + // The active qualifier means that non-active parameters do not count. Care + // must be taken when indexing into jacobian_layout_ to account for this. + // Consider a single residual example: + // + // r(x, y, z) + // + // with r in R^3, x in R^4, y in R^2, and z in R^5. + // Take y as a constant (non-active) parameter. + // Take r as residual number 0. + // + // In this case, the active arguments are only (x, z), so the active argument + // position for x is 0, and the active argument position for z is 1. This is + // similar to thinking of r as taking only 2 parameters: + // + // r(x, z) + // + // There are only 2 jacobian blocks: dr/dx and dr/dz. jacobian_layout_ would + // have the following contents: + // + // jacobian_layout_[0] = { 0, 12 } + // + // which indicates that dr/dx is located at values_[0], and dr/dz is at + // values_[12]. See BlockEvaluatePreparer::Prepare()'s comments about 'j'. + vector jacobian_layout_; + + // The pointers in jacobian_layout_ point directly into this vector. + vector jacobian_layout_storage_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc new file mode 100644 index 00000000000..2afaf5e2ea2 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc @@ -0,0 +1,83 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_random_access_dense_matrix.h" + +#include +#include +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +BlockRandomAccessDenseMatrix::BlockRandomAccessDenseMatrix( + const vector& blocks) { + block_layout_.resize(blocks.size(), 0); + num_rows_ = 0; + for (int i = 0; i < blocks.size(); ++i) { + block_layout_[i] = num_rows_; + num_rows_ += blocks[i]; + } + + values_.reset(new double[num_rows_ * num_rows_]); + CHECK_NOTNULL(values_.get()); + cell_info_.values = values_.get(); + SetZero(); +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +BlockRandomAccessDenseMatrix::~BlockRandomAccessDenseMatrix() { +} + +CellInfo* BlockRandomAccessDenseMatrix::GetCell(const int row_block_id, + const int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride) { + *row = block_layout_[row_block_id]; + *col = block_layout_[col_block_id]; + *row_stride = num_rows_; + *col_stride = num_rows_; + return &cell_info_; +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +void BlockRandomAccessDenseMatrix::SetZero() { + if (num_rows_) { + VectorRef(values_.get(), num_rows_ * num_rows_).setZero(); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h new file mode 100644 index 00000000000..3a0096209f7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h @@ -0,0 +1,98 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ + +#include "ceres/block_random_access_matrix.h" + +#include + +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// A square block random accessible matrix with the same row and +// column block structure. All cells are stored in the same single +// array, so that its also accessible as a dense matrix of size +// num_rows x num_cols. +// +// This class is NOT thread safe. Since all n^2 cells are stored, +// GetCell never returns NULL for any (row_block_id, col_block_id) +// pair. +// +// ReturnCell is a nop. +class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix { + public: + // blocks is a vector of block sizes. The resulting matrix has + // blocks.size() * blocks.size() cells. + explicit BlockRandomAccessDenseMatrix(const vector& blocks); + + // The destructor is not thread safe. It assumes that no one is + // modifying any cells when the matrix is being destroyed. + virtual ~BlockRandomAccessDenseMatrix(); + + // BlockRandomAccessMatrix interface. + virtual CellInfo* GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride); + + // This is not a thread safe method, it assumes that no cell is + // locked. + virtual void SetZero(); + + // Since the matrix is square with the same row and column block + // structure, num_rows() = num_cols(). + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_rows_; } + + // The underlying matrix storing the cells. + const double* values() const { return values_.get(); } + double* mutable_values() { return values_.get(); } + + private: + CellInfo cell_info_; + int num_rows_; + vector block_layout_; + scoped_array values_; + + DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc new file mode 100644 index 00000000000..58fe4a10de3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.cc @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_random_access_matrix.h" + +namespace ceres { +namespace internal { + +BlockRandomAccessMatrix::~BlockRandomAccessMatrix() { +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h new file mode 100644 index 00000000000..f398af3be87 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h @@ -0,0 +1,132 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Interface for matrices that allow block based random access. + +#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_ + +#include "ceres/mutex.h" + +namespace ceres { +namespace internal { + +// A matrix implementing the BlockRandomAccessMatrix interface is a +// matrix whose rows and columns are divided into blocks. For example +// the matrix A: +// +// 3 4 5 +// A = 5 [c_11 c_12 c_13] +// 4 [c_21 c_22 c_23] +// +// has row blocks of size 5 and 4, and column blocks of size 3, 4 and +// 5. It has six cells corresponding to the six row-column block +// combinations. +// +// BlockRandomAccessMatrix objects provide access to cells c_ij using +// the GetCell method. when a cell is present, GetCell will return a +// CellInfo object containing a pointer to an array which contains the +// cell as a submatrix and a mutex that guards this submatrix. If the +// user is accessing the matrix concurrently, it is his responsibility +// to use the mutex to exclude other writers from writing to the cell +// concurrently. +// +// There is no requirement that all cells be present, i.e. the matrix +// itself can be block sparse. When a cell is not present, the GetCell +// method will return a NULL pointer. +// +// There is no requirement about how the cells are stored beyond that +// form a dense submatrix of a larger dense matrix. Like everywhere +// else in Ceres, RowMajor storage assumed. +// +// Example usage: +// +// BlockRandomAccessMatrix* A = new BlockRandomAccessMatrixSubClass(...) +// +// int row, col, row_stride, col_stride; +// CellInfo* cell = A->GetCell(row_block_id, col_block_id, +// &row, &col, +// &row_stride, &col_stride); +// +// if (cell != NULL) { +// MatrixRef m(cell->values, row_stride, col_stride); +// MutexLock l(&cell->m); +// m.block(row, col, row_block_size, col_block_size) = ... +// } + +// Structure to carry a pointer to the array containing a cell and the +// Mutex guarding it. +struct CellInfo { + CellInfo() + : values(NULL) { + } + + explicit CellInfo(double* ptr) + : values(ptr) { + } + + double* values; + Mutex m; +}; + +class BlockRandomAccessMatrix { + public: + virtual ~BlockRandomAccessMatrix(); + + // If the cell (row_block_id, col_block_id) is present, then return + // a CellInfo with a pointer to the dense matrix containing it, + // otherwise return NULL. The dense matrix containing this cell has + // size row_stride, col_stride and the cell is located at position + // (row, col) within this matrix. + // + // The size of the cell is row_block_size x col_block_size is + // assumed known to the caller. row_block_size less than or equal to + // row_stride and col_block_size is upper bounded by col_stride. + virtual CellInfo* GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride) = 0; + + // Zero out the values of the array. The structure of the matrix + // (size and sparsity) is preserved. + virtual void SetZero() = 0; + + // Number of scalar rows and columns in the matrix, i.e the sum of + // all row blocks and column block sizes respectively. + virtual int num_rows() const = 0; + virtual int num_cols() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc new file mode 100644 index 00000000000..c496fcd13de --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc @@ -0,0 +1,158 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_random_access_sparse_matrix.h" + +#include +#include +#include +#include +#include +#include "ceres/mutex.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( + const vector& blocks, + const set >& block_pairs) + : kMaxRowBlocks(10 * 1000 * 1000), + blocks_(blocks) { + CHECK_LT(blocks.size(), kMaxRowBlocks); + + // Build the row/column layout vector and count the number of scalar + // rows/columns. + int num_cols = 0; + vector col_layout; + for (int i = 0; i < blocks_.size(); ++i) { + col_layout.push_back(num_cols); + num_cols += blocks_[i]; + } + + // Count the number of scalar non-zero entries and build the layout + // object for looking into the values array of the + // TripletSparseMatrix. + int num_nonzeros = 0; + for (set >::const_iterator it = block_pairs.begin(); + it != block_pairs.end(); + ++it) { + const int row_block_size = blocks_[it->first]; + const int col_block_size = blocks_[it->second]; + num_nonzeros += row_block_size * col_block_size; + } + + VLOG(1) << "Matrix Size [" << num_cols + << "," << num_cols + << "] " << num_nonzeros; + + tsm_.reset(new TripletSparseMatrix(num_cols, num_cols, num_nonzeros)); + tsm_->set_num_nonzeros(num_nonzeros); + int* rows = tsm_->mutable_rows(); + int* cols = tsm_->mutable_cols(); + double* values = tsm_->mutable_values(); + + int pos = 0; + for (set >::const_iterator it = block_pairs.begin(); + it != block_pairs.end(); + ++it) { + const int row_block_size = blocks_[it->first]; + const int col_block_size = blocks_[it->second]; + layout_[IntPairToLong(it->first, it->second)] = + new CellInfo(values + pos); + pos += row_block_size * col_block_size; + } + + // Fill the sparsity pattern of the underlying matrix. + for (set >::const_iterator it = block_pairs.begin(); + it != block_pairs.end(); + ++it) { + const int row_block_id = it->first; + const int col_block_id = it->second; + const int row_block_size = blocks_[row_block_id]; + const int col_block_size = blocks_[col_block_id]; + int pos = + layout_[IntPairToLong(row_block_id, col_block_id)]->values - values; + for (int r = 0; r < row_block_size; ++r) { + for (int c = 0; c < col_block_size; ++c, ++pos) { + rows[pos] = col_layout[row_block_id] + r; + cols[pos] = col_layout[col_block_id] + c; + values[pos] = 1.0; + DCHECK_LT(rows[pos], tsm_->num_rows()); + DCHECK_LT(cols[pos], tsm_->num_rows()); + } + } + } +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +BlockRandomAccessSparseMatrix::~BlockRandomAccessSparseMatrix() { + for (LayoutType::iterator it = layout_.begin(); + it != layout_.end(); + ++it) { + delete it->second; + } +} + +CellInfo* BlockRandomAccessSparseMatrix::GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride) { + const LayoutType::iterator it = + layout_.find(IntPairToLong(row_block_id, col_block_id)); + if (it == layout_.end()) { + return NULL; + } + + // Each cell is stored contiguously as its own little dense matrix. + *row = 0; + *col = 0; + *row_stride = blocks_[row_block_id]; + *col_stride = blocks_[col_block_id]; + return it->second; +} + +// Assume that the user does not hold any locks on any cell blocks +// when they are calling SetZero. +void BlockRandomAccessSparseMatrix::SetZero() { + if (tsm_->num_nonzeros()) { + VectorRef(tsm_->mutable_values(), + tsm_->num_nonzeros()).setZero(); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h new file mode 100644 index 00000000000..12613c3daa0 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h @@ -0,0 +1,109 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ + +#include +#include +#include +#include "ceres/mutex.h" +#include "ceres/block_random_access_matrix.h" +#include "ceres/collections_port.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// A threaf safe square block sparse implementation of +// BlockRandomAccessMatrix. Internally a TripletSparseMatrix is used +// for doing the actual storage. This class augments this matrix with +// an unordered_map that allows random read/write access. +class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { + public: + // blocks is an array of block sizes. block_pairs is a set of + // pairs to identify the non-zero cells + // of this matrix. + BlockRandomAccessSparseMatrix(const vector& blocks, + const set >& block_pairs); + + // The destructor is not thread safe. It assumes that no one is + // modifying any cells when the matrix is being destroyed. + virtual ~BlockRandomAccessSparseMatrix(); + + // BlockRandomAccessMatrix Interface. + virtual CellInfo* GetCell(int row_block_id, + int col_block_id, + int* row, + int* col, + int* row_stride, + int* col_stride); + + // This is not a thread safe method, it assumes that no cell is + // locked. + virtual void SetZero(); + virtual bool IsThreadSafe() const { return true; } + + // Since the matrix is square, num_rows() == num_cols(). + virtual int num_rows() const { return tsm_->num_rows(); } + virtual int num_cols() const { return tsm_->num_cols(); } + + // Access to the underlying matrix object. + const TripletSparseMatrix* matrix() const { return tsm_.get(); } + TripletSparseMatrix* mutable_matrix() { return tsm_.get(); } + + private: + long int IntPairToLong(int a, int b) { + return a * kMaxRowBlocks + b; + } + + const int kMaxRowBlocks; + // row/column block sizes. + const vector blocks_; + + // A mapping from to the position in + // the values array of tsm_ where the block is stored. + typedef HashMap LayoutType; + LayoutType layout_; + + // The underlying matrix object which actually stores the cells. + scoped_ptr tsm_; + + DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc new file mode 100644 index 00000000000..7dd395e2975 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc @@ -0,0 +1,286 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_sparse_matrix.h" + +#include +#include +#include +#include +#include "ceres/block_structure.h" +#include "ceres/matrix_proto.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +BlockSparseMatrix::~BlockSparseMatrix() {} + +BlockSparseMatrix::BlockSparseMatrix( + CompressedRowBlockStructure* block_structure) + : num_rows_(0), + num_cols_(0), + num_nonzeros_(0), + values_(NULL), + block_structure_(block_structure) { + CHECK_NOTNULL(block_structure_.get()); + + // Count the number of columns in the matrix. + for (int i = 0; i < block_structure_->cols.size(); ++i) { + num_cols_ += block_structure_->cols[i].size; + } + + // Count the number of non-zero entries and the number of rows in + // the matrix. + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_size = block_structure_->rows[i].block.size; + num_rows_ += row_block_size; + + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + num_nonzeros_ += col_block_size * row_block_size; + } + } + + CHECK_GE(num_rows_, 0); + CHECK_GE(num_cols_, 0); + CHECK_GE(num_nonzeros_, 0); + VLOG(2) << "Allocating values array with " + << num_nonzeros_ * sizeof(double) << " bytes."; // NOLINT + values_.reset(new double[num_nonzeros_]); + CHECK_NOTNULL(values_.get()); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +BlockSparseMatrix::BlockSparseMatrix(const SparseMatrixProto& outer_proto) { + CHECK(outer_proto.has_block_matrix()); + + const BlockSparseMatrixProto& proto = outer_proto.block_matrix(); + CHECK(proto.has_num_rows()); + CHECK(proto.has_num_cols()); + CHECK_EQ(proto.num_nonzeros(), proto.values_size()); + + num_rows_ = proto.num_rows(); + num_cols_ = proto.num_cols(); + num_nonzeros_ = proto.num_nonzeros(); + + // Copy out the values into *this. + values_.reset(new double[num_nonzeros_]); + for (int i = 0; i < proto.num_nonzeros(); ++i) { + values_[i] = proto.values(i); + } + + // Create the block structure according to the proto. + block_structure_.reset(new CompressedRowBlockStructure); + ProtoToBlockStructure(proto.block_structure(), block_structure_.get()); +} +#endif + +void BlockSparseMatrix::SetZero() { + fill(values_.get(), values_.get() + num_nonzeros_, 0.0); +} + +void BlockSparseMatrix::RightMultiply(const double* x, double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + VectorRef yref(y + row_block_pos, row_block_size); + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + ConstVectorRef xref(x + col_block_pos, col_block_size); + MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + yref += m.lazyProduct(xref); + } + } +} + +void BlockSparseMatrix::LeftMultiply(const double* x, double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + const ConstVectorRef xref(x + row_block_pos, row_block_size); + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + VectorRef yref(y + col_block_pos, col_block_size); + MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + yref += m.transpose().lazyProduct(xref); + } + } +} + +void BlockSparseMatrix::SquaredColumnNorm(double* x) const { + CHECK_NOTNULL(x); + VectorRef(x, num_cols_).setZero(); + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + const MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + VectorRef(x + col_block_pos, col_block_size) += m.colwise().squaredNorm(); + } + } +} + +void BlockSparseMatrix::ScaleColumns(const double* scale) { + CHECK_NOTNULL(scale); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + MatrixRef m(values_.get() + cells[j].position, + row_block_size, col_block_size); + m *= ConstVectorRef(scale + col_block_pos, col_block_size).asDiagonal(); + } + } +} + +void BlockSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + CHECK_NOTNULL(dense_matrix); + + dense_matrix->resize(num_rows_, num_cols_); + dense_matrix->setZero(); + Matrix& m = *dense_matrix; + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + int jac_pos = cells[j].position; + m.block(row_block_pos, col_block_pos, row_block_size, col_block_size) + += MatrixRef(values_.get() + jac_pos, row_block_size, col_block_size); + } + } +} + +void BlockSparseMatrix::ToTripletSparseMatrix( + TripletSparseMatrix* matrix) const { + CHECK_NOTNULL(matrix); + + matrix->Reserve(num_nonzeros_); + matrix->Resize(num_rows_, num_cols_); + matrix->SetZero(); + + for (int i = 0; i < block_structure_->rows.size(); ++i) { + int row_block_pos = block_structure_->rows[i].block.position; + int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + int col_block_id = cells[j].block_id; + int col_block_size = block_structure_->cols[col_block_id].size; + int col_block_pos = block_structure_->cols[col_block_id].position; + int jac_pos = cells[j].position; + for (int r = 0; r < row_block_size; ++r) { + for (int c = 0; c < col_block_size; ++c, ++jac_pos) { + matrix->mutable_rows()[jac_pos] = row_block_pos + r; + matrix->mutable_cols()[jac_pos] = col_block_pos + c; + matrix->mutable_values()[jac_pos] = values_[jac_pos]; + } + } + } + } + matrix->set_num_nonzeros(num_nonzeros_); +} + +// Return a pointer to the block structure. We continue to hold +// ownership of the object though. +const CompressedRowBlockStructure* BlockSparseMatrix::block_structure() + const { + return block_structure_.get(); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { + outer_proto->Clear(); + + BlockSparseMatrixProto* proto = outer_proto->mutable_block_matrix(); + proto->set_num_rows(num_rows_); + proto->set_num_cols(num_cols_); + proto->set_num_nonzeros(num_nonzeros_); + for (int i = 0; i < num_nonzeros_; ++i) { + proto->add_values(values_[i]); + } + BlockStructureToProto(*block_structure_, proto->mutable_block_structure()); +} +#endif + +void BlockSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + for (int i = 0; i < block_structure_->rows.size(); ++i) { + const int row_block_pos = block_structure_->rows[i].block.position; + const int row_block_size = block_structure_->rows[i].block.size; + const vector& cells = block_structure_->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + const int col_block_id = cells[j].block_id; + const int col_block_size = block_structure_->cols[col_block_id].size; + const int col_block_pos = block_structure_->cols[col_block_id].position; + int jac_pos = cells[j].position; + for (int r = 0; r < row_block_size; ++r) { + for (int c = 0; c < col_block_size; ++c) { + fprintf(file, "% 10d % 10d %17f\n", + row_block_pos + r, + col_block_pos + c, + values_[jac_pos++]); + } + } + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h new file mode 100644 index 00000000000..f71446e8f58 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h @@ -0,0 +1,144 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Implementation of the SparseMatrix interface for block sparse +// matrices. + +#ifndef CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ + +#include "ceres/block_structure.h" +#include "ceres/sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; +class TripletSparseMatrix; + +// A further extension of the SparseMatrix interface to support block-oriented +// matrices. The key addition is the RowBlockValues() accessor, which enables +// the lazy block sparse matrix implementation. +class BlockSparseMatrixBase : public SparseMatrix { + public: + BlockSparseMatrixBase() {} + virtual ~BlockSparseMatrixBase() {} + + // Convert this matrix into a triplet sparse matrix. + virtual void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const = 0; + + // Returns a pointer to the block structure. Does not transfer + // ownership. + virtual const CompressedRowBlockStructure* block_structure() const = 0; + + // Returns a pointer to a row of the matrix. The returned array is only valid + // until the next call to RowBlockValues. The caller does not own the result. + // + // The returned array is laid out such that cells on the specified row are + // contiguous in the returned array, though neighbouring cells in row order + // may not be contiguous in the row values. The cell values for cell + // (row_block, cell_block) are found at offset + // + // block_structure()->rows[row_block].cells[cell_block].position + // + virtual const double* RowBlockValues(int row_block_index) const = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase); +}; + +// This class implements the SparseMatrix interface for storing and +// manipulating block sparse matrices. The block structure is stored +// in the CompressedRowBlockStructure object and one is needed to +// initialize the matrix. For details on how the blocks structure of +// the matrix is stored please see the documentation +// +// internal/ceres/block_structure.h +// +class BlockSparseMatrix : public BlockSparseMatrixBase { + public: + // Construct a block sparse matrix with a fully initialized + // CompressedRowBlockStructure objected. The matrix takes over + // ownership of this object and destroys it upon destruction. + // + // TODO(sameeragarwal): Add a function which will validate legal + // CompressedRowBlockStructure objects. + explicit BlockSparseMatrix(CompressedRowBlockStructure* block_structure); + + // Construct a block sparse matrix from a protocol buffer. +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit BlockSparseMatrix(const SparseMatrixProto& proto); +#endif + + BlockSparseMatrix(); + virtual ~BlockSparseMatrix(); + + // Implementation of SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto* proto) const; +#endif + virtual void ToTextFile(FILE* file) const; + + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_cols_; } + virtual int num_nonzeros() const { return num_nonzeros_; } + virtual const double* values() const { return values_.get(); } + virtual double* mutable_values() { return values_.get(); } + + // Implementation of BlockSparseMatrixBase interface. + virtual void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const; + virtual const CompressedRowBlockStructure* block_structure() const; + virtual const double* RowBlockValues(int row_block_index) const { + return values_.get(); + } + + private: + int num_rows_; + int num_cols_; + int max_num_nonzeros_; + int num_nonzeros_; + scoped_array values_; + scoped_ptr block_structure_; + DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc new file mode 100644 index 00000000000..5add4f3b94d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc @@ -0,0 +1,92 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/block_structure.h" +#include "ceres/matrix_proto.h" + +namespace ceres { +namespace internal { + +bool CellLessThan(const Cell& lhs, const Cell& rhs) { + return (lhs.block_id < rhs.block_id); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void ProtoToBlockStructure(const BlockStructureProto &proto, + CompressedRowBlockStructure *block_structure) { + // Decode the column blocks. + block_structure->cols.resize(proto.cols_size()); + for (int i = 0; i < proto.cols_size(); ++i) { + block_structure->cols[i].size = proto.cols(i).size(); + block_structure->cols[i].position = + proto.cols(i).position(); + } + // Decode the row structure. + block_structure->rows.resize(proto.rows_size()); + for (int i = 0; i < proto.rows_size(); ++i) { + const CompressedRowProto &row = proto.rows(i); + block_structure->rows[i].block.size = row.block().size(); + block_structure->rows[i].block.position = row.block().position(); + + // Copy the cells within the row. + block_structure->rows[i].cells.resize(row.cells_size()); + for (int j = 0; j < row.cells_size(); ++j) { + const CellProto &cell = row.cells(j); + block_structure->rows[i].cells[j].block_id = cell.block_id(); + block_structure->rows[i].cells[j].position = cell.position(); + } + } +} + +void BlockStructureToProto(const CompressedRowBlockStructure &block_structure, + BlockStructureProto *proto) { + // Encode the column blocks. + for (int i = 0; i < block_structure.cols.size(); ++i) { + BlockProto *block = proto->add_cols(); + block->set_size(block_structure.cols[i].size); + block->set_position(block_structure.cols[i].position); + } + // Encode the row structure. + for (int i = 0; i < block_structure.rows.size(); ++i) { + CompressedRowProto *row = proto->add_rows(); + BlockProto *block = row->mutable_block(); + block->set_size(block_structure.rows[i].block.size); + block->set_position(block_structure.rows[i].block.position); + for (int j = 0; j < block_structure.rows[i].cells.size(); ++j) { + CellProto *cell = row->add_cells(); + cell->set_block_id(block_structure.rows[i].cells[j].block_id); + cell->set_position(block_structure.rows[i].cells[j].position); + } + } +} +#endif + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_structure.h b/extern/libmv/third_party/ceres/internal/ceres/block_structure.h new file mode 100644 index 00000000000..f509067d216 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/block_structure.h @@ -0,0 +1,105 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Block structure objects are used to carry information about the +// dense block structure of sparse matrices. The BlockSparseMatrix +// object uses the BlockStructure objects to keep track of the matrix +// structure and operate upon it. This allows us to use more cache +// friendly block oriented linear algebra operations on the matrix +// instead of accessing it one scalar entry at a time. + +#ifndef CERES_INTERNAL_BLOCK_STRUCTURE_H_ +#define CERES_INTERNAL_BLOCK_STRUCTURE_H_ + +#include +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockStructureProto; + +typedef int16 BlockSize; + +struct Block { + Block() : size(-1), position(-1) {} + Block(int size_, int position_) : size(size_), position(position_) {} + + BlockSize size; + int position; // Position along the row/column. +}; + +struct Cell { + Cell() : block_id(-1), position(-1) {} + Cell(int block_id_, int position_) + : block_id(block_id_), position(position_) {} + + // Column or row block id as the case maybe. + int block_id; + // Where in the values array of the jacobian is this cell located. + int position; +}; + +// Order cell by their block_id; +bool CellLessThan(const Cell& lhs, const Cell& rhs); + +struct CompressedList { + Block block; + vector cells; +}; + +typedef CompressedList CompressedRow; +typedef CompressedList CompressedColumn; + +struct CompressedRowBlockStructure { + vector cols; + vector rows; +}; + +struct CompressedColumnBlockStructure { + vector rows; + vector cols; +}; + +// Deserialize the given block structure proto to the given block structure. +// Destroys previous contents of block_structure. +void ProtoToBlockStructure(const BlockStructureProto &proto, + CompressedRowBlockStructure *block_structure); + +// Serialize the given block structure to the given proto. Destroys previous +// contents of proto. +void BlockStructureToProto(const CompressedRowBlockStructure &block_structure, + BlockStructureProto *proto); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_BLOCK_STRUCTURE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc new file mode 100644 index 00000000000..53190ada6fc --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc @@ -0,0 +1,238 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: David Gallup (dgallup@google.com) +// Sameer Agarwal (sameeragarwal@google.com) + +#include "ceres/canonical_views_clustering.h" + +#include +#include "ceres/graph.h" +#include "ceres/collections_port.h" +#include "ceres/map_util.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +typedef HashMap IntMap; +typedef HashSet IntSet; + +class CanonicalViewsClustering { + public: + CanonicalViewsClustering() {} + + // Compute the canonical views clustering of the vertices of the + // graph. centers will contain the vertices that are the identified + // as the canonical views/cluster centers, and membership is a map + // from vertices to cluster_ids. The i^th cluster center corresponds + // to the i^th cluster. It is possible depending on the + // configuration of the clustering algorithm that some of the + // vertices may not be assigned to any cluster. In this case they + // are assigned to a cluster with id = kInvalidClusterId. + void ComputeClustering(const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + IntMap* membership); + + private: + void FindValidViews(IntSet* valid_views) const; + double ComputeClusteringQualityDifference(const int candidate, + const vector& centers) const; + void UpdateCanonicalViewAssignments(const int canonical_view); + void ComputeClusterMembership(const vector& centers, + IntMap* membership) const; + + CanonicalViewsClusteringOptions options_; + const Graph* graph_; + // Maps a view to its representative canonical view (its cluster + // center). + IntMap view_to_canonical_view_; + // Maps a view to its similarity to its current cluster center. + HashMap view_to_canonical_view_similarity_; + DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering); +}; + +void ComputeCanonicalViewsClustering( + const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + IntMap* membership) { + time_t start_time = time(NULL); + CanonicalViewsClustering cv; + cv.ComputeClustering(graph, options, centers, membership); + VLOG(2) << "Canonical views clustering time (secs): " + << time(NULL) - start_time; +} + +// Implementation of CanonicalViewsClustering +void CanonicalViewsClustering::ComputeClustering( + const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + IntMap* membership) { + options_ = options; + CHECK_NOTNULL(centers)->clear(); + CHECK_NOTNULL(membership)->clear(); + graph_ = &graph; + + IntSet valid_views; + FindValidViews(&valid_views); + while (valid_views.size() > 0) { + // Find the next best canonical view. + double best_difference = -std::numeric_limits::max(); + int best_view = 0; + + // TODO(sameeragarwal): Make this loop multi-threaded. + for (IntSet::const_iterator view = valid_views.begin(); + view != valid_views.end(); + ++view) { + const double difference = + ComputeClusteringQualityDifference(*view, *centers); + if (difference > best_difference) { + best_difference = difference; + best_view = *view; + } + } + + CHECK_GT(best_difference, -std::numeric_limits::max()); + + // Add canonical view if quality improves, or if minimum is not + // yet met, otherwise break. + if ((best_difference <= 0) && + (centers->size() >= options_.min_views)) { + break; + } + + centers->push_back(best_view); + valid_views.erase(best_view); + UpdateCanonicalViewAssignments(best_view); + } + + ComputeClusterMembership(*centers, membership); +} + +// Return the set of vertices of the graph which have valid vertex +// weights. +void CanonicalViewsClustering::FindValidViews( + IntSet* valid_views) const { + const IntSet& views = graph_->vertices(); + for (IntSet::const_iterator view = views.begin(); + view != views.end(); + ++view) { + if (graph_->VertexWeight(*view) != Graph::InvalidWeight()) { + valid_views->insert(*view); + } + } +} + +// Computes the difference in the quality score if 'candidate' were +// added to the set of canonical views. +double CanonicalViewsClustering::ComputeClusteringQualityDifference( + const int candidate, + const vector& centers) const { + // View score. + double difference = + options_.view_score_weight * graph_->VertexWeight(candidate); + + // Compute how much the quality score changes if the candidate view + // was added to the list of canonical views and its nearest + // neighbors became members of its cluster. + const IntSet& neighbors = graph_->Neighbors(candidate); + for (IntSet::const_iterator neighbor = neighbors.begin(); + neighbor != neighbors.end(); + ++neighbor) { + const double old_similarity = + FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); + const double new_similarity = graph_->EdgeWeight(*neighbor, candidate); + if (new_similarity > old_similarity) { + difference += new_similarity - old_similarity; + } + } + + // Number of views penalty. + difference -= options_.size_penalty_weight; + + // Orthogonality. + for (int i = 0; i < centers.size(); ++i) { + difference -= options_.similarity_penalty_weight * + graph_->EdgeWeight(centers[i], candidate); + } + + return difference; +} + +// Reassign views if they're more similar to the new canonical view. +void CanonicalViewsClustering::UpdateCanonicalViewAssignments( + const int canonical_view) { + const IntSet& neighbors = graph_->Neighbors(canonical_view); + for (IntSet::const_iterator neighbor = neighbors.begin(); + neighbor != neighbors.end(); + ++neighbor) { + const double old_similarity = + FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0); + const double new_similarity = + graph_->EdgeWeight(*neighbor, canonical_view); + if (new_similarity > old_similarity) { + view_to_canonical_view_[*neighbor] = canonical_view; + view_to_canonical_view_similarity_[*neighbor] = new_similarity; + } + } +} + +// Assign a cluster id to each view. +void CanonicalViewsClustering::ComputeClusterMembership( + const vector& centers, + IntMap* membership) const { + CHECK_NOTNULL(membership)->clear(); + + // The i^th cluster has cluster id i. + IntMap center_to_cluster_id; + for (int i = 0; i < centers.size(); ++i) { + center_to_cluster_id[centers[i]] = i; + } + + static const int kInvalidClusterId = -1; + + const IntSet& views = graph_->vertices(); + for (IntSet::const_iterator view = views.begin(); + view != views.end(); + ++view) { + IntMap::const_iterator it = + view_to_canonical_view_.find(*view); + int cluster_id = kInvalidClusterId; + if (it != view_to_canonical_view_.end()) { + cluster_id = FindOrDie(center_to_cluster_id, it->second); + } + + InsertOrDie(membership, *view, cluster_id); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h new file mode 100644 index 00000000000..2d1eb403995 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h @@ -0,0 +1,133 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// An implementation of the Canonical Views clustering algorithm from +// "Scene Summarization for Online Image Collections", Ian Simon, Noah +// Snavely, Steven M. Seitz, ICCV 2007. +// +// More details can be found at +// http://grail.cs.washington.edu/projects/canonview/ +// +// Ceres uses this algorithm to perform view clustering for +// constructing visibility based preconditioners. + +#ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ +#define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ + +#include + +#include +#include "ceres/collections_port.h" +#include "ceres/graph.h" +#include "ceres/map_util.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class CanonicalViewsClusteringOptions; + +// Compute a partitioning of the vertices of the graph using the +// canonical views clustering algorithm. +// +// In the following we will use the terms vertices and views +// interchangably. Given a weighted Graph G(V,E), the canonical views +// of G are the the set of vertices that best "summarize" the content +// of the graph. If w_ij i s the weight connecting the vertex i to +// vertex j, and C is the set of canonical views. Then the objective +// of the canonical views algorithm is +// +// E[C] = sum_[i in V] max_[j in C] w_ij +// - size_penalty_weight * |C| +// - similarity_penalty_weight * sum_[i in C, j in C, j > i] w_ij +// +// alpha is the size penalty that penalizes large number of canonical +// views. +// +// beta is the similarity penalty that penalizes canonical views that +// are too similar to other canonical views. +// +// Thus the canonical views algorithm tries to find a canonical view +// for each vertex in the graph which best explains it, while trying +// to minimize the number of canonical views and the overlap between +// them. +// +// We further augment the above objective function by allowing for per +// vertex weights, higher weights indicating a higher preference for +// being chosen as a canonical view. Thus if w_i is the vertex weight +// for vertex i, the objective function is then +// +// E[C] = sum_[i in V] max_[j in C] w_ij +// - size_penalty_weight * |C| +// - similarity_penalty_weight * sum_[i in C, j in C, j > i] w_ij +// + view_score_weight * sum_[i in C] w_i +// +// centers will contain the vertices that are the identified +// as the canonical views/cluster centers, and membership is a map +// from vertices to cluster_ids. The i^th cluster center corresponds +// to the i^th cluster. +// +// It is possible depending on the configuration of the clustering +// algorithm that some of the vertices may not be assigned to any +// cluster. In this case they are assigned to a cluster with id = -1; +void ComputeCanonicalViewsClustering( + const Graph& graph, + const CanonicalViewsClusteringOptions& options, + vector* centers, + HashMap* membership); + +struct CanonicalViewsClusteringOptions { + CanonicalViewsClusteringOptions() + : min_views(3), + size_penalty_weight(5.75), + similarity_penalty_weight(100.0), + view_score_weight(0.0) { + } + // The minimum number of canonical views to compute. + int min_views; + + // Penalty weight for the number of canonical views. A higher + // number will result in fewer canonical views. + double size_penalty_weight; + + // Penalty weight for the diversity (orthogonality) of the + // canonical views. A higher number will encourage less similar + // canonical views. + double similarity_penalty_weight; + + // Weight for per-view scores. Lower weight places less + // confidence in the view scores. + double view_score_weight; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/casts.h b/extern/libmv/third_party/ceres/internal/ceres/casts.h new file mode 100644 index 00000000000..99cf2186cc7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/casts.h @@ -0,0 +1,108 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_CASTS_H_ +#define CERES_INTERNAL_CASTS_H_ + +#include +#include // For NULL. + +namespace ceres { + +// Identity metafunction. +template +struct identity_ { + typedef T type; +}; + +// Use implicit_cast as a safe version of static_cast or const_cast +// for implicit conversions. For example: +// - Upcasting in a type hierarchy. +// - Performing arithmetic conversions (int32 to int64, int to double, etc.). +// - Adding const or volatile qualifiers. +// +// In general, implicit_cast can be used to convert this code +// To to = from; +// DoSomething(to); +// to this +// DoSomething(implicit_cast(from)); +// +// base::identity_ is used to make a non-deduced context, which +// forces all callers to explicitly specify the template argument. +template +inline To implicit_cast(typename identity_::type to) { + return to; +} + +// This version of implicit_cast is used when two template arguments +// are specified. It's obsolete and should not be used. +template +inline To implicit_cast(typename identity_::type const &f) { + return f; +} + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. + +template // use like this: down_cast(foo); +inline To down_cast(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + + // TODO(csilvers): This should use COMPILE_ASSERT. + if (false) { + implicit_cast(NULL); + } + + // uses RTTI in dbg and fastbuild. asserts are disabled in opt builds. + assert(f == NULL || dynamic_cast(f) != NULL); // NOLINT + return static_cast(f); +} + +} // namespace ceres + +#endif // CERES_INTERNAL_CASTS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h new file mode 100644 index 00000000000..f32d8d95c19 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_linear_operator.h @@ -0,0 +1,120 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ +#define CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ + +#include +#include "ceres/linear_operator.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +class SparseMatrix; + +// A linear operator which takes a matrix A and a diagonal vector D and +// performs products of the form +// +// (A^T A + D^T D)x +// +// This is used to implement iterative general sparse linear solving with +// conjugate gradients, where A is the Jacobian and D is a regularizing +// parameter. A brief proof that D^T D is the correct regularizer: +// +// Given a regularized least squares problem: +// +// min ||Ax - b||^2 + ||Dx||^2 +// x +// +// First expand into matrix notation: +// +// (Ax - b)^T (Ax - b) + xD^TDx +// +// Then multiply out to get: +// +// = xA^TAx - 2b^T Ax + b^Tb + xD^TDx +// +// Take the derivative: +// +// 0 = 2A^TAx - 2A^T b + 2 D^TDx +// 0 = A^TAx - A^T b + D^TDx +// 0 = (A^TA + D^TD)x - A^T b +// +// Thus, the symmetric system we need to solve for CGNR is +// +// Sx = z +// +// with S = A^TA + D^TD +// and z = A^T b +// +// Note: This class is not thread safe, since it uses some temporary storage. +class CgnrLinearOperator : public LinearOperator { + public: + CgnrLinearOperator(const LinearOperator& A, const double *D) + : A_(A), D_(D), z_(new double[A.num_rows()]) { + } + virtual ~CgnrLinearOperator() {} + + virtual void RightMultiply(const double* x, double* y) const { + std::fill(z_.get(), z_.get() + A_.num_rows(), 0.0); + + // z = Ax + A_.RightMultiply(x, z_.get()); + + // y = y + Atz + A_.LeftMultiply(z_.get(), y); + + // y = y + DtDx + if (D_ != NULL) { + int n = A_.num_cols(); + VectorRef(y, n).array() += ConstVectorRef(D_, n).array().square() * + ConstVectorRef(x, n).array(); + } + } + + virtual void LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); + } + + virtual int num_rows() const { return A_.num_cols(); } + virtual int num_cols() const { return A_.num_cols(); } + + private: + const LinearOperator& A_; + const double* D_; + scoped_array z_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc new file mode 100644 index 00000000000..ccc8026f9f7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc @@ -0,0 +1,80 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/cgnr_solver.h" + +#include "glog/logging.h" +#include "ceres/linear_solver.h" +#include "ceres/cgnr_linear_operator.h" +#include "ceres/conjugate_gradients_solver.h" +#include "ceres/block_jacobi_preconditioner.h" + +namespace ceres { +namespace internal { + +CgnrSolver::CgnrSolver(const LinearSolver::Options& options) + : options_(options), + jacobi_preconditioner_(NULL) { +} + +LinearSolver::Summary CgnrSolver::Solve( + LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + // Form z = Atb. + scoped_array z(new double[A->num_cols()]); + std::fill(z.get(), z.get() + A->num_cols(), 0.0); + A->LeftMultiply(b, z.get()); + + // Precondition if necessary. + LinearSolver::PerSolveOptions cg_per_solve_options = per_solve_options; + if (options_.preconditioner_type == JACOBI) { + if (jacobi_preconditioner_.get() == NULL) { + jacobi_preconditioner_.reset(new BlockJacobiPreconditioner(*A)); + } + jacobi_preconditioner_->Update(*A, per_solve_options.D); + cg_per_solve_options.preconditioner = jacobi_preconditioner_.get(); + } else if (options_.preconditioner_type != IDENTITY) { + LOG(FATAL) << "CGNR only supports IDENTITY and JACOBI preconditioners."; + } + + // Solve (AtA + DtD)x = z (= Atb). + std::fill(x, x + A->num_cols(), 0.0); + CgnrLinearOperator lhs(*A, per_solve_options.D); + ConjugateGradientsSolver conjugate_gradient_solver(options_); + return conjugate_gradient_solver.Solve(&lhs, + z.get(), + cg_per_solve_options, + x); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h new file mode 100644 index 00000000000..dd36f99006b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h @@ -0,0 +1,66 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_CGNR_SOLVER_H_ +#define CERES_INTERNAL_CGNR_SOLVER_H_ + +#include "ceres/internal/scoped_ptr.h" +#include "ceres/linear_solver.h" + +namespace ceres { +namespace internal { + +class BlockJacobiPreconditioner; + +// A conjugate gradients on the normal equations solver. This directly solves +// for the solution to +// +// (A^T A + D^T D)x = A^T b +// +// as required for solving for x in the least squares sense. Currently only +// block diagonal preconditioning is supported. +class CgnrSolver : public LinearSolver { + public: + explicit CgnrSolver(const LinearSolver::Options& options); + virtual Summary Solve(LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + private: + const LinearSolver::Options options_; + scoped_ptr jacobi_preconditioner_; + DISALLOW_COPY_AND_ASSIGN(CgnrSolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CGNR_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h new file mode 100644 index 00000000000..e125f3fffcd --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h @@ -0,0 +1,141 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Portable HashMap and HashSet, and a specialized overload for hashing pairs. + +#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_ +#define CERES_INTERNAL_COLLECTIONS_PORT_H_ + +#if defined(_MSC_VER) && _MSC_VER <= 1600 +#include +#include +#else +#include +#include +#endif +#include +#include "ceres/integral_types.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +template +struct HashMap : tr1::unordered_map {}; + +template +struct HashSet : tr1::unordered_set {}; + +#ifdef _WIN32 +#define GG_LONGLONG(x) x##I64 +#define GG_ULONGLONG(x) x##UI64 +#else +#define GG_LONGLONG(x) x##LL +#define GG_ULONGLONG(x) x##ULL +#endif + +// The hash function is due to Bob Jenkins (see +// http://burtleburtle.net/bob/hash/index.html). Each mix takes 36 instructions, +// in 18 cycles if you're lucky. On x86 architectures, this requires 45 +// instructions in 27 cycles, if you're lucky. +// +// 32bit version +inline void hash_mix(uint32& a, uint32& b, uint32& c) { + a -= b; a -= c; a ^= (c>>13); + b -= c; b -= a; b ^= (a<<8); + c -= a; c -= b; c ^= (b>>13); + a -= b; a -= c; a ^= (c>>12); + b -= c; b -= a; b ^= (a<<16); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>3); + b -= c; b -= a; b ^= (a<<10); + c -= a; c -= b; c ^= (b>>15); +} + +// 64bit version +inline void hash_mix(uint64& a, uint64& b, uint64& c) { + a -= b; a -= c; a ^= (c>>43); + b -= c; b -= a; b ^= (a<<9); + c -= a; c -= b; c ^= (b>>8); + a -= b; a -= c; a ^= (c>>38); + b -= c; b -= a; b ^= (a<<23); + c -= a; c -= b; c ^= (b>>5); + a -= b; a -= c; a ^= (c>>35); + b -= c; b -= a; b ^= (a<<49); + c -= a; c -= b; c ^= (b>>11); +} + +inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) { + // The golden ratio; an arbitrary value. + uint32 b = 0x9e3779b9UL; + hash_mix(num, b, c); + return c; +} + +inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) { + // More of the golden ratio. + uint64 b = GG_ULONGLONG(0xe08c1d668b756f82); + hash_mix(num, b, c); + return c; +} + +} // namespace internal +} // namespace ceres + +// Since on some platforms this is a doubly-nested namespace (std::tr1) and +// others it is not, the entire namespace line must be in a macro. +CERES_HASH_NAMESPACE_START + +// The outrageously annoying specializations below are for portability reasons. +// In short, it's not possible to have two overloads of hash + +// Hasher for STL pairs. Requires hashers for both members to be defined. +template +struct hash > { + size_t operator()(const pair& p) const { + size_t h1 = hash()(p.first); + size_t h2 = hash()(p.second); + // The decision below is at compile time + return (sizeof(h1) <= sizeof(ceres::internal::uint32)) ? + ceres::internal::Hash32NumWithSeed(h1, h2) : + ceres::internal::Hash64NumWithSeed(h1, h2); + } + // Less than operator for MSVC. + bool operator()(const pair& a, + const pair& b) const { + return a < b; + } + static const size_t bucket_size = 4; // These are required by MSVC + static const size_t min_buckets = 8; // 4 and 8 are defaults. +}; + +CERES_HASH_NAMESPACE_END + +#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc new file mode 100644 index 00000000000..aa883b7d353 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc @@ -0,0 +1,201 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/compressed_row_jacobian_writer.h" + +#include "ceres/casts.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/scratch_evaluate_preparer.h" + +namespace ceres { +namespace internal { + +SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { + const vector& residual_blocks = + program_->residual_blocks(); + + int total_num_residuals = program_->NumResiduals(); + int total_num_effective_parameters = program_->NumEffectiveParameters(); + + // Count the number of jacobian nonzeros. + int num_jacobian_nonzeros = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + ResidualBlock* residual_block = residual_blocks[i]; + const int num_residuals = residual_block->NumResiduals(); + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + num_jacobian_nonzeros += num_residuals * parameter_block->LocalSize(); + } + } + } + + // Allocate storage for the jacobian with some extra space at the end. + // Allocate more space than needed to store the jacobian so that when the LM + // algorithm adds the diagonal, no reallocation is necessary. This reduces + // peak memory usage significantly. + CompressedRowSparseMatrix* jacobian = + new CompressedRowSparseMatrix( + total_num_residuals, + total_num_effective_parameters, + num_jacobian_nonzeros + total_num_effective_parameters); + + // At this stage, the CompressedSparseMatrix is an invalid state. But this + // seems to be the only way to construct it without doing a memory copy. + int* rows = jacobian->mutable_rows(); + int* cols = jacobian->mutable_cols(); + int row_pos = 0; + rows[0] = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Count the number of derivatives for a row of this residual block and + // build a list of active parameter block indices. + int num_derivatives = 0; + vector parameter_indices; + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + parameter_indices.push_back(parameter_block->index()); + num_derivatives += parameter_block->LocalSize(); + } + } + + // Sort the parameters by their position in the state vector. + sort(parameter_indices.begin(), parameter_indices.end()); + CHECK(unique(parameter_indices.begin(), parameter_indices.end()) == + parameter_indices.end()) + << "Ceres internal error: " + << "Duplicate parameter blocks detected in a cost function. " + << "This should never happen. Please report this to " + << "the Ceres developers."; + + // Update the row indices. + const int num_residuals = residual_block->NumResiduals(); + for (int j = 0; j < num_residuals; ++j) { + rows[row_pos + j + 1] = rows[row_pos + j] + num_derivatives; + } + + // Iterate over parameter blocks in the order which they occur in the + // parameter vector. This code mirrors that in Write(), where jacobian + // values are updated. + int col_pos = 0; + for (int j = 0; j < parameter_indices.size(); ++j) { + ParameterBlock* parameter_block = + program_->parameter_blocks()[parameter_indices[j]]; + const int parameter_block_size = parameter_block->LocalSize(); + + for (int r = 0; r < num_residuals; ++r) { + // This is the position in the values array of the jacobian where this + // row of the jacobian block should go. + const int column_block_begin = rows[row_pos + r] + col_pos; + + for (int c = 0; c < parameter_block_size; ++c) { + cols[column_block_begin + c] = parameter_block->delta_offset() + c; + } + } + col_pos += parameter_block_size; + } + row_pos += num_residuals; + } + + CHECK_EQ(num_jacobian_nonzeros, rows[total_num_residuals]); + return jacobian; +} + +void CompressedRowJacobianWriter::Write(int residual_id, + int residual_offset, + double **jacobians, + SparseMatrix* base_jacobian) { + CompressedRowSparseMatrix* jacobian = + down_cast(base_jacobian); + + double* jacobian_values = jacobian->mutable_values(); + const int* jacobian_rows = jacobian->rows(); + + const ResidualBlock* residual_block = + program_->residual_blocks()[residual_id]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + const int num_residuals = residual_block->NumResiduals(); + + // It is necessary to determine the order of the jacobian blocks before + // copying them into the CompressedRowSparseMatrix. Just because a cost + // function uses parameter blocks 1 after 2 in its arguments does not mean + // that the block 1 occurs before block 2 in the column layout of the + // jacobian. Thus, determine the order by sorting the jacobian blocks by their + // position in the state vector. + vector > evaluated_jacobian_blocks; + for (int j = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (!parameter_block->IsConstant()) { + evaluated_jacobian_blocks.push_back( + make_pair(parameter_block->index(), j)); + } + } + sort(evaluated_jacobian_blocks.begin(), evaluated_jacobian_blocks.end()); + + // Where in the current row does the jacobian for a parameter block begin. + int col_pos = 0; + + // Iterate over the jacobian blocks in increasing order of their + // positions in the reduced parameter vector. + for (int i = 0; i < evaluated_jacobian_blocks.size(); ++i) { + const ParameterBlock* parameter_block = + program_->parameter_blocks()[evaluated_jacobian_blocks[i].first]; + const int argument = evaluated_jacobian_blocks[i].second; + const int parameter_block_size = parameter_block->LocalSize(); + + // Copy one row of the jacobian block at a time. + for (int r = 0; r < num_residuals; ++r) { + // Position of the r^th row of the current jacobian block. + const double* block_row_begin = + jacobians[argument] + r * parameter_block_size; + + // Position in the values array of the jacobian where this + // row of the jacobian block should go. + double* column_block_begin = + jacobian_values + jacobian_rows[residual_offset + r] + col_pos; + + copy(block_row_begin, + block_row_begin + parameter_block_size, + column_block_begin); + } + col_pos += parameter_block_size; + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h new file mode 100644 index 00000000000..c103165eaf1 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.h @@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A jacobian writer that directly writes to compressed row sparse matrices. + +#ifndef CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ +#define CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ + +#include "ceres/evaluator.h" +#include "ceres/scratch_evaluate_preparer.h" + +namespace ceres { +namespace internal { + +class Program; +class SparseMatrix; + +class CompressedRowJacobianWriter { + public: + CompressedRowJacobianWriter(Evaluator::Options /* ignored */, + Program* program) + : program_(program) { + } + + // JacobianWriter interface. + + // Since the compressed row matrix has different layout than that assumed by + // the cost functions, use scratch space to store the jacobians temporarily + // then copy them over to the larger jacobian in the Write() function. + ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) { + return ScratchEvaluatePreparer::Create(*program_, num_threads); + } + + SparseMatrix* CreateJacobian() const; + + void Write(int residual_id, + int residual_offset, + double **jacobians, + SparseMatrix* base_jacobian); + + private: + Program* program_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc new file mode 100644 index 00000000000..95edf5396af --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc @@ -0,0 +1,334 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/compressed_row_sparse_matrix.h" + +#include +#include +#include "ceres/matrix_proto.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { +namespace { + +// Helper functor used by the constructor for reordering the contents +// of a TripletSparseMatrix. +struct RowColLessThan { + RowColLessThan(const int* rows, const int* cols) + : rows(rows), cols(cols) { + } + + bool operator()(const int x, const int y) const { + if (rows[x] == rows[y]) { + return (cols[x] < cols[y]); + } + return (rows[x] < rows[y]); + } + + const int* rows; + const int* cols; +}; + +} // namespace + +// This constructor gives you a semi-initialized CompressedRowSparseMatrix. +CompressedRowSparseMatrix::CompressedRowSparseMatrix(int num_rows, + int num_cols, + int max_num_nonzeros) { + num_rows_ = num_rows; + num_cols_ = num_cols; + max_num_nonzeros_ = max_num_nonzeros; + + VLOG(1) << "# of rows: " << num_rows_ << " # of columns: " << num_cols_ + << " max_num_nonzeros: " << max_num_nonzeros_ + << ". Allocating " << (num_rows_ + 1) * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(double); // NOLINT + + rows_.reset(new int[num_rows_ + 1]); + cols_.reset(new int[max_num_nonzeros_]); + values_.reset(new double[max_num_nonzeros_]); + + fill(rows_.get(), rows_.get() + num_rows_ + 1, 0); + fill(cols_.get(), cols_.get() + max_num_nonzeros_, 0); + fill(values_.get(), values_.get() + max_num_nonzeros_, 0); +} + +CompressedRowSparseMatrix::CompressedRowSparseMatrix( + const TripletSparseMatrix& m) { + num_rows_ = m.num_rows(); + num_cols_ = m.num_cols(); + max_num_nonzeros_ = m.max_num_nonzeros(); + + // index is the list of indices into the TripletSparseMatrix m. + vector index(m.num_nonzeros(), 0); + for (int i = 0; i < m.num_nonzeros(); ++i) { + index[i] = i; + } + + // Sort index such that the entries of m are ordered by row and ties + // are broken by column. + sort(index.begin(), index.end(), RowColLessThan(m.rows(), m.cols())); + + VLOG(1) << "# of rows: " << num_rows_ << " # of columns: " << num_cols_ + << " max_num_nonzeros: " << max_num_nonzeros_ + << ". Allocating " << (num_rows_ + 1) * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(int) + // NOLINT + max_num_nonzeros_ * sizeof(double); // NOLINT + + rows_.reset(new int[num_rows_ + 1]); + cols_.reset(new int[max_num_nonzeros_]); + values_.reset(new double[max_num_nonzeros_]); + + // rows_ = 0 + fill(rows_.get(), rows_.get() + num_rows_ + 1, 0); + + // Copy the contents of the cols and values array in the order given + // by index and count the number of entries in each row. + for (int i = 0; i < m.num_nonzeros(); ++i) { + const int idx = index[i]; + ++rows_[m.rows()[idx] + 1]; + cols_[i] = m.cols()[idx]; + values_[i] = m.values()[idx]; + } + + // Find the cumulative sum of the row counts. + for (int i = 1; i < num_rows_ + 1; ++i) { + rows_[i] += rows_[i-1]; + } + + CHECK_EQ(num_nonzeros(), m.num_nonzeros()); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +CompressedRowSparseMatrix::CompressedRowSparseMatrix( + const SparseMatrixProto& outer_proto) { + CHECK(outer_proto.has_compressed_row_matrix()); + + const CompressedRowSparseMatrixProto& proto = + outer_proto.compressed_row_matrix(); + + num_rows_ = proto.num_rows(); + num_cols_ = proto.num_cols(); + + rows_.reset(new int[proto.rows_size()]); + cols_.reset(new int[proto.cols_size()]); + values_.reset(new double[proto.values_size()]); + + for (int i = 0; i < proto.rows_size(); ++i) { + rows_[i] = proto.rows(i); + } + + CHECK_EQ(proto.rows_size(), num_rows_ + 1); + CHECK_EQ(proto.cols_size(), proto.values_size()); + CHECK_EQ(proto.cols_size(), rows_[num_rows_]); + + for (int i = 0; i < proto.cols_size(); ++i) { + cols_[i] = proto.cols(i); + values_[i] = proto.values(i); + } + + max_num_nonzeros_ = proto.cols_size(); +} +#endif + +CompressedRowSparseMatrix::CompressedRowSparseMatrix(const double* diagonal, + int num_rows) { + CHECK_NOTNULL(diagonal); + + num_rows_ = num_rows; + num_cols_ = num_rows; + max_num_nonzeros_ = num_rows; + + rows_.reset(new int[num_rows_ + 1]); + cols_.reset(new int[num_rows_]); + values_.reset(new double[num_rows_]); + + rows_[0] = 0; + for (int i = 0; i < num_rows_; ++i) { + cols_[i] = i; + values_[i] = diagonal[i]; + rows_[i + 1] = i + 1; + } + + CHECK_EQ(num_nonzeros(), num_rows); +} + +CompressedRowSparseMatrix::~CompressedRowSparseMatrix() { +} + +void CompressedRowSparseMatrix::SetZero() { + fill(values_.get(), values_.get() + num_nonzeros(), 0.0); +} + +void CompressedRowSparseMatrix::RightMultiply(const double* x, + double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + y[r] += values_[idx] * x[cols_[idx]]; + } + } +} + +void CompressedRowSparseMatrix::LeftMultiply(const double* x, double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + y[cols_[idx]] += values_[idx] * x[r]; + } + } +} + +void CompressedRowSparseMatrix::SquaredColumnNorm(double* x) const { + CHECK_NOTNULL(x); + + fill(x, x + num_cols_, 0.0); + for (int idx = 0; idx < rows_[num_rows_]; ++idx) { + x[cols_[idx]] += values_[idx] * values_[idx]; + } +} + +void CompressedRowSparseMatrix::ScaleColumns(const double* scale) { + CHECK_NOTNULL(scale); + + for (int idx = 0; idx < rows_[num_rows_]; ++idx) { + values_[idx] *= scale[cols_[idx]]; + } +} + +void CompressedRowSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + CHECK_NOTNULL(dense_matrix); + dense_matrix->resize(num_rows_, num_cols_); + dense_matrix->setZero(); + + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + (*dense_matrix)(r, cols_[idx]) = values_[idx]; + } + } +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void CompressedRowSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { + CHECK_NOTNULL(outer_proto); + + outer_proto->Clear(); + CompressedRowSparseMatrixProto* proto + = outer_proto->mutable_compressed_row_matrix(); + + proto->set_num_rows(num_rows_); + proto->set_num_cols(num_cols_); + + for (int r = 0; r < num_rows_ + 1; ++r) { + proto->add_rows(rows_[r]); + } + + for (int idx = 0; idx < rows_[num_rows_]; ++idx) { + proto->add_cols(cols_[idx]); + proto->add_values(values_[idx]); + } +} +#endif + +void CompressedRowSparseMatrix::DeleteRows(int delta_rows) { + CHECK_GE(delta_rows, 0); + CHECK_LE(delta_rows, num_rows_); + + int new_num_rows = num_rows_ - delta_rows; + + num_rows_ = new_num_rows; + int* new_rows = new int[num_rows_ + 1]; + copy(rows_.get(), rows_.get() + num_rows_ + 1, new_rows); + rows_.reset(new_rows); +} + +void CompressedRowSparseMatrix::AppendRows(const CompressedRowSparseMatrix& m) { + CHECK_EQ(m.num_cols(), num_cols_); + + // Check if there is enough space. If not, then allocate new arrays + // to hold the combined matrix and copy the contents of this matrix + // into it. + if (max_num_nonzeros_ < num_nonzeros() + m.num_nonzeros()) { + int new_max_num_nonzeros = num_nonzeros() + m.num_nonzeros(); + + VLOG(1) << "Reallocating " << sizeof(int) * new_max_num_nonzeros; // NOLINT + + int* new_cols = new int[new_max_num_nonzeros]; + copy(cols_.get(), cols_.get() + max_num_nonzeros_, new_cols); + cols_.reset(new_cols); + + double* new_values = new double[new_max_num_nonzeros]; + copy(values_.get(), values_.get() + max_num_nonzeros_, new_values); + values_.reset(new_values); + + max_num_nonzeros_ = new_max_num_nonzeros; + } + + // Copy the contents of m into this matrix. + copy(m.cols(), m.cols() + m.num_nonzeros(), cols_.get() + num_nonzeros()); + copy(m.values(), + m.values() + m.num_nonzeros(), + values_.get() + num_nonzeros()); + + // Create the new rows array to hold the enlarged matrix. + int* new_rows = new int[num_rows_ + m.num_rows() + 1]; + // The first num_rows_ entries are the same + copy(rows_.get(), rows_.get() + num_rows_, new_rows); + + // new_rows = [rows_, m.row() + rows_[num_rows_]] + fill(new_rows + num_rows_, + new_rows + num_rows_ + m.num_rows() + 1, + rows_[num_rows_]); + + for (int r = 0; r < m.num_rows() + 1; ++r) { + new_rows[num_rows_ + r] += m.rows()[r]; + } + + rows_.reset(new_rows); + num_rows_ += m.num_rows(); +} + +void CompressedRowSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + for (int r = 0; r < num_rows_; ++r) { + for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) { + fprintf(file, "% 10d % 10d %17f\n", r, cols_[idx], values_[idx]); + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h new file mode 100644 index 00000000000..9a39d28e111 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ + +#include +#include "ceres/sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/macros.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; + +class CompressedRowSparseMatrix : public SparseMatrix { + public: + // Build a matrix with the same content as the TripletSparseMatrix + // m. TripletSparseMatrix objects are easier to construct + // incrementally, so we use them to initialize SparseMatrix + // objects. + // + // We assume that m does not have any repeated entries. + explicit CompressedRowSparseMatrix(const TripletSparseMatrix& m); +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit CompressedRowSparseMatrix(const SparseMatrixProto& proto); +#endif + + // Use this constructor only if you know what you are doing. This + // creates a "blank" matrix with the appropriate amount of memory + // allocated. However, the object itself is in an inconsistent state + // as the rows and cols matrices do not match the values of + // num_rows, num_cols and max_num_nonzeros. + // + // The use case for this constructor is that when the user knows the + // size of the matrix to begin with and wants to update the layout + // manually, instead of going via the indirect route of first + // constructing a TripletSparseMatrix, which leads to more than + // double the peak memory usage. + CompressedRowSparseMatrix(int num_rows, + int num_cols, + int max_num_nonzeros); + + // Build a square sparse diagonal matrix with num_rows rows and + // columns. The diagonal m(i,i) = diagonal(i); + CompressedRowSparseMatrix(const double* diagonal, int num_rows); + + virtual ~CompressedRowSparseMatrix(); + + // SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto* proto) const; +#endif + virtual void ToTextFile(FILE* file) const; + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_cols_; } + virtual int num_nonzeros() const { return rows_[num_rows_]; } + virtual const double* values() const { return values_.get(); } + virtual double* mutable_values() { return values_.get(); } + + // Delete the bottom delta_rows. + // num_rows -= delta_rows + void DeleteRows(int delta_rows); + + // Append the contents of m to the bottom of this matrix. m must + // have the same number of columns as this matrix. + void AppendRows(const CompressedRowSparseMatrix& m); + + // Low level access methods that expose the structure of the matrix. + const int* cols() const { return cols_.get(); } + int* mutable_cols() { return cols_.get(); } + + const int* rows() const { return rows_.get(); } + int* mutable_rows() { return rows_.get(); } + + private: + scoped_array cols_; + scoped_array rows_; + scoped_array values_; + + int num_rows_; + int num_cols_; + + int max_num_nonzeros_; + + DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc new file mode 100644 index 00000000000..ca80bfb9c9d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc @@ -0,0 +1,130 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: wjr@google.com (William Rucklidge) +// +// This file contains the implementation of the conditioned cost function. + +#include "ceres/conditioned_cost_function.h" + +#include + +#include +#include "ceres/stl_util.h" +#include "ceres/internal/eigen.h" +#include "ceres/types.h" + +namespace ceres { + +// This cost function has the same dimensions (parameters, residuals) as +// the one it's wrapping. +ConditionedCostFunction::ConditionedCostFunction( + CostFunction* wrapped_cost_function, + const vector& conditioners, + Ownership ownership) + : wrapped_cost_function_(wrapped_cost_function), + conditioners_(conditioners), + ownership_(ownership) { + // Set up our dimensions. + set_num_residuals(wrapped_cost_function_->num_residuals()); + *mutable_parameter_block_sizes() = + wrapped_cost_function_->parameter_block_sizes(); + + // Sanity-check the conditioners' dimensions. + CHECK_EQ(wrapped_cost_function_->num_residuals(), conditioners_.size()); + for (int i = 0; i < wrapped_cost_function_->num_residuals(); i++) { + if (conditioners[i]) { + CHECK_EQ(1, conditioners[i]->num_residuals()); + CHECK_EQ(1, conditioners[i]->parameter_block_sizes().size()); + CHECK_EQ(1, conditioners[i]->parameter_block_sizes()[0]); + } + } +} + +ConditionedCostFunction::~ConditionedCostFunction() { + if (ownership_ == TAKE_OWNERSHIP) { + STLDeleteElements(&conditioners_); + } else { + wrapped_cost_function_.release(); + } +} + +bool ConditionedCostFunction::Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + bool success = wrapped_cost_function_->Evaluate(parameters, residuals, + jacobians); + if (!success) { + return false; + } + + for (int r = 0; r < wrapped_cost_function_->num_residuals(); r++) { + // On output, we want to have + // residuals[r] = conditioners[r](wrapped_residuals[r]) + // For parameter block i, column c, + // jacobians[i][r*parameter_block_size_[i] + c] = + // = d residual[r] / d parameters[i][c] + // = conditioners[r]'(wrapped_residuals[r]) * + // d wrapped_residuals[r] / d parameters[i][c] + if (conditioners_[r]) { + double conditioner_derivative; + double* conditioner_derivative_pointer = &conditioner_derivative; + double** conditioner_derivative_pointer2 = + &conditioner_derivative_pointer; + if (!jacobians) { + conditioner_derivative_pointer2 = NULL; + } + + double unconditioned_residual = residuals[r]; + double* parameter_pointer = &unconditioned_residual; + success = conditioners_[r]->Evaluate(¶meter_pointer, + &residuals[r], + conditioner_derivative_pointer2); + if (!success) { + return false; + } + + if (jacobians) { + for (int i = 0; + i < wrapped_cost_function_->parameter_block_sizes().size(); + i++) { + if (jacobians[i]) { + int parameter_block_size = + wrapped_cost_function_->parameter_block_sizes()[i]; + VectorRef jacobian_row(jacobians[i] + r * parameter_block_size, + parameter_block_size, 1); + jacobian_row *= conditioner_derivative; + } + } + } + } + } + return true; +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc new file mode 100644 index 00000000000..75f9e043fa5 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc @@ -0,0 +1,233 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// A preconditioned conjugate gradients solver +// (ConjugateGradientsSolver) for positive semidefinite linear +// systems. +// +// We have also augmented the termination criterion used by this +// solver to support not just residual based termination but also +// termination based on decrease in the value of the quadratic model +// that CG optimizes. + +#include "ceres/conjugate_gradients_solver.h" + +#include +#include +#include +#include "ceres/linear_operator.h" +#include "ceres/internal/eigen.h" +#include "ceres/types.h" +#include "ceres/jet.h" + +namespace ceres { +namespace internal { +namespace { + +bool IsZeroOrInfinity(double x) { + return ((x == 0.0) || (isinf(x))); +} + +// Constant used in the MATLAB implementation ~ 2 * eps. +const double kEpsilon = 2.2204e-16; + +} // namespace + +ConjugateGradientsSolver::ConjugateGradientsSolver( + const LinearSolver::Options& options) + : options_(options) { +} + +LinearSolver::Summary ConjugateGradientsSolver::Solve( + LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(x); + CHECK_NOTNULL(b); + CHECK_EQ(A->num_rows(), A->num_cols()); + + LinearSolver::Summary summary; + summary.termination_type = MAX_ITERATIONS; + summary.num_iterations = 0; + + int num_cols = A->num_cols(); + VectorRef xref(x, num_cols); + ConstVectorRef bref(b, num_cols); + + double norm_b = bref.norm(); + if (norm_b == 0.0) { + xref.setZero(); + summary.termination_type = TOLERANCE; + return summary; + } + + Vector r(num_cols); + Vector p(num_cols); + Vector z(num_cols); + Vector tmp(num_cols); + + double tol_r = per_solve_options.r_tolerance * norm_b; + + tmp.setZero(); + A->RightMultiply(x, tmp.data()); + r = bref - tmp; + double norm_r = r.norm(); + + if (norm_r <= tol_r) { + summary.termination_type = TOLERANCE; + return summary; + } + + double rho = 1.0; + + // Initial value of the quadratic model Q = x'Ax - 2 * b'x. + double Q0 = -1.0 * xref.dot(bref + r); + + for (summary.num_iterations = 1; + summary.num_iterations < options_.max_num_iterations; + ++summary.num_iterations) { + VLOG(2) << "cg iteration " << summary.num_iterations; + + // Apply preconditioner + if (per_solve_options.preconditioner != NULL) { + z.setZero(); + per_solve_options.preconditioner->RightMultiply(r.data(), z.data()); + } else { + z = r; + } + + double last_rho = rho; + rho = r.dot(z); + + if (IsZeroOrInfinity(rho)) { + LOG(ERROR) << "Numerical failure. rho = " << rho; + summary.termination_type = FAILURE; + break; + }; + + if (summary.num_iterations == 1) { + p = z; + } else { + double beta = rho / last_rho; + if (IsZeroOrInfinity(beta)) { + LOG(ERROR) << "Numerical failure. beta = " << beta; + summary.termination_type = FAILURE; + break; + } + p = z + beta * p; + } + + Vector& q = z; + q.setZero(); + A->RightMultiply(p.data(), q.data()); + double pq = p.dot(q); + + if ((pq <= 0) || isinf(pq)) { + LOG(ERROR) << "Numerical failure. pq = " << pq; + summary.termination_type = FAILURE; + break; + } + + double alpha = rho / pq; + if (isinf(alpha)) { + LOG(ERROR) << "Numerical failure. alpha " << alpha; + summary.termination_type = FAILURE; + break; + } + + xref = xref + alpha * p; + + // Ideally we would just use the update r = r - alpha*q to keep + // track of the residual vector. However this estimate tends to + // drift over time due to round off errors. Thus every + // residual_reset_period iterations, we calculate the residual as + // r = b - Ax. We do not do this every iteration because this + // requires an additional matrix vector multiply which would + // double the complexity of the CG algorithm. + if (summary.num_iterations % options_.residual_reset_period == 0) { + tmp.setZero(); + A->RightMultiply(x, tmp.data()); + r = bref - tmp; + } else { + r = r - alpha * q; + } + + // Quadratic model based termination. + // Q1 = x'Ax - 2 * b' x. + double Q1 = -1.0 * xref.dot(bref + r); + + // For PSD matrices A, let + // + // Q(x) = x'Ax - 2b'x + // + // be the cost of the quadratic function defined by A and b. Then, + // the solver terminates at iteration i if + // + // i * (Q(x_i) - Q(x_i-1)) / Q(x_i) < q_tolerance. + // + // This termination criterion is more useful when using CG to + // solve the Newton step. This particular convergence test comes + // from Stephen Nash's work on truncated Newton + // methods. References: + // + // 1. Stephen G. Nash & Ariela Sofer, Assessing A Search + // Direction Within A Truncated Newton Method, Operation + // Research Letters 9(1990) 219-221. + // + // 2. Stephen G. Nash, A Survey of Truncated Newton Methods, + // Journal of Computational and Applied Mathematics, + // 124(1-2), 45-59, 2000. + // + double zeta = summary.num_iterations * (Q1 - Q0) / Q1; + VLOG(2) << "Q termination: zeta " << zeta + << " " << per_solve_options.q_tolerance; + if (zeta < per_solve_options.q_tolerance) { + summary.termination_type = TOLERANCE; + break; + } + Q0 = Q1; + + // Residual based termination. + norm_r = r. norm(); + VLOG(2) << "R termination: norm_r " << norm_r + << " " << tol_r; + if (norm_r <= tol_r) { + summary.termination_type = TOLERANCE; + break; + } + } + + return summary; +}; + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h new file mode 100644 index 00000000000..57f99e31db7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h @@ -0,0 +1,74 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Preconditioned Conjugate Gradients based solver for positive +// semidefinite linear systems. + +#ifndef CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ +#define CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class LinearOperator; + +// This class implements the now classical Conjugate Gradients +// algorithm of Hestenes & Stiefel for solving postive semidefinite +// linear sytems. Optionally it can use a preconditioner also to +// reduce the condition number of the linear system and improve the +// convergence rate. Modern references for Conjugate Gradients are the +// books by Yousef Saad and Trefethen & Bau. This implementation of CG +// has been augmented with additional termination tests that are +// needed for forcing early termination when used as part of an +// inexact Newton solver. +// +// For more details see the documentation for +// LinearSolver::PerSolveOptions::r_tolerance and +// LinearSolver::PerSolveOptions::q_tolerance in linear_solver.h. +class ConjugateGradientsSolver : public LinearSolver { + public: + explicit ConjugateGradientsSolver(const LinearSolver::Options& options); + virtual Summary Solve(LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + private: + const LinearSolver::Options options_; + DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc new file mode 100644 index 00000000000..4ca2c6f6c86 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc @@ -0,0 +1,125 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/corrector.h" + +#include +#include +#include +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +Corrector::Corrector(double sq_norm, const double rho[3]) { + CHECK_GE(sq_norm, 0.0); + CHECK_GT(rho[1], 0.0); + sqrt_rho1_ = sqrt(rho[1]); + + // If sq_norm = 0.0, the correction becomes trivial, the residual + // and the jacobian are scaled by the squareroot of the derivative + // of rho. Handling this case explicitly avoids the divide by zero + // error that would occur below. + // + // The case where rho'' < 0 also gets special handling. Technically + // it shouldn't, and the computation of the scaling should proceed + // as below, however we found in experiments that applying the + // curvature correction when rho'' < 0, which is the case when we + // are in the outlier region slows down the convergence of the + // algorithm significantly. + // + // Thus, we have divided the action of the robustifier into two + // parts. In the inliner region, we do the full second order + // correction which re-wights the gradient of the function by the + // square root of the derivative of rho, and the Gauss-Newton + // Hessian gets both the scaling and the rank-1 curvature + // correction. Normaly, alpha is upper bounded by one, but with this + // change, alpha is bounded above by zero. + // + // Empirically we have observed that the full Triggs correction and + // the clamped correction both start out as very good approximations + // to the loss function when we are in the convex part of the + // function, but as the function starts transitioning from convex to + // concave, the Triggs approximation diverges more and more and + // ultimately becomes linear. The clamped Triggs model however + // remains quadratic. + // + // The reason why the Triggs approximation becomes so poor is + // because the curvature correction that it applies to the gauss + // newton hessian goes from being a full rank correction to a rank + // deficient correction making the inversion of the Hessian fraught + // with all sorts of misery and suffering. + // + // The clamped correction retains its quadratic nature and inverting it + // is always well formed. + if ((sq_norm == 0.0) || (rho[2] <= 0.0)) { + residual_scaling_ = sqrt_rho1_; + alpha_sq_norm_ = 0.0; + return; + } + + // Calculate the smaller of the two solutions to the equation + // + // 0.5 * alpha^2 - alpha - rho'' / rho' * z'z = 0. + // + // Start by calculating the discriminant D. + const double D = 1.0 + 2.0 * sq_norm*rho[2] / rho[1]; + + // Since both rho[1] and rho[2] are guaranteed to be positive at + // this point, we know that D > 1.0. + + const double alpha = 1.0 - sqrt(D); + + // Calculate the constants needed by the correction routines. + residual_scaling_ = sqrt_rho1_ / (1 - alpha); + alpha_sq_norm_ = alpha / sq_norm; +} + +void Corrector::CorrectResiduals(int nrow, double* residuals) { + DCHECK(residuals != NULL); + VectorRef r_ref(residuals, nrow); + // Equation 11 in BANS. + r_ref *= residual_scaling_; +} + +void Corrector::CorrectJacobian(int nrow, int ncol, + double* residuals, double* jacobian) { + DCHECK(residuals != NULL); + DCHECK(jacobian != NULL); + ConstVectorRef r_ref(residuals, nrow); + MatrixRef j_ref(jacobian, nrow, ncol); + + // Equation 11 in BANS. + j_ref = sqrt_rho1_ * (j_ref - alpha_sq_norm_ * + r_ref * (r_ref.transpose() * j_ref)); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.h b/extern/libmv/third_party/ceres/internal/ceres/corrector.h new file mode 100644 index 00000000000..9914641cb01 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.h @@ -0,0 +1,88 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Class definition for the object that is responsible for applying a +// second order correction to the Gauss-Newton based on the ideas in +// BANS by Triggs et al. + +#ifndef CERES_INTERNAL_CORRECTOR_H_ +#define CERES_INTERNAL_CORRECTOR_H_ + +namespace ceres { +namespace internal { + +// Corrector is responsible for applying the second order correction +// to the residual and jacobian of a least squares problem based on a +// radial robust loss. +// +// The key idea here is to look at the expressions for the robustified +// gauss newton approximation and then take its squareroot to get the +// corresponding corrections to the residual and jacobian. For the +// full expressions see Eq. 10 and 11 in BANS by Triggs et al. +class Corrector { + public: + // The constructor takes the squared norm, the value, the first and + // second derivatives of the LossFunction. It precalculates some of + // the constants that are needed to apply the correction. The + // correction constant alpha is constrained to be smaller than 1, if + // it becomes larger than 1, then it will reverse the sign of the + // residual and the correction. If alpha is equal to 1 will result + // in a divide by zero error. Thus we constrain alpha to be upper + // bounded by 1 - epsilon_. + // + // rho[1] needs to be positive. The constructor will crash if this + // condition is not met. + // + // In practical use CorrectJacobian should always be called before + // CorrectResidual, because the jacobian correction depends on the + // value of the uncorrected residual values. + explicit Corrector(double sq_norm, const double rho[3]); + + // residuals *= sqrt(rho[1]) / (1 - alpha) + void CorrectResiduals(int nrow, double* residuals); + + // jacobian = sqrt(rho[1]) * jacobian - + // sqrt(rho[1]) * alpha / sq_norm * residuals residuals' * jacobian. + // + // The method assumes that the jacobian has row-major storage. It is + // the caller's responsibility to ensure that the pointer to + // jacobian is not null. + void CorrectJacobian(int nrow, int ncol, + double* residuals, double* jacobian); + + private: + double sqrt_rho1_; + double residual_scaling_; + double alpha_sq_norm_; +}; +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CORRECTOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h new file mode 100644 index 00000000000..1177b83a556 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h @@ -0,0 +1,110 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A jacobian writer that writes to dense Eigen matrices. + +#ifndef CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ +#define CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ + +#include "ceres/casts.h" +#include "ceres/dense_sparse_matrix.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/scratch_evaluate_preparer.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +class DenseJacobianWriter { + public: + DenseJacobianWriter(Evaluator::Options /* ignored */, + Program* program) + : program_(program) { + } + + // JacobianWriter interface. + + // Since the dense matrix has different layout than that assumed by the cost + // functions, use scratch space to store the jacobians temporarily then copy + // them over to the larger jacobian later. + ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) { + return ScratchEvaluatePreparer::Create(*program_, num_threads); + } + + SparseMatrix* CreateJacobian() const { + return new DenseSparseMatrix(program_->NumResiduals(), + program_->NumEffectiveParameters()); + } + + void Write(int residual_id, + int residual_offset, + double **jacobians, + SparseMatrix* jacobian) { + DenseSparseMatrix* dense_jacobian; + if (jacobian != NULL) { + dense_jacobian = down_cast(jacobian); + } + const ResidualBlock* residual_block = + program_->residual_blocks()[residual_id]; + int num_parameter_blocks = residual_block->NumParameterBlocks(); + int num_residuals = residual_block->NumResiduals(); + + // Now copy the jacobians for each parameter into the dense jacobian matrix. + for (int j = 0; j < num_parameter_blocks; ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + + // If the parameter block is fixed, then there is nothing to do. + if (parameter_block->IsConstant()) { + continue; + } + + int parameter_block_size = parameter_block->LocalSize(); + MatrixRef parameter_jacobian(jacobians[j], + num_residuals, + parameter_block_size); + + dense_jacobian->mutable_matrix().block( + residual_offset, + parameter_block->delta_offset(), + num_residuals, + parameter_block_size) = parameter_jacobian; + } + } + + private: + Program* program_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc new file mode 100644 index 00000000000..328505404d7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc @@ -0,0 +1,93 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/dense_qr_solver.h" + +#include + +#include "Eigen/Dense" +#include "ceres/linear_solver.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +DenseQRSolver::DenseQRSolver(const LinearSolver::Options& options) + : options_(options) {} + +LinearSolver::Summary DenseQRSolver::SolveImpl( + DenseSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + const int num_rows = A->num_rows(); + const int num_cols = A->num_cols(); + VLOG(2) << "DenseQRSolver: " + << num_rows << " x " << num_cols << " system."; + + if (per_solve_options.D != NULL) { + // Temporarily append a diagonal block to the A matrix, but undo + // it before returning the matrix to the user. + A->AppendDiagonal(per_solve_options.D); + } + + // rhs = [b;0] to account for the additional rows in the lhs. + Vector rhs(num_rows + ((per_solve_options.D !=NULL) ? num_cols : 0)); + rhs.setZero(); + rhs.head(num_rows) = ConstVectorRef(b, num_rows); + + // Solve the system. + VectorRef(x, num_cols) = A->matrix().colPivHouseholderQr().solve(rhs); + + VLOG(3) << "A:\n" << A->matrix(); + VLOG(3) << "x:\n" << VectorRef(x, num_cols); + VLOG(3) << "b:\n" << rhs; + VLOG(3) << "error: " << (A->matrix() * VectorRef(x, num_cols) - rhs).norm(); + + + if (per_solve_options.D != NULL) { + // Undo the modifications to the matrix A. + A->RemoveDiagonal(); + } + + // We always succeed, since the QR solver returns the best solution + // it can. It is the job of the caller to determine if the solution + // is good enough or not. + LinearSolver::Summary summary; + summary.num_iterations = 1; + summary.termination_type = TOLERANCE; + return summary; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h new file mode 100644 index 00000000000..990c8d445eb --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h @@ -0,0 +1,99 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Solve dense rectangular systems Ax = b using the QR factoriztion. +#ifndef CERES_INTERNAL_DENSE_QR_SOLVER_H_ +#define CERES_INTERNAL_DENSE_QR_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class DenseSparseMatrix; + +// This class implements the LinearSolver interface for solving +// rectangular/unsymmetric (well constrained) linear systems of the +// form +// +// Ax = b +// +// Since there does not usually exist a solution that satisfies these +// equations, the solver instead solves the linear least squares +// problem +// +// min_x |Ax - b|^2 +// +// The solution strategy is based on computing the QR decomposition of +// A, i.e. +// +// A = QR +// +// Where Q is an orthonormal matrix and R is an upper triangular +// matrix. Then +// +// Ax = b +// QRx = b +// Q'QRx = Q'b +// Rx = Q'b +// x = R^{-1} Q'b +// +// If the PerSolveOptions struct has a non-null array D, then the +// augmented/regularized linear system +// +// [ A ]x = [b] +// [ diag(D) ] [0] +// +// is solved. +// +// This class uses the dense QR factorization routines from the Eigen +// library. This solver always returns a solution, it is the user's +// responsibility to judge if the solution is good enough for their +// purposes. +class DenseQRSolver: public DenseSparseMatrixSolver { + public: + explicit DenseQRSolver(const LinearSolver::Options& options); + + private: + virtual LinearSolver::Summary SolveImpl( + DenseSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + const LinearSolver::Options options_; + DISALLOW_COPY_AND_ASSIGN(DenseQRSolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_QR_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc new file mode 100644 index 00000000000..5d392ba6c3b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc @@ -0,0 +1,197 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/dense_sparse_matrix.h" + +#include +#include "ceres/matrix_proto.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +DenseSparseMatrix::DenseSparseMatrix(int num_rows, int num_cols) + : has_diagonal_appended_(false), + has_diagonal_reserved_(false) { + // Allocate enough space for the diagonal. + m_.resize(num_rows, num_cols); + m_.setZero(); +} + +DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m) + : m_(Eigen::MatrixXd::Zero(m.num_rows(), m.num_cols())), + has_diagonal_appended_(false), + has_diagonal_reserved_(false) { + const double *values = m.values(); + const int *rows = m.rows(); + const int *cols = m.cols(); + int num_nonzeros = m.num_nonzeros(); + + for (int i = 0; i < num_nonzeros; ++i) { + m_(rows[i], cols[i]) += values[i]; + } +} + +DenseSparseMatrix::DenseSparseMatrix(const Matrix& m) + : m_(m), + has_diagonal_appended_(false), + has_diagonal_reserved_(false) { +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +DenseSparseMatrix::DenseSparseMatrix(const SparseMatrixProto& outer_proto) + : m_(Eigen::MatrixXd::Zero( + outer_proto.dense_matrix().num_rows(), + outer_proto.dense_matrix().num_cols())), + has_diagonal_appended_(false), + has_diagonal_reserved_(false) { + const DenseSparseMatrixProto& proto = outer_proto.dense_matrix(); + for (int i = 0; i < m_.rows(); ++i) { + for (int j = 0; j < m_.cols(); ++j) { + m_(i, j) = proto.values(m_.cols() * i + j); + } + } +} +#endif + +void DenseSparseMatrix::SetZero() { + m_.setZero(); +} + +void DenseSparseMatrix::RightMultiply(const double* x, double* y) const { + VectorRef(y, num_rows()) += matrix() * ConstVectorRef(x, num_cols()); +} + +void DenseSparseMatrix::LeftMultiply(const double* x, double* y) const { + VectorRef(y, num_cols()) += + matrix().transpose() * ConstVectorRef(x, num_rows()); +} + +void DenseSparseMatrix::SquaredColumnNorm(double* x) const { + VectorRef(x, num_cols()) = m_.colwise().squaredNorm(); +} + +void DenseSparseMatrix::ScaleColumns(const double* scale) { + m_ *= ConstVectorRef(scale, num_cols()).asDiagonal(); +} + +void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + *dense_matrix = m_; +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { + CHECK(!has_diagonal_appended_) << "Not supported."; + outer_proto->Clear(); + DenseSparseMatrixProto* proto = outer_proto->mutable_dense_matrix(); + + proto->set_num_rows(num_rows()); + proto->set_num_cols(num_cols()); + + int num_nnz = num_nonzeros(); + for (int i = 0; i < num_nnz; ++i) { + proto->add_values(m_.data()[i]); + } +} +#endif + +void DenseSparseMatrix::AppendDiagonal(double *d) { + CHECK(!has_diagonal_appended_); + if (!has_diagonal_reserved_) { + Matrix tmp = m_; + m_.resize(m_.rows() + m_.cols(), m_.cols()); + m_.setZero(); + m_.block(0, 0, tmp.rows(), tmp.cols()) = tmp; + has_diagonal_reserved_ = true; + } + + m_.bottomLeftCorner(m_.cols(), m_.cols()) = + ConstVectorRef(d, m_.cols()).asDiagonal(); + has_diagonal_appended_ = true; +} + +void DenseSparseMatrix::RemoveDiagonal() { + CHECK(has_diagonal_appended_); + has_diagonal_appended_ = false; + // Leave the diagonal reserved. +} + +int DenseSparseMatrix::num_rows() const { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return m_.rows() - m_.cols(); + } + return m_.rows(); +} + +int DenseSparseMatrix::num_cols() const { + return m_.cols(); +} + +int DenseSparseMatrix::num_nonzeros() const { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return (m_.rows() - m_.cols()) * m_.cols(); + } + return m_.rows() * m_.cols(); +} + +ConstAlignedMatrixRef DenseSparseMatrix::matrix() const { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return ConstAlignedMatrixRef( + m_.data(), m_.rows() - m_.cols(), m_.cols()); + } + return ConstAlignedMatrixRef(m_.data(), m_.rows(), m_.cols()); +} + +AlignedMatrixRef DenseSparseMatrix::mutable_matrix() { + if (has_diagonal_reserved_ && !has_diagonal_appended_) { + return AlignedMatrixRef( + m_.data(), m_.rows() - m_.cols(), m_.cols()); + } + return AlignedMatrixRef(m_.data(), m_.rows(), m_.cols()); +} + +void DenseSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + const int active_rows = + (has_diagonal_reserved_ && !has_diagonal_appended_) + ? (m_.rows() - m_.cols()) + : m_.rows(); + + for (int r = 0; r < active_rows; ++r) { + for (int c = 0; c < m_.cols(); ++c) { + fprintf(file, "% 10d % 10d %17f\n", r, c, m_(r, c)); + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h new file mode 100644 index 00000000000..416c2143c2c --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h @@ -0,0 +1,116 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A dense matrix implemented under the SparseMatrix interface. + +#ifndef CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ + +#include +#include "ceres/sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; +class TripletSparseMatrix; + +class DenseSparseMatrix : public SparseMatrix { + public: + // Build a matrix with the same content as the TripletSparseMatrix + // m. This assumes that m does not have any repeated entries. + explicit DenseSparseMatrix(const TripletSparseMatrix& m); + explicit DenseSparseMatrix(const Matrix& m); +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit DenseSparseMatrix(const SparseMatrixProto& proto); +#endif + + DenseSparseMatrix(int num_rows, int num_cols); + + virtual ~DenseSparseMatrix() {} + + // SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto* proto) const; +#endif + virtual void ToTextFile(FILE* file) const; + virtual int num_rows() const; + virtual int num_cols() const; + virtual int num_nonzeros() const; + virtual const double* values() const { return m_.data(); } + virtual double* mutable_values() { return m_.data(); } + + ConstAlignedMatrixRef matrix() const; + AlignedMatrixRef mutable_matrix(); + + // Only one diagonal can be appended at a time. The diagonal is appended to + // as a new set of rows, e.g. + // + // Original matrix: + // + // x x x + // x x x + // x x x + // + // After append diagonal (1, 2, 3): + // + // x x x + // x x x + // x x x + // 1 0 0 + // 0 2 0 + // 0 0 3 + // + // Calling RemoveDiagonal removes the block. It is a fatal error to append a + // diagonal to a matrix that already has an appended diagonal, and it is also + // a fatal error to remove a diagonal from a matrix that has none. + void AppendDiagonal(double *d); + void RemoveDiagonal(); + + private: + Matrix m_; + bool has_diagonal_appended_; + bool has_diagonal_reserved_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc new file mode 100644 index 00000000000..e9755043bab --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc @@ -0,0 +1,114 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include "ceres/detect_structure.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +void DetectStructure(const CompressedRowBlockStructure& bs, + const int num_eliminate_blocks, + int* row_block_size, + int* e_block_size, + int* f_block_size) { + const int num_row_blocks = bs.rows.size(); + *row_block_size = 0; + *e_block_size = 0; + *f_block_size = 0; + + // Iterate over row blocks of the matrix, checking if row_block, + // e_block or f_block sizes remain constant. + for (int r = 0; r < num_row_blocks; ++r) { + const CompressedRow& row = bs.rows[r]; + // We do not care about the sizes of the blocks in rows which do + // not contain e_blocks. + if (row.cells.front().block_id >= num_eliminate_blocks) { + break; + } + const int e_block_id = row.cells.front().block_id; + + if (*row_block_size == 0) { + *row_block_size = row.block.size; + } else if (*row_block_size != Eigen::Dynamic && + *row_block_size != row.block.size) { + *row_block_size = Eigen::Dynamic; + VLOG(2) << "Dynamic row block size because the block size changed from " + << *row_block_size << " to " + << row.block.size; + } + + + if (*e_block_size == 0) { + *e_block_size = bs.cols[e_block_id].size; + } else if (*e_block_size != Eigen::Dynamic && + *e_block_size != bs.cols[e_block_id].size) { + *e_block_size = Eigen::Dynamic; + VLOG(2) << "Dynamic e block size because the block size changed from " + << *e_block_size << " to " + << bs.cols[e_block_id].size; + } + + if (*f_block_size == 0) { + if (row.cells.size() > 1) { + const int f_block_id = row.cells[1].block_id; + *f_block_size = bs.cols[f_block_id].size; + } + } else if (*f_block_size != Eigen::Dynamic) { + for (int c = 1; c < row.cells.size(); ++c) { + if (*f_block_size != bs.cols[row.cells[c].block_id].size) { + *f_block_size = Eigen::Dynamic; + VLOG(2) << "Dynamic f block size because the block size " + << "changed from " << *f_block_size << " to " + << bs.cols[row.cells[c].block_id].size; + break; + } + } + } + + const bool is_everything_dynamic = (*row_block_size == Eigen::Dynamic && + *e_block_size == Eigen::Dynamic && + *f_block_size == Eigen::Dynamic); + if (is_everything_dynamic) { + break; + } + } + + CHECK_NE(*row_block_size, 0) << "No rows found"; + CHECK_NE(*e_block_size, 0) << "No e type blocks found"; + VLOG(1) << "Schur complement static structure <" + << *row_block_size << "," + << *e_block_size << "," + << *f_block_size << ">."; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h new file mode 100644 index 00000000000..8af4f236690 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h @@ -0,0 +1,63 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_DETECT_STRUCTURE_H_ +#define CERES_INTERNAL_DETECT_STRUCTURE_H_ + +#include "ceres/block_structure.h" + +namespace ceres { +namespace internal { + +// Detect static blocks in the problem sparsity. For rows containing +// e_blocks, we are interested in detecting if the size of the row +// blocks, e_blocks and the f_blocks remain constant. If they do, then +// we can use template specialization to improve the performance of +// the block level linear algebra operations used by the +// SchurEliminator. +// +// If a block size is not constant, we return Eigen::Dynamic as the +// value. This just means that the eliminator uses dynamically sized +// linear algebra operations rather than static operations whose size +// is known as compile time. +// +// For more details about e_blocks and f_blocks, see +// schur_complement.h. This information is used to initialized an +// appropriate template specialization of SchurEliminator. +void DetectStructure(const CompressedRowBlockStructure& bs, + const int num_eliminate_blocks, + int* row_block_size, + int* e_block_size, + int* f_block_size); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DETECT_STRUCTURE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc new file mode 100644 index 00000000000..ea05aefec8c --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc @@ -0,0 +1,71 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include +#include "ceres/evaluator.h" +#include "ceres/block_evaluate_preparer.h" +#include "ceres/block_jacobian_writer.h" +#include "ceres/compressed_row_jacobian_writer.h" +#include "ceres/scratch_evaluate_preparer.h" +#include "ceres/dense_jacobian_writer.h" +#include "ceres/program_evaluator.h" + +namespace ceres { +namespace internal { + +Evaluator::~Evaluator() {} + +Evaluator* Evaluator::Create(const Evaluator::Options& options, + Program* program, + string* error) { + switch (options.linear_solver_type) { + case DENSE_QR: + return new ProgramEvaluator(options, + program); + case DENSE_SCHUR: + case SPARSE_SCHUR: + case ITERATIVE_SCHUR: + case CGNR: + return new ProgramEvaluator(options, + program); + case SPARSE_NORMAL_CHOLESKY: + return new ProgramEvaluator(options, + program); + default: + *error = "Invalid Linear Solver Type. Unable to create evaluator."; + return NULL; + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h new file mode 100644 index 00000000000..adefdd26660 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_EVALUATOR_H_ +#define CERES_INTERNAL_EVALUATOR_H_ + +#include +#include "ceres/internal/port.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class Program; +class SparseMatrix; + +// The Evaluator interface offers a way to interact with a least squares cost +// function that is useful for an optimizer that wants to minimize the least +// squares objective. This insulates the optimizer from issues like Jacobian +// storage, parameterization, etc. +class Evaluator { + public: + virtual ~Evaluator(); + + struct Options { + Options() + : num_threads(1), + num_eliminate_blocks(-1), + linear_solver_type(DENSE_QR) {} + + int num_threads; + int num_eliminate_blocks; + LinearSolverType linear_solver_type; + }; + + static Evaluator* Create(const Options& options, + Program* program, + string* error); + + // Build and return a sparse matrix for storing and working with the Jacobian + // of the objective function. The jacobian has dimensions + // NumEffectiveParameters() by NumParameters(), and is typically extremely + // sparse. Since the sparsity pattern of the Jacobian remains constant over + // the lifetime of the optimization problem, this method is used to + // instantiate a SparseMatrix object with the appropriate sparsity structure + // (which can be an expensive operation) and then reused by the optimization + // algorithm and the various linear solvers. + // + // It is expected that the classes implementing this interface will be aware + // of their client's requirements for the kind of sparse matrix storage and + // layout that is needed for an efficient implementation. For example + // CompressedRowOptimizationProblem creates a compressed row representation of + // the jacobian for use with CHOLMOD, where as BlockOptimizationProblem + // creates a BlockSparseMatrix representation of the jacobian for use in the + // Schur complement based methods. + virtual SparseMatrix* CreateJacobian() const = 0; + + // Evaluate the cost function for the given state. Returns the cost, + // residuals, and jacobian in the corresponding arguments. Both residuals and + // jacobian are optional; to avoid computing them, pass NULL. + // + // If non-NULL, the Jacobian must have a suitable sparsity pattern; only the + // values array of the jacobian is modified. + // + // state is an array of size NumParameters(), cost is a pointer to a single + // double, and residuals is an array of doubles of size NumResiduals(). + virtual bool Evaluate(const double* state, + double* cost, + double* residuals, + SparseMatrix* jacobian) = 0; + + // Make a change delta (of size NumEffectiveParameters()) to state (of size + // NumParameters()) and store the result in state_plus_delta. + // + // In the case that there are no parameterizations used, this is equivalent to + // + // state_plus_delta[i] = state[i] + delta[i] ; + // + // however, the mapping is more complicated in the case of parameterizations + // like quaternions. This is the same as the "Plus()" operation in + // local_parameterization.h, but operating over the entire state vector for a + // problem. + virtual bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const = 0; + + // The number of parameters in the optimization problem. + virtual int NumParameters() const = 0; + + // This is the effective number of parameters that the optimizer may adjust. + // This applies when there are parameterizations on some of the parameters. + virtual int NumEffectiveParameters() const = 0; + + // The number of residuals in the optimization problem. + virtual int NumResiduals() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_EVALUATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.cc b/extern/libmv/third_party/ceres/internal/ceres/file.cc new file mode 100644 index 00000000000..5fc9d220861 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/file.cc @@ -0,0 +1,93 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Really simple file IO. + +#include +#include + +namespace ceres { +namespace internal { + +using std::string; + +void WriteStringToFileOrDie(const string &data, const string &filename) { + FILE* file_descriptor = fopen(filename.c_str(), "wb"); + if (!file_descriptor) { + LOG(FATAL) << "Couldn't write to file: " << filename; + } + fwrite(data.c_str(), 1, data.size(), file_descriptor); + fclose(file_descriptor); +} + +void ReadFileToStringOrDie(const string &filename, string *data) { + FILE* file_descriptor = file_descriptor = fopen(filename.c_str(), "r"); + + if (!file_descriptor) { + LOG(FATAL) << "Couldn't read file: " << filename; + } + + // Resize the input buffer appropriately. + fseek(file_descriptor, 0L, SEEK_END); + int num_bytes = ftell(file_descriptor); + data->resize(num_bytes); + + // Read the data. + fseek(file_descriptor, 0L, SEEK_SET); + int num_read = fread(&((*data)[0]), + sizeof((*data)[0]), + num_bytes, + file_descriptor); + if (num_read != num_bytes) { + LOG(FATAL) << "Couldn't read all of " << filename + << "expected bytes: " << num_bytes * sizeof((*data)[0]) + << "actual bytes: " << num_read; + } + fclose(file_descriptor); +} + +string JoinPath(const string& dirname, const string& basename) { +#ifdef _WIN32 + static const char separator = '\\'; +#else + static const char separator = '/'; +#endif // _WIN32 + + if ((!basename.empty() && basename[0] == separator) || dirname.empty()) { + return basename; + } else if (dirname[dirname.size() - 1] == separator) { + return dirname + basename; + } else { + return dirname + string(&separator, 1) + basename; + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.h b/extern/libmv/third_party/ceres/internal/ceres/file.h new file mode 100644 index 00000000000..4741d650646 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/file.h @@ -0,0 +1,52 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Simple file IO support. This is a portability shim. + +#ifndef CERES_INTERNAL_FILE_H_ +#define CERES_INTERNAL_FILE_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +void WriteStringToFileOrDie(const string &data, const string &filename); +void ReadFileToStringOrDie(const string &filename, string *data); + +// Join two path components, adding a slash if necessary. If basename is an +// absolute path then JoinPath ignores dirname and simply returns basename. +string JoinPath(const string& dirname, const string& basename); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_FILE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc new file mode 100644 index 00000000000..5529386e485 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, 2>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc new file mode 100644 index 00000000000..fd7af95192e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc new file mode 100644 index 00000000000..109483e9fc0 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc new file mode 100644 index 00000000000..b93e82fe2fa --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 2, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc new file mode 100644 index 00000000000..86352c07304 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc new file mode 100644 index 00000000000..200df7f5931 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc new file mode 100644 index 00000000000..1fda3434bef --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, 9>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc new file mode 100644 index 00000000000..385cd2d70c9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 3, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc new file mode 100644 index 00000000000..7b15d6366ac --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 4, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc new file mode 100644 index 00000000000..29a610d743e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 4, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc new file mode 100644 index 00000000000..a3bc4dc6f83 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<2, 4, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc new file mode 100644 index 00000000000..f71a4f62944 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, 2>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc new file mode 100644 index 00000000000..52259fb1a67 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, 3>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc new file mode 100644 index 00000000000..775424e6c8f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, 4>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc new file mode 100644 index 00000000000..97cde594059 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<4, 4, Dynamic>; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc new file mode 100644 index 00000000000..4cba32e26c8 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc @@ -0,0 +1,53 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator; + +} // namespace internal +} // namespace ceres + diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc new file mode 100644 index 00000000000..abba40824ef --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc @@ -0,0 +1,308 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/gradient_checking_cost_function.h" + +#include +#include +#include +#include +#include + +#include +#include "ceres/parameter_block.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/runtime_numeric_diff_cost_function.h" +#include "ceres/stringprintf.h" +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/problem.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { +namespace { + +// True if x and y have an absolute relative difference less than +// relative_precision and false otherwise. Stores the relative and absolute +// difference in relative/absolute_error if non-NULL. +bool IsClose(double x, double y, double relative_precision, + double *relative_error, + double *absolute_error) { + double local_absolute_error; + double local_relative_error; + if (!absolute_error) { + absolute_error = &local_absolute_error; + } + if (!relative_error) { + relative_error = &local_relative_error; + } + *absolute_error = fabs(x - y); + *relative_error = *absolute_error / max(fabs(x), fabs(y)); + if (x == 0 || y == 0) { + // If x or y is exactly zero, then relative difference doesn't have any + // meaning. Take the absolute difference instead. + *relative_error = *absolute_error; + } + return fabs(*relative_error) < fabs(relative_precision); +} + +class GradientCheckingCostFunction : public CostFunction { + public: + GradientCheckingCostFunction(const CostFunction* function, + double relative_step_size, + double relative_precision, + const string& extra_info) + : function_(function), + finite_diff_cost_function_( + CreateRuntimeNumericDiffCostFunction(function, + CENTRAL, + relative_step_size)), + relative_precision_(relative_precision), + extra_info_(extra_info) { + *mutable_parameter_block_sizes() = function->parameter_block_sizes(); + set_num_residuals(function->num_residuals()); + } + + virtual ~GradientCheckingCostFunction() { } + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + if (!jacobians) { + // Nothing to check in this case; just forward. + return function_->Evaluate(parameters, residuals, NULL); + } + + int num_residuals = function_->num_residuals(); + + // Make space for the jacobians of the two methods. + const vector& block_sizes = function_->parameter_block_sizes(); + vector term_jacobians(block_sizes.size()); + vector finite_difference_jacobians(block_sizes.size()); + vector term_jacobian_pointers(block_sizes.size()); + vector finite_difference_jacobian_pointers(block_sizes.size()); + for (int i = 0; i < block_sizes.size(); i++) { + term_jacobians[i].resize(num_residuals, block_sizes[i]); + term_jacobian_pointers[i] = term_jacobians[i].data(); + finite_difference_jacobians[i].resize(num_residuals, block_sizes[i]); + finite_difference_jacobian_pointers[i] = + finite_difference_jacobians[i].data(); + } + + // Evaluate the derivative using the user supplied code. + if (!function_->Evaluate(parameters, + residuals, + &term_jacobian_pointers[0])) { + LOG(WARNING) << "Function evaluation failed."; + return false; + } + + // Evaluate the derivative using numeric derivatives. + finite_diff_cost_function_->Evaluate( + parameters, + residuals, + &finite_difference_jacobian_pointers[0]); + + // See if any elements have relative error larger than the threshold. + int num_bad_jacobian_components = 0; + double worst_relative_error = 0; + + // Accumulate the error message for all the jacobians, since it won't get + // output if there are no bad jacobian components. + string m; + for (int k = 0; k < block_sizes.size(); k++) { + // Copy the original jacobian blocks into the jacobians array. + if (jacobians[k] != NULL) { + MatrixRef(jacobians[k], + term_jacobians[k].rows(), + term_jacobians[k].cols()) = term_jacobians[k]; + } + + StringAppendF(&m, + "========== " + "Jacobian for " "block %d: (%ld by %ld)) " + "==========\n", + k, + term_jacobians[k].rows(), + term_jacobians[k].cols()); + // The funny spacing creates appropriately aligned column headers. + m += " block row col user dx/dy num diff dx/dy " + "abs error relative error parameter residual\n"; + + for (int i = 0; i < term_jacobians[k].rows(); i++) { + for (int j = 0; j < term_jacobians[k].cols(); j++) { + double term_jacobian = term_jacobians[k](i, j); + double finite_jacobian = finite_difference_jacobians[k](i, j); + double relative_error, absolute_error; + bool bad_jacobian_entry = + !IsClose(term_jacobian, + finite_jacobian, + relative_precision_, + &relative_error, + &absolute_error); + worst_relative_error = std::max(worst_relative_error, + relative_error); + + StringAppendF(&m, "%6d %4d %4d %17g %17g %17g %17g %17g %17g", + k, i, j, + term_jacobian, finite_jacobian, + absolute_error, relative_error, + parameters[k][j], + residuals[i]); + + if (bad_jacobian_entry) { + num_bad_jacobian_components++; + StringAppendF( + &m, " ------ (%d,%d,%d) Relative error worse than %g", + k, i, j, relative_precision_); + } + m += "\n"; + } + } + } + + // Since there were some bad errors, dump comprehensive debug info. + if (num_bad_jacobian_components) { + string header = StringPrintf("Detected %d bad jacobian component(s). " + "Worst relative error was %g.\n", + num_bad_jacobian_components, + worst_relative_error); + if (!extra_info_.empty()) { + header += "Extra info for this residual: " + extra_info_ + "\n"; + } + LOG(WARNING) << "\n" << header << m; + } + return true; + } + + private: + const CostFunction* function_; + internal::scoped_ptr finite_diff_cost_function_; + double relative_precision_; + string extra_info_; +}; + +} // namespace + +CostFunction *CreateGradientCheckingCostFunction( + const CostFunction *cost_function, + double relative_step_size, + double relative_precision, + const string& extra_info) { + return new GradientCheckingCostFunction(cost_function, + relative_step_size, + relative_precision, + extra_info); +} + +ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl, + double relative_step_size, + double relative_precision) { + // We create new CostFunctions by wrapping the original CostFunction + // in a gradient checking CostFunction. So its okay for the + // ProblemImpl to take ownership of it and destroy it. The + // LossFunctions and LocalParameterizations are reused and since + // they are owned by problem_impl, gradient_checking_problem_impl + // should not take ownership of it. + Problem::Options gradient_checking_problem_options; + gradient_checking_problem_options.cost_function_ownership = TAKE_OWNERSHIP; + gradient_checking_problem_options.loss_function_ownership = + DO_NOT_TAKE_OWNERSHIP; + gradient_checking_problem_options.local_parameterization_ownership = + DO_NOT_TAKE_OWNERSHIP; + + ProblemImpl* gradient_checking_problem_impl = new ProblemImpl( + gradient_checking_problem_options); + + Program* program = problem_impl->mutable_program(); + + // For every ParameterBlock in problem_impl, create a new parameter + // block with the same local parameterization and constancy. + const vector& parameter_blocks = program->parameter_blocks(); + for (int i = 0; i < parameter_blocks.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks[i]; + gradient_checking_problem_impl->AddParameterBlock( + parameter_block->mutable_user_state(), + parameter_block->Size(), + parameter_block->mutable_local_parameterization()); + + if (parameter_block->IsConstant()) { + gradient_checking_problem_impl->SetParameterBlockConstant( + parameter_block->mutable_user_state()); + } + } + + // For every ResidualBlock in problem_impl, create a new + // ResidualBlock by wrapping its CostFunction inside a + // GradientCheckingCostFunction. + const vector& residual_blocks = program->residual_blocks(); + for (int i = 0; i < residual_blocks.size(); ++i) { + ResidualBlock* residual_block = residual_blocks[i]; + + // Build a human readable string which identifies the + // ResidualBlock. This is used by the GradientCheckingCostFunction + // when logging debugging information. + string extra_info = StringPrintf( + "Residual block id %d; depends on parameters [", i); + vector parameter_blocks; + for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; + parameter_blocks.push_back(parameter_block->mutable_user_state()); + StringAppendF(&extra_info, "%p", parameter_block->mutable_user_state()); + extra_info += (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]"; + } + + // Wrap the original CostFunction in a GradientCheckingCostFunction. + CostFunction* gradient_checking_cost_function = + CreateGradientCheckingCostFunction(residual_block->cost_function(), + relative_step_size, + relative_precision, + extra_info); + + // The const_cast is necessary because + // ProblemImpl::AddResidualBlock can potentially take ownership of + // the LossFunction, but in this case we are guaranteed that this + // will not be the case, so this const_cast is harmless. + gradient_checking_problem_impl->AddResidualBlock( + gradient_checking_cost_function, + const_cast(residual_block->loss_function()), + parameter_blocks); + } + + return gradient_checking_problem_impl; +} + + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h new file mode 100644 index 00000000000..d49c8e6c244 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.h @@ -0,0 +1,85 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ +#define CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ + +#include + +#include "ceres/cost_function.h" + +namespace ceres { +namespace internal { + +class ProblemImpl; + +// Creates a CostFunction that checks the jacobians that cost_function computes +// with finite differences. Bad results are logged; required precision is +// controlled by relative_precision and the numeric differentiation step size is +// controlled with relative_step_size. See solver.h for a better explanation of +// relative_step_size. Caller owns result. +// +// The condition enforced is that +// +// (J_actual(i, j) - J_numeric(i, j)) +// ------------------------------------ < relative_precision +// max(J_actual(i, j), J_numeric(i, j)) +// +// where J_actual(i, j) is the jacobian as computed by the supplied cost +// function (by the user) and J_numeric is the jacobian as computed by finite +// differences. +// +// Note: This is quite inefficient and is intended only for debugging. +CostFunction* CreateGradientCheckingCostFunction( + const CostFunction* cost_function, + double relative_step_size, + double relative_precision, + const string& extra_info); + +// Create a new ProblemImpl object from the input problem_impl, where +// each CostFunctions in problem_impl are wrapped inside a +// GradientCheckingCostFunctions. This gives us a ProblemImpl object +// which checks its derivatives against estimates from numeric +// differentiation everytime a ResidualBlock is evaluated. +// +// relative_step_size and relative_precision are parameters to control +// the numeric differentiation and the relative tolerance between the +// jacobian computed by the CostFunctions in problem_impl and +// jacobians obtained by numerically differentiating them. For more +// details see the documentation for +// CreateGradientCheckingCostFunction above. +ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl, + double relative_step_size, + double relative_precision); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph.h b/extern/libmv/third_party/ceres/internal/ceres/graph.h new file mode 100644 index 00000000000..fd7a224f0aa --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/graph.h @@ -0,0 +1,138 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_GRAPH_H_ +#define CERES_INTERNAL_GRAPH_H_ + +#include +#include +#include "ceres/integral_types.h" +#include "ceres/map_util.h" +#include "ceres/collections_port.h" +#include "ceres/internal/macros.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// A weighted undirected graph templated over the vertex ids. Vertex +// should be hashable and comparable. +template +class Graph { + public: + Graph() {} + + // Add a weighted vertex. If the vertex already exists in the graph, + // its weight is set to the new weight. + void AddVertex(const Vertex& vertex, double weight) { + if (vertices_.find(vertex) == vertices_.end()) { + vertices_.insert(vertex); + edges_[vertex] = HashSet(); + } + vertex_weights_[vertex] = weight; + } + + // Uses weight = 1.0. If vertex already exists, its weight is set to + // 1.0. + void AddVertex(const Vertex& vertex) { + AddVertex(vertex, 1.0); + } + + // Add a weighted edge between the vertex1 and vertex2. Calling + // AddEdge on a pair of vertices which do not exist in the graph yet + // will result in undefined behavior. + // + // It is legal to call this method repeatedly for the same set of + // vertices. + void AddEdge(const Vertex& vertex1, const Vertex& vertex2, double weight) { + DCHECK(vertices_.find(vertex1) != vertices_.end()); + DCHECK(vertices_.find(vertex2) != vertices_.end()); + + if (edges_[vertex1].insert(vertex2).second) { + edges_[vertex2].insert(vertex1); + } + + if (vertex1 < vertex2) { + edge_weights_[make_pair(vertex1, vertex2)] = weight; + } else { + edge_weights_[make_pair(vertex2, vertex1)] = weight; + } + } + + // Uses weight = 1.0. + void AddEdge(const Vertex& vertex1, const Vertex& vertex2) { + AddEdge(vertex1, vertex2, 1.0); + } + + // Calling VertexWeight on a vertex not in the graph will result in + // undefined behavior. + double VertexWeight(const Vertex& vertex) const { + return FindOrDie(vertex_weights_, vertex); + } + + // Calling EdgeWeight on a pair of vertices where either one of the + // vertices is not present in the graph will result in undefined + // behaviour. If there is no edge connecting vertex1 and vertex2, + // the edge weight is zero. + double EdgeWeight(const Vertex& vertex1, const Vertex& vertex2) const { + if (vertex1 < vertex2) { + return FindWithDefault(edge_weights_, make_pair(vertex1, vertex2), 0.0); + } else { + return FindWithDefault(edge_weights_, make_pair(vertex2, vertex1), 0.0); + } + } + + // Calling Neighbors on a vertex not in the graph will result in + // undefined behaviour. + const HashSet& Neighbors(const Vertex& vertex) const { + return FindOrDie(edges_, vertex); + } + + const HashSet& vertices() const { + return vertices_; + } + + static double InvalidWeight() { + return std::numeric_limits::quiet_NaN(); + }; + + private: + HashSet vertices_; + HashMap vertex_weights_; + HashMap > edges_; + HashMap, double> edge_weights_; + + DISALLOW_COPY_AND_ASSIGN(Graph); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRAPH_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h new file mode 100644 index 00000000000..3b42d936336 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h @@ -0,0 +1,270 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Various algorithms that operate on undirected graphs. + +#ifndef CERES_INTERNAL_GRAPH_ALGORITHMS_H_ +#define CERES_INTERNAL_GRAPH_ALGORITHMS_H_ + +#include +#include +#include "ceres/collections_port.h" +#include "ceres/graph.h" + +namespace ceres { +namespace internal { + +// Compare two vertices of a graph by their degrees. +template +class VertexDegreeLessThan { + public: + explicit VertexDegreeLessThan(const Graph& graph) + : graph_(graph) {} + + bool operator()(const Vertex& lhs, const Vertex& rhs) const { + if (graph_.Neighbors(lhs).size() == graph_.Neighbors(rhs).size()) { + return lhs < rhs; + } + return graph_.Neighbors(lhs).size() < graph_.Neighbors(rhs).size(); + } + + private: + const Graph& graph_; +}; + +// Order the vertices of a graph using its (approximately) largest +// independent set, where an independent set of a graph is a set of +// vertices that have no edges connecting them. The maximum +// independent set problem is NP-Hard, but there are effective +// approximation algorithms available. The implementation here uses a +// breadth first search that explores the vertices in order of +// increasing degree. The same idea is used by Saad & Li in "MIQR: A +// multilevel incomplete QR preconditioner for large sparse +// least-squares problems", SIMAX, 2007. +// +// Given a undirected graph G(V,E), the algorithm is a greedy BFS +// search where the vertices are explored in increasing order of their +// degree. The output vector ordering contains elements of S in +// increasing order of their degree, followed by elements of V - S in +// increasing order of degree. The return value of the function is the +// cardinality of S. +template +int IndependentSetOrdering(const Graph& graph, + vector* ordering) { + const HashSet& vertices = graph.vertices(); + const int num_vertices = vertices.size(); + + CHECK_NOTNULL(ordering); + ordering->clear(); + ordering->reserve(num_vertices); + + // Colors for labeling the graph during the BFS. + const char kWhite = 0; + const char kGrey = 1; + const char kBlack = 2; + + // Mark all vertices white. + HashMap vertex_color; + vector vertex_queue; + for (typename HashSet::const_iterator it = vertices.begin(); + it != vertices.end(); + ++it) { + vertex_color[*it] = kWhite; + vertex_queue.push_back(*it); + } + + + sort(vertex_queue.begin(), vertex_queue.end(), + VertexDegreeLessThan(graph)); + + // Iterate over vertex_queue. Pick the first white vertex, add it + // to the independent set. Mark it black and its neighbors grey. + for (int i = 0; i < vertex_queue.size(); ++i) { + const Vertex& vertex = vertex_queue[i]; + if (vertex_color[vertex] != kWhite) { + continue; + } + + ordering->push_back(vertex); + vertex_color[vertex] = kBlack; + const HashSet& neighbors = graph.Neighbors(vertex); + for (typename HashSet::const_iterator it = neighbors.begin(); + it != neighbors.end(); + ++it) { + vertex_color[*it] = kGrey; + } + } + + int independent_set_size = ordering->size(); + + // Iterate over the vertices and add all the grey vertices to the + // ordering. At this stage there should only be black or grey + // vertices in the graph. + for (typename vector::const_iterator it = vertex_queue.begin(); + it != vertex_queue.end(); + ++it) { + const Vertex vertex = *it; + DCHECK(vertex_color[vertex] != kWhite); + if (vertex_color[vertex] != kBlack) { + ordering->push_back(vertex); + } + } + + CHECK_EQ(ordering->size(), num_vertices); + return independent_set_size; +} + +// Find the connected component for a vertex implemented using the +// find and update operation for disjoint-set. Recursively traverse +// the disjoint set structure till you reach a vertex whose connected +// component has the same id as the vertex itself. Along the way +// update the connected components of all the vertices. This updating +// is what gives this data structure its efficiency. +template +Vertex FindConnectedComponent(const Vertex& vertex, + HashMap* union_find) { + typename HashMap::iterator it = union_find->find(vertex); + DCHECK(it != union_find->end()); + if (it->second != vertex) { + it->second = FindConnectedComponent(it->second, union_find); + } + + return it->second; +} + +// Compute a degree two constrained Maximum Spanning Tree/forest of +// the input graph. Caller owns the result. +// +// Finding degree 2 spanning tree of a graph is not always +// possible. For example a star graph, i.e. a graph with n-nodes +// where one node is connected to the other n-1 nodes does not have +// a any spanning trees of degree less than n-1.Even if such a tree +// exists, finding such a tree is NP-Hard. + +// We get around both of these problems by using a greedy, degree +// constrained variant of Kruskal's algorithm. We start with a graph +// G_T with the same vertex set V as the input graph G(V,E) but an +// empty edge set. We then iterate over the edges of G in decreasing +// order of weight, adding them to G_T if doing so does not create a +// cycle in G_T} and the degree of all the vertices in G_T remains +// bounded by two. This O(|E|) algorithm results in a degree-2 +// spanning forest, or a collection of linear paths that span the +// graph G. +template +Graph* +Degree2MaximumSpanningForest(const Graph& graph) { + // Array of edges sorted in decreasing order of their weights. + vector > > weighted_edges; + Graph* forest = new Graph(); + + // Disjoint-set to keep track of the connected components in the + // maximum spanning tree. + HashMap disjoint_set; + + // Sort of the edges in the graph in decreasing order of their + // weight. Also add the vertices of the graph to the Maximum + // Spanning Tree graph and set each vertex to be its own connected + // component in the disjoint_set structure. + const HashSet& vertices = graph.vertices(); + for (typename HashSet::const_iterator it = vertices.begin(); + it != vertices.end(); + ++it) { + const Vertex vertex1 = *it; + forest->AddVertex(vertex1, graph.VertexWeight(vertex1)); + disjoint_set[vertex1] = vertex1; + + const HashSet& neighbors = graph.Neighbors(vertex1); + for (typename HashSet::const_iterator it2 = neighbors.begin(); + it2 != neighbors.end(); + ++it2) { + const Vertex vertex2 = *it2; + if (vertex1 >= vertex2) { + continue; + } + const double weight = graph.EdgeWeight(vertex1, vertex2); + weighted_edges.push_back(make_pair(weight, make_pair(vertex1, vertex2))); + } + } + + // The elements of this vector, are pairs. Sorting it using the reverse iterators gives us the edges + // in decreasing order of edges. + sort(weighted_edges.rbegin(), weighted_edges.rend()); + + // Greedily add edges to the spanning tree/forest as long as they do + // not violate the degree/cycle constraint. + for (int i =0; i < weighted_edges.size(); ++i) { + const pair& edge = weighted_edges[i].second; + const Vertex vertex1 = edge.first; + const Vertex vertex2 = edge.second; + + // Check if either of the vertices are of degree 2 already, in + // which case adding this edge will violate the degree 2 + // constraint. + if ((forest->Neighbors(vertex1).size() == 2) || + (forest->Neighbors(vertex2).size() == 2)) { + continue; + } + + // Find the id of the connected component to which the two + // vertices belong to. If the id is the same, it means that the + // two of them are already connected to each other via some other + // vertex, and adding this edge will create a cycle. + Vertex root1 = FindConnectedComponent(vertex1, &disjoint_set); + Vertex root2 = FindConnectedComponent(vertex2, &disjoint_set); + + if (root1 == root2) { + continue; + } + + // This edge can be added, add an edge in either direction with + // the same weight as the original graph. + const double edge_weight = graph.EdgeWeight(vertex1, vertex2); + forest->AddEdge(vertex1, vertex2, edge_weight); + forest->AddEdge(vertex2, vertex1, edge_weight); + + // Connected the two connected components by updating the + // disjoint_set structure. Always connect the connected component + // with the greater index with the connected component with the + // smaller index. This should ensure shallower trees, for quicker + // lookup. + if (root2 < root1) { + std::swap(root1, root2); + }; + + disjoint_set[root2] = root1; + } + return forest; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRAPH_ALGORITHMS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc new file mode 100644 index 00000000000..bd908846362 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc @@ -0,0 +1,237 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/implicit_schur_complement.h" + +#include +#include "Eigen/Dense" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +ImplicitSchurComplement::ImplicitSchurComplement(int num_eliminate_blocks, + bool constant_sparsity, + bool preconditioner) + : num_eliminate_blocks_(num_eliminate_blocks), + constant_sparsity_(constant_sparsity), + preconditioner_(preconditioner), + A_(NULL), + D_(NULL), + b_(NULL), + block_diagonal_EtE_inverse_(NULL), + block_diagonal_FtF_inverse_(NULL) { +} + +ImplicitSchurComplement::~ImplicitSchurComplement() { +} + +void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A, + const double* D, + const double* b) { + // Since initialization is reasonably heavy, perhaps we can save on + // constructing a new object everytime. + if ((A_ == NULL) || !constant_sparsity_) { + A_.reset(new PartitionedMatrixView(A, num_eliminate_blocks_)); + } + + D_ = D; + b_ = b; + + // Initialize temporary storage and compute the block diagonals of + // E'E and F'E. + if ((!constant_sparsity_) || (block_diagonal_EtE_inverse_ == NULL)) { + block_diagonal_EtE_inverse_.reset(A_->CreateBlockDiagonalEtE()); + if (preconditioner_) { + block_diagonal_FtF_inverse_.reset(A_->CreateBlockDiagonalFtF()); + } + rhs_.resize(A_->num_cols_f()); + rhs_.setZero(); + tmp_rows_.resize(A_->num_rows()); + tmp_e_cols_.resize(A_->num_cols_e()); + tmp_e_cols_2_.resize(A_->num_cols_e()); + tmp_f_cols_.resize(A_->num_cols_f()); + } else { + A_->UpdateBlockDiagonalEtE(block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + A_->UpdateBlockDiagonalFtF(block_diagonal_FtF_inverse_.get()); + } + } + + // The block diagonals of the augmented linear system contain + // contributions from the diagonal D if it is non-null. Add that to + // the block diagonals and invert them. + if (D_ != NULL) { + AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + AddDiagonalAndInvert(D_ + A_->num_cols_e(), + block_diagonal_FtF_inverse_.get()); + } + } else { + AddDiagonalAndInvert(NULL, block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + AddDiagonalAndInvert(NULL, block_diagonal_FtF_inverse_.get()); + } + } + + // Compute the RHS of the Schur complement system. + UpdateRhs(); +} + +// Evaluate the product +// +// Sx = [F'F - F'E (E'E)^-1 E'F]x +// +// By breaking it down into individual matrix vector products +// involving the matrices E and F. This is implemented using a +// PartitionedMatrixView of the input matrix A. +void ImplicitSchurComplement::RightMultiply(const double* x, double* y) const { + // y1 = F x + tmp_rows_.setZero(); + A_->RightMultiplyF(x, tmp_rows_.data()); + + // y2 = E' y1 + tmp_e_cols_.setZero(); + A_->LeftMultiplyE(tmp_rows_.data(), tmp_e_cols_.data()); + + // y3 = -(E'E)^-1 y2 + tmp_e_cols_2_.setZero(); + block_diagonal_EtE_inverse_->RightMultiply(tmp_e_cols_.data(), + tmp_e_cols_2_.data()); + tmp_e_cols_2_ *= -1.0; + + // y1 = y1 + E y3 + A_->RightMultiplyE(tmp_e_cols_2_.data(), tmp_rows_.data()); + + // y5 = D * x + if (D_ != NULL) { + ConstVectorRef Dref(D_ + A_->num_cols_e(), num_cols()); + VectorRef(y, num_cols()) = + (Dref.array().square() * + ConstVectorRef(x, num_cols()).array()).matrix(); + } else { + VectorRef(y, num_cols()).setZero(); + } + + // y = y5 + F' y1 + A_->LeftMultiplyF(tmp_rows_.data(), y); +} + +// Given a block diagonal matrix and an optional array of diagonal +// entries D, add them to the diagonal of the matrix and compute the +// inverse of each diagonal block. +void ImplicitSchurComplement::AddDiagonalAndInvert( + const double* D, + BlockSparseMatrix* block_diagonal) { + const CompressedRowBlockStructure* block_diagonal_structure = + block_diagonal->block_structure(); + for (int r = 0; r < block_diagonal_structure->rows.size(); ++r) { + const int row_block_pos = block_diagonal_structure->rows[r].block.position; + const int row_block_size = block_diagonal_structure->rows[r].block.size; + const Cell& cell = block_diagonal_structure->rows[r].cells[0]; + MatrixRef m(block_diagonal->mutable_values() + cell.position, + row_block_size, row_block_size); + + if (D != NULL) { + ConstVectorRef d(D + row_block_pos, row_block_size); + m += d.array().square().matrix().asDiagonal(); + } + + m = m + .selfadjointView() + .ldlt() + .solve(Matrix::Identity(row_block_size, row_block_size)); + } +} + +// Similar to RightMultiply, use the block structure of the matrix A +// to compute y = (E'E)^-1 (E'b - E'F x). +void ImplicitSchurComplement::BackSubstitute(const double* x, double* y) { + const int num_cols_e = A_->num_cols_e(); + const int num_cols_f = A_->num_cols_f(); + const int num_cols = A_->num_cols(); + const int num_rows = A_->num_rows(); + + // y1 = F x + tmp_rows_.setZero(); + A_->RightMultiplyF(x, tmp_rows_.data()); + + // y2 = b - y1 + tmp_rows_ = ConstVectorRef(b_, num_rows) - tmp_rows_; + + // y3 = E' y2 + tmp_e_cols_.setZero(); + A_->LeftMultiplyE(tmp_rows_.data(), tmp_e_cols_.data()); + + // y = (E'E)^-1 y3 + VectorRef(y, num_cols).setZero(); + block_diagonal_EtE_inverse_->RightMultiply(tmp_e_cols_.data(), y); + + // The full solution vector y has two blocks. The first block of + // variables corresponds to the eliminated variables, which we just + // computed via back substitution. The second block of variables + // corresponds to the Schur complement system, so we just copy those + // values from the solution to the Schur complement. + VectorRef(y + num_cols_e, num_cols_f) = ConstVectorRef(x, num_cols_f); +} + +// Compute the RHS of the Schur complement system. +// +// rhs = F'b - F'E (E'E)^-1 E'b +// +// Like BackSubstitute, we use the block structure of A to implement +// this using a series of matrix vector products. +void ImplicitSchurComplement::UpdateRhs() { + // y1 = E'b + tmp_e_cols_.setZero(); + A_->LeftMultiplyE(b_, tmp_e_cols_.data()); + + // y2 = (E'E)^-1 y1 + Vector y2 = Vector::Zero(A_->num_cols_e()); + block_diagonal_EtE_inverse_->RightMultiply(tmp_e_cols_.data(), y2.data()); + + // y3 = E y2 + tmp_rows_.setZero(); + A_->RightMultiplyE(y2.data(), tmp_rows_.data()); + + // y3 = b - y3 + tmp_rows_ = ConstVectorRef(b_, A_->num_rows()) - tmp_rows_; + + // rhs = F' y3 + rhs_.setZero(); + A_->LeftMultiplyF(tmp_rows_.data(), rhs_.data()); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h new file mode 100644 index 00000000000..37a319f9c57 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h @@ -0,0 +1,176 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// An iterative solver for solving the Schur complement/reduced camera +// linear system that arise in SfM problems. + +#ifndef CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ +#define CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ + +#include "ceres/linear_operator.h" +#include "ceres/partitioned_matrix_view.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockSparseMatrix; +class BlockSparseMatrixBase; + +// This class implements various linear algebraic operations related +// to the Schur complement without explicitly forming it. +// +// +// Given a reactangular linear system Ax = b, where +// +// A = [E F] +// +// The normal equations are given by +// +// A'Ax = A'b +// +// |E'E E'F||y| = |E'b| +// |F'E F'F||z| |F'b| +// +// and the Schur complement system is given by +// +// [F'F - F'E (E'E)^-1 E'F] z = F'b - F'E (E'E)^-1 E'b +// +// Now if we wish to solve Ax = b in the least squares sense, one way +// is to form this Schur complement system and solve it using +// Preconditioned Conjugate Gradients. +// +// The key operation in a conjugate gradient solver is the evaluation of the +// matrix vector product with the Schur complement +// +// S = F'F - F'E (E'E)^-1 E'F +// +// It is straightforward to see that matrix vector products with S can +// be evaluated without storing S in memory. Instead, given (E'E)^-1 +// (which for our purposes is an easily inverted block diagonal +// matrix), it can be done in terms of matrix vector products with E, +// F and (E'E)^-1. This class implements this functionality and other +// auxilliary bits needed to implement a CG solver on the Schur +// complement using the PartitionedMatrixView object. +// +// THREAD SAFETY: This class is nqot thread safe. In particular, the +// RightMultiply (and the LeftMultiply) methods are not thread safe as +// they depend on mutable arrays used for the temporaries needed to +// compute the product y += Sx; +class ImplicitSchurComplement : public LinearOperator { + public: + // num_eliminate_blocks is the number of E blocks in the matrix + // A. + // + // constant_sparsity indicates if across calls to Init, the sparsity + // structure of the matrix A remains constant or not. This makes for + // significant savings across multiple matrices A, e.g. when used in + // conjunction with an optimization algorithm. + // + // preconditioner indicates whether the inverse of the matrix F'F + // should be computed or not as a preconditioner for the Schur + // Complement. + // + // TODO(sameeragarwal): Get rid of the two bools below and replace + // them with enums. + ImplicitSchurComplement(int num_eliminate_blocks, + bool constant_sparsity, + bool preconditioner); + virtual ~ImplicitSchurComplement(); + + // Initialize the Schur complement for a linear least squares + // problem of the form + // + // |A | x = |b| + // |diag(D)| |0| + // + // If D is null, then it is treated as a zero dimensional matrix. It + // is important that the matrix A have a BlockStructure object + // associated with it and has a block structure that is compatible + // with the SchurComplement solver. + void Init(const BlockSparseMatrixBase& A, const double* D, const double* b); + + // y += Sx, where S is the Schur complement. + virtual void RightMultiply(const double* x, double* y) const; + + // The Schur complement is a symmetric positive definite matrix, + // thus the left and right multiply operators are the same. + virtual void LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); + } + + // y = (E'E)^-1 (E'b - E'F x). Given an estimate of the solution to + // the Schur complement system, this method computes the value of + // the e_block variables that were eliminated to form the Schur + // complement. + void BackSubstitute(const double* x, double* y); + + virtual int num_rows() const { return A_->num_cols_f(); } + virtual int num_cols() const { return A_->num_cols_f(); } + const Vector& rhs() const { return rhs_; } + + const BlockSparseMatrix* block_diagonal_EtE_inverse() const { + return block_diagonal_EtE_inverse_.get(); + } + + const BlockSparseMatrix* block_diagonal_FtF_inverse() const { + return block_diagonal_FtF_inverse_.get(); + } + + private: + void AddDiagonalAndInvert(const double* D, BlockSparseMatrix* matrix); + void UpdateRhs(); + + int num_eliminate_blocks_; + bool constant_sparsity_; + bool preconditioner_; + + scoped_ptr A_; + const double* D_; + const double* b_; + + scoped_ptr block_diagonal_EtE_inverse_; + scoped_ptr block_diagonal_FtF_inverse_; + + Vector rhs_; + + // Temporary storage vectors used to implement RightMultiply. + mutable Vector tmp_rows_; + mutable Vector tmp_e_cols_; + mutable Vector tmp_e_cols_2_; + mutable Vector tmp_f_cols_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/integral_types.h b/extern/libmv/third_party/ceres/internal/ceres/integral_types.h new file mode 100644 index 00000000000..01e04937e3e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/integral_types.h @@ -0,0 +1,92 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Portable typedefs for various fixed-size integers. Uses template +// metaprogramming instead of fragile compiler defines. + +#ifndef CERES_INTERNAL_INTEGRAL_TYPES_H_ +#define CERES_INTERNAL_INTEGRAL_TYPES_H_ + +namespace ceres { +namespace internal { + +// Compile time ternary on types. +template +struct Ternary { + typedef kTrueType type; +}; +template +struct Ternary { + typedef kFalseType type; +}; + +#define CERES_INTSIZE(TYPE) \ + typename Ternary +struct Integer { + typedef + CERES_INTSIZE(char) + CERES_INTSIZE(short) + CERES_INTSIZE(int) + CERES_INTSIZE(long int) + CERES_INTSIZE(long long) + void>::type >::type >::type >::type >::type + type; +}; + +template +struct UnsignedInteger { + typedef + CERES_INTSIZE(unsigned char) + CERES_INTSIZE(unsigned short) + CERES_INTSIZE(unsigned int) + CERES_INTSIZE(unsigned long int) + CERES_INTSIZE(unsigned long long) + void>::type >::type >::type >::type >::type + type; +}; + +#undef CERES_INTSIZE + +typedef Integer< 8>::type int8; +typedef Integer<16>::type int16; +typedef Integer<32>::type int32; +typedef Integer<64>::type int64; + +typedef UnsignedInteger< 8>::type uint8; +typedef UnsignedInteger<16>::type uint16; +typedef UnsignedInteger<32>::type uint32; +typedef UnsignedInteger<64>::type uint64; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_INTEGRAL_TYPES_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc new file mode 100644 index 00000000000..51303195317 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc @@ -0,0 +1,150 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/iterative_schur_complement_solver.h" + +#include +#include +#include + +#include +#include "Eigen/Dense" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/conjugate_gradients_solver.h" +#include "ceres/implicit_schur_complement.h" +#include "ceres/linear_solver.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/visibility_based_preconditioner.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/linear_solver.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/types.h" +#include "ceres/visibility_based_preconditioner.h" + +namespace ceres { +namespace internal { + +IterativeSchurComplementSolver::IterativeSchurComplementSolver( + const LinearSolver::Options& options) + : options_(options) { +} + +IterativeSchurComplementSolver::~IterativeSchurComplementSolver() { +} + +LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + CHECK_NOTNULL(A->block_structure()); + + // Initialize a ImplicitSchurComplement object. + if ((schur_complement_ == NULL) || (!options_.constant_sparsity)) { + schur_complement_.reset( + new ImplicitSchurComplement(options_.num_eliminate_blocks, + options_.constant_sparsity, + options_.preconditioner_type == JACOBI)); + } + schur_complement_->Init(*A, per_solve_options.D, b); + + // Initialize the solution to the Schur complement system to zero. + // + // TODO(sameeragarwal): There maybe a better initialization than an + // all zeros solution. Explore other cheap starting points. + reduced_linear_system_solution_.resize(schur_complement_->num_rows()); + reduced_linear_system_solution_.setZero(); + + // Instantiate a conjugate gradient solver that runs on the Schur complement + // matrix with the block diagonal of the matrix F'F as the preconditioner. + LinearSolver::Options cg_options; + cg_options.max_num_iterations = options_.max_num_iterations; + ConjugateGradientsSolver cg_solver(cg_options); + LinearSolver::PerSolveOptions cg_per_solve_options; + + cg_per_solve_options.r_tolerance = per_solve_options.r_tolerance; + cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance; + + bool is_preconditioner_good = false; + switch (options_.preconditioner_type) { + case IDENTITY: + is_preconditioner_good = true; + break; + case JACOBI: + // We need to strip the constness of the block_diagonal_FtF_inverse + // matrix here because the only other way to initialize the struct + // cg_solve_options would be to add a constructor to it. We know + // that the only method ever called on the preconditioner is the + // RightMultiply which is a const method so we don't need to worry + // about the object getting modified. + cg_per_solve_options.preconditioner = + const_cast( + schur_complement_->block_diagonal_FtF_inverse()); + is_preconditioner_good = true; + break; + case SCHUR_JACOBI: + case CLUSTER_JACOBI: + case CLUSTER_TRIDIAGONAL: + if (visibility_based_preconditioner_.get() == NULL) { + visibility_based_preconditioner_.reset( + new VisibilityBasedPreconditioner(*A->block_structure(), options_)); + } + is_preconditioner_good = + visibility_based_preconditioner_->Compute(*A, per_solve_options.D); + cg_per_solve_options.preconditioner = + visibility_based_preconditioner_.get(); + break; + default: + LOG(FATAL) << "Unknown Preconditioner Type"; + } + + LinearSolver::Summary cg_summary; + cg_summary.num_iterations = 0; + cg_summary.termination_type = FAILURE; + + if (is_preconditioner_good) { + cg_summary = cg_solver.Solve(schur_complement_.get(), + schur_complement_->rhs().data(), + cg_per_solve_options, + reduced_linear_system_solution_.data()); + if (cg_summary.termination_type != FAILURE) { + schur_complement_->BackSubstitute( + reduced_linear_system_solution_.data(), x); + } + } + + VLOG(2) << "CG Iterations : " << cg_summary.num_iterations; + return cg_summary; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h new file mode 100644 index 00000000000..cfeb65e1eec --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h @@ -0,0 +1,94 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ +#define CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockSparseMatrix; +class BlockSparseMatrixBase; +class ImplicitSchurComplement; +class VisibilityBasedPreconditioner; + +// This class implements an iterative solver for the linear least +// squares problems that have a bi-partitte sparsity structure common +// to Structure from Motion problems. +// +// The algorithm used by this solver was developed in a series of +// papers - "Agarwal et al, Bundle Adjustment in the Large, ECCV 2010" +// and "Wu et al, Multicore Bundle Adjustment, submitted to CVPR +// 2011" at the Univeristy of Washington. +// +// The key idea is that one can run Conjugate Gradients on the Schur +// Complement system without explicitly forming the Schur Complement +// in memory. The heavy lifting for this is done by the +// ImplicitSchurComplement class. Not forming the Schur complement in +// memory and factoring it results in substantial savings in time and +// memory. Further, iterative solvers like this open up the +// possibility of solving the Newton equations in a non-linear solver +// only approximately and terminating early, thereby saving even more +// time. +// +// For the curious, running CG on the Schur complement is the same as +// running CG on the Normal Equations with an SSOR preconditioner. For +// a proof of this fact and others related to this solver please see +// the section on Domain Decomposition Methods in Saad's book +// "Iterative Methods for Sparse Linear Systems". +class IterativeSchurComplementSolver : public BlockSparseMatrixBaseSolver { + public: + explicit IterativeSchurComplementSolver( + const LinearSolver::Options& options); + + virtual ~IterativeSchurComplementSolver(); + + private: + virtual LinearSolver::Summary SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& options, + double* x); + + LinearSolver::Options options_; + scoped_ptr schur_complement_; + scoped_ptr visibility_based_preconditioner_; + Vector reduced_linear_system_solution_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc new file mode 100644 index 00000000000..b40a5162adc --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc @@ -0,0 +1,574 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Implementation of a simple LM algorithm which uses the step sizing +// rule of "Methods for Nonlinear Least Squares" by K. Madsen, +// H.B. Nielsen and O. Tingleff. Available to download from +// +// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf +// +// The basic algorithm described in this note is an exact step +// algorithm that depends on the Newton(LM) step being solved exactly +// in each iteration. When a suitable iterative solver is available to +// solve the Newton(LM) step, the algorithm will automatically switch +// to an inexact step solution method. This trades some slowdown in +// convergence for significant savings in solve time and memory +// usage. Our implementation of the Truncated Newton algorithm follows +// the discussion and recommendataions in "Stephen G. Nash, A Survey +// of Truncated Newton Methods, Journal of Computational and Applied +// Mathematics, 124(1-2), 45-59, 2000. + +#include "ceres/levenberg_marquardt.h" + +#include +#include +#include +#include +#include +#include + +#include +#include "Eigen/Core" +#include "ceres/evaluator.h" +#include "ceres/file.h" +#include "ceres/linear_least_squares_problems.h" +#include "ceres/linear_solver.h" +#include "ceres/matrix_proto.h" +#include "ceres/sparse_matrix.h" +#include "ceres/stringprintf.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { +namespace { + +// Numbers for clamping the size of the LM diagonal. The size of these +// numbers is heuristic. We will probably be adjusting them in the +// future based on more numerical experience. With jacobi scaling +// enabled, these numbers should be all but redundant. +const double kMinLevenbergMarquardtDiagonal = 1e-6; +const double kMaxLevenbergMarquardtDiagonal = 1e32; + +// Small constant for various floating point issues. +const double kEpsilon = 1e-12; + +// Number of times the linear solver should be retried in case of +// numerical failure. The retries are done by exponentially scaling up +// mu at each retry. This leads to stronger and stronger +// regularization making the linear least squares problem better +// conditioned at each retry. +const int kMaxLinearSolverRetries = 5; + +// D = 1/sqrt(diag(J^T * J)) +void EstimateScale(const SparseMatrix& jacobian, double* D) { + CHECK_NOTNULL(D); + jacobian.SquaredColumnNorm(D); + for (int i = 0; i < jacobian.num_cols(); ++i) { + D[i] = 1.0 / (kEpsilon + sqrt(D[i])); + } +} + +// D = diag(J^T * J) +void LevenbergMarquardtDiagonal(const SparseMatrix& jacobian, + double* D) { + CHECK_NOTNULL(D); + jacobian.SquaredColumnNorm(D); + for (int i = 0; i < jacobian.num_cols(); ++i) { + D[i] = min(max(D[i], kMinLevenbergMarquardtDiagonal), + kMaxLevenbergMarquardtDiagonal); + } +} + +bool RunCallback(IterationCallback* callback, + const IterationSummary& iteration_summary, + Solver::Summary* summary) { + const CallbackReturnType status = (*callback)(iteration_summary); + switch (status) { + case SOLVER_TERMINATE_SUCCESSFULLY: + summary->termination_type = USER_SUCCESS; + VLOG(1) << "Terminating on USER_SUCCESS."; + return false; + case SOLVER_ABORT: + summary->termination_type = USER_ABORT; + VLOG(1) << "Terminating on USER_ABORT."; + return false; + case SOLVER_CONTINUE: + return true; + default: + LOG(FATAL) << "Unknown status returned by callback: " + << status; + return NULL; + } +} + +} // namespace + +LevenbergMarquardt::~LevenbergMarquardt() {} + +void LevenbergMarquardt::Minimize(const Minimizer::Options& options, + Evaluator* evaluator, + LinearSolver* linear_solver, + const double* initial_parameters, + double* final_parameters, + Solver::Summary* summary) { + time_t start_time = time(NULL); + const int num_parameters = evaluator->NumParameters(); + const int num_effective_parameters = evaluator->NumEffectiveParameters(); + const int num_residuals = evaluator->NumResiduals(); + + summary->termination_type = NO_CONVERGENCE; + summary->num_successful_steps = 0; + summary->num_unsuccessful_steps = 0; + + // Allocate the various vectors needed by the algorithm. + memcpy(final_parameters, initial_parameters, + num_parameters * sizeof(*initial_parameters)); + + VectorRef x(final_parameters, num_parameters); + Vector x_new(num_parameters); + + Vector lm_step(num_effective_parameters); + Vector gradient(num_effective_parameters); + Vector scaled_gradient(num_effective_parameters); + // Jacobi scaling vector + Vector scale(num_effective_parameters); + + Vector f_model(num_residuals); + Vector f(num_residuals); + Vector f_new(num_residuals); + Vector D(num_parameters); + Vector muD(num_parameters); + + // Ask the Evaluator to create the jacobian matrix. The sparsity + // pattern of this matrix is going to remain constant, so we only do + // this once and then re-use this matrix for all subsequent Jacobian + // computations. + scoped_ptr jacobian(evaluator->CreateJacobian()); + + double x_norm = x.norm(); + + double cost = 0.0; + D.setOnes(); + f.setZero(); + + // Do initial cost and Jacobian evaluation. + if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) { + LOG(WARNING) << "Failed to compute residuals and Jacobian. " + << "Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + if (options.jacobi_scaling) { + EstimateScale(*jacobian, scale.data()); + jacobian->ScaleColumns(scale.data()); + } else { + scale.setOnes(); + } + + // This is a poor way to do this computation. Even if fixed_cost is + // zero, because we are subtracting two possibly large numbers, we + // are depending on exact cancellation to give us a zero here. But + // initial_cost and cost have been computed by two different + // evaluators. One which runs on the whole problem (in + // solver_impl.cc) in single threaded mode and another which runs + // here on the reduced problem, so fixed_cost can (and does) contain + // some numerical garbage with a relative magnitude of 1e-14. + // + // The right way to do this, would be to compute the fixed cost on + // just the set of residual blocks which are held constant and were + // removed from the original problem when the reduced problem was + // constructed. + summary->fixed_cost = summary->initial_cost - cost; + + double model_cost = f.squaredNorm() / 2.0; + double total_cost = summary->fixed_cost + cost; + + scaled_gradient.setZero(); + jacobian->LeftMultiply(f.data(), scaled_gradient.data()); + gradient = scaled_gradient.array() / scale.array(); + + double gradient_max_norm = gradient.lpNorm(); + // We need the max here to guard againt the gradient being zero. + const double gradient_max_norm_0 = max(gradient_max_norm, kEpsilon); + double gradient_tolerance = options.gradient_tolerance * gradient_max_norm_0; + + double mu = options.tau; + double nu = 2.0; + int iteration = 0; + double actual_cost_change = 0.0; + double step_norm = 0.0; + double relative_decrease = 0.0; + + // Insane steps are steps which are not sane, i.e. there is some + // numerical kookiness going on with them. There are various reasons + // for this kookiness, some easier to diagnose then others. From the + // point of view of the non-linear solver, they are steps which + // cannot be used. We return with NUMERICAL_FAILURE after + // kMaxLinearSolverRetries consecutive insane steps. + bool step_is_sane = false; + int num_consecutive_insane_steps = 0; + + // Whether the step resulted in a sufficient decrease in the + // objective function when compared to the decrease in the value of + // the lineariztion. + bool step_is_successful = false; + + // Parse the iterations for which to dump the linear problem. + vector iterations_to_dump = options.lsqp_iterations_to_dump; + sort(iterations_to_dump.begin(), iterations_to_dump.end()); + + IterationSummary iteration_summary; + iteration_summary.iteration = iteration; + iteration_summary.step_is_successful = false; + iteration_summary.cost = total_cost; + iteration_summary.cost_change = actual_cost_change; + iteration_summary.gradient_max_norm = gradient_max_norm; + iteration_summary.step_norm = step_norm; + iteration_summary.relative_decrease = relative_decrease; + iteration_summary.mu = mu; + iteration_summary.eta = options.eta; + iteration_summary.linear_solver_iterations = 0; + iteration_summary.linear_solver_time_sec = 0.0; + iteration_summary.iteration_time_sec = (time(NULL) - start_time); + if (options.logging_type >= PER_MINIMIZER_ITERATION) { + summary->iterations.push_back(iteration_summary); + } + + // Check if the starting point is an optimum. + VLOG(2) << "Gradient max norm: " << gradient_max_norm + << " tolerance: " << gradient_tolerance + << " ratio: " << gradient_max_norm / gradient_max_norm_0 + << " tolerance: " << options.gradient_tolerance; + if (gradient_max_norm <= gradient_tolerance) { + summary->termination_type = GRADIENT_TOLERANCE; + VLOG(1) << "Terminating on GRADIENT_TOLERANCE. " + << "Relative gradient max norm: " + << gradient_max_norm / gradient_max_norm_0 + << " <= " << options.gradient_tolerance; + return; + } + + // Call the various callbacks. + for (int i = 0; i < options.callbacks.size(); ++i) { + if (!RunCallback(options.callbacks[i], iteration_summary, summary)) { + return; + } + } + + // We only need the LM diagonal if we are actually going to do at + // least one iteration of the optimization. So we wait to do it + // until now. + LevenbergMarquardtDiagonal(*jacobian, D.data()); + + while ((iteration < options.max_num_iterations) && + (time(NULL) - start_time) <= options.max_solver_time_sec) { + time_t iteration_start_time = time(NULL); + step_is_sane = false; + step_is_successful = false; + + IterationSummary iteration_summary; + // The while loop here is just to provide an easily breakable + // control structure. We are guaranteed to always exit this loop + // at the end of one iteration or before. + while (1) { + muD = (mu * D).array().sqrt(); + LinearSolver::PerSolveOptions solve_options; + solve_options.D = muD.data(); + solve_options.q_tolerance = options.eta; + // Disable r_tolerance checking. Since we only care about + // termination via the q_tolerance. As Nash and Sofer show, + // r_tolerance based termination is essentially useless in + // Truncated Newton methods. + solve_options.r_tolerance = -1.0; + + const time_t linear_solver_start_time = time(NULL); + LinearSolver::Summary linear_solver_summary = + linear_solver->Solve(jacobian.get(), + f.data(), + solve_options, + lm_step.data()); + iteration_summary.linear_solver_time_sec = + (time(NULL) - linear_solver_start_time); + iteration_summary.linear_solver_iterations = + linear_solver_summary.num_iterations; + + if (binary_search(iterations_to_dump.begin(), + iterations_to_dump.end(), + iteration)) { + CHECK(DumpLinearLeastSquaresProblem(options.lsqp_dump_directory, + iteration, + options.lsqp_dump_format_type, + jacobian.get(), + muD.data(), + f.data(), + lm_step.data(), + options.num_eliminate_blocks)) + << "Tried writing linear least squares problem: " + << options.lsqp_dump_directory + << " but failed."; + } + + // We ignore the case where the linear solver did not converge, + // since the partial solution computed by it still maybe of use, + // and there is no reason to ignore it, especially since we + // spent so much time computing it. + if ((linear_solver_summary.termination_type != TOLERANCE) && + (linear_solver_summary.termination_type != MAX_ITERATIONS)) { + VLOG(1) << "Linear solver failure: retrying with a higher mu"; + break; + } + + step_norm = (lm_step.array() * scale.array()).matrix().norm(); + + // Check step length based convergence. If the step length is + // too small, then we are done. + const double step_size_tolerance = options.parameter_tolerance * + (x_norm + options.parameter_tolerance); + + VLOG(2) << "Step size: " << step_norm + << " tolerance: " << step_size_tolerance + << " ratio: " << step_norm / step_size_tolerance + << " tolerance: " << options.parameter_tolerance; + if (step_norm <= options.parameter_tolerance * + (x_norm + options.parameter_tolerance)) { + summary->termination_type = PARAMETER_TOLERANCE; + VLOG(1) << "Terminating on PARAMETER_TOLERANCE." + << "Relative step size: " << step_norm / step_size_tolerance + << " <= " << options.parameter_tolerance; + return; + } + + Vector delta = -(lm_step.array() * scale.array()).matrix(); + if (!evaluator->Plus(x.data(), delta.data(), x_new.data())) { + LOG(WARNING) << "Failed to compute Plus(x, delta, x_plus_delta). " + << "Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + double cost_new = 0.0; + if (!evaluator->Evaluate(x_new.data(), &cost_new, NULL, NULL)) { + LOG(WARNING) << "Failed to compute the value of the objective " + << "function. Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + f_model.setZero(); + jacobian->RightMultiply(lm_step.data(), f_model.data()); + const double model_cost_new = + (f.segment(0, num_residuals) - f_model).squaredNorm() / 2; + + actual_cost_change = cost - cost_new; + double model_cost_change = model_cost - model_cost_new; + + VLOG(2) << "[Model cost] current: " << model_cost + << " new : " << model_cost_new + << " change: " << model_cost_change; + + VLOG(2) << "[Nonlinear cost] current: " << cost + << " new : " << cost_new + << " change: " << actual_cost_change + << " relative change: " << fabs(actual_cost_change) / cost + << " tolerance: " << options.function_tolerance; + + // In exact arithmetic model_cost_change should never be + // negative. But due to numerical precision issues, we may end up + // with a small negative number. model_cost_change which are + // negative and large in absolute value are indicative of a + // numerical failure in the solver. + if (model_cost_change < -kEpsilon) { + VLOG(1) << "Model cost change is negative.\n" + << "Current : " << model_cost + << " new : " << model_cost_new + << " change: " << model_cost_change << "\n"; + break; + } + + // If we have reached this far, then we are willing to trust the + // numerical quality of the step. + step_is_sane = true; + num_consecutive_insane_steps = 0; + + // Check function value based convergence. + if (fabs(actual_cost_change) < options.function_tolerance * cost) { + VLOG(1) << "Termination on FUNCTION_TOLERANCE." + << " Relative cost change: " << fabs(actual_cost_change) / cost + << " tolerance: " << options.function_tolerance; + summary->termination_type = FUNCTION_TOLERANCE; + return; + } + + // Clamp model_cost_change at kEpsilon from below. + if (model_cost_change < kEpsilon) { + VLOG(1) << "Clamping model cost change " << model_cost_change + << " to " << kEpsilon; + model_cost_change = kEpsilon; + } + + relative_decrease = actual_cost_change / model_cost_change; + VLOG(2) << "actual_cost_change / model_cost_change = " + << relative_decrease; + + if (relative_decrease < options.min_relative_decrease) { + VLOG(2) << "Unsuccessful step."; + break; + } + + VLOG(2) << "Successful step."; + + ++summary->num_successful_steps; + x = x_new; + x_norm = x.norm(); + + if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) { + LOG(WARNING) << "Failed to compute residuals and jacobian. " + << "Terminating."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + if (options.jacobi_scaling) { + jacobian->ScaleColumns(scale.data()); + } + + model_cost = f.squaredNorm() / 2.0; + LevenbergMarquardtDiagonal(*jacobian, D.data()); + scaled_gradient.setZero(); + jacobian->LeftMultiply(f.data(), scaled_gradient.data()); + gradient = scaled_gradient.array() / scale.array(); + gradient_max_norm = gradient.lpNorm(); + + // Check gradient based convergence. + VLOG(2) << "Gradient max norm: " << gradient_max_norm + << " tolerance: " << gradient_tolerance + << " ratio: " << gradient_max_norm / gradient_max_norm_0 + << " tolerance: " << options.gradient_tolerance; + if (gradient_max_norm <= gradient_tolerance) { + summary->termination_type = GRADIENT_TOLERANCE; + VLOG(1) << "Terminating on GRADIENT_TOLERANCE. " + << "Relative gradient max norm: " + << gradient_max_norm / gradient_max_norm_0 + << " <= " << options.gradient_tolerance + << " (tolerance)."; + return; + } + + mu = mu * max(1.0 / 3.0, 1 - pow(2 * relative_decrease - 1, 3)); + nu = 2.0; + step_is_successful = true; + break; + } + + if (!step_is_sane) { + ++num_consecutive_insane_steps; + } + + if (num_consecutive_insane_steps == kMaxLinearSolverRetries) { + summary->termination_type = NUMERICAL_FAILURE; + VLOG(1) << "Too many consecutive retries; ending with numerical fail."; + + if (!options.crash_and_dump_lsqp_on_failure) { + return; + } + + // Dump debugging information to disk. + CHECK(options.lsqp_dump_format_type == TEXTFILE || + options.lsqp_dump_format_type == PROTOBUF) + << "Dumping the linear least squares problem on crash " + << "requires Solver::Options::lsqp_dump_format_type to be " + << "PROTOBUF or TEXTFILE."; + + if (DumpLinearLeastSquaresProblem(options.lsqp_dump_directory, + iteration, + options.lsqp_dump_format_type, + jacobian.get(), + muD.data(), + f.data(), + lm_step.data(), + options.num_eliminate_blocks)) { + LOG(FATAL) << "Linear least squares problem saved to: " + << options.lsqp_dump_directory + << ". Please provide this to the Ceres developers for " + << " debugging along with the v=2 log."; + } else { + LOG(FATAL) << "Tried writing linear least squares problem: " + << options.lsqp_dump_directory + << " but failed."; + } + } + + if (!step_is_successful) { + // Either the step did not lead to a decrease in cost or there + // was numerical failure. In either case we will scale mu up and + // retry. If it was a numerical failure, we hope that the + // stronger regularization will make the linear system better + // conditioned. If it was numerically sane, but there was no + // decrease in cost, then increasing mu reduces the size of the + // trust region and we look for a decrease closer to the + // linearization point. + ++summary->num_unsuccessful_steps; + mu = mu * nu; + nu = 2 * nu; + } + + ++iteration; + + total_cost = summary->fixed_cost + cost; + + iteration_summary.iteration = iteration; + iteration_summary.step_is_successful = step_is_successful; + iteration_summary.cost = total_cost; + iteration_summary.cost_change = actual_cost_change; + iteration_summary.gradient_max_norm = gradient_max_norm; + iteration_summary.step_norm = step_norm; + iteration_summary.relative_decrease = relative_decrease; + iteration_summary.mu = mu; + iteration_summary.eta = options.eta; + iteration_summary.iteration_time_sec = (time(NULL) - iteration_start_time); + + if (options.logging_type >= PER_MINIMIZER_ITERATION) { + summary->iterations.push_back(iteration_summary); + } + + // Call the various callbacks. + for (int i = 0; i < options.callbacks.size(); ++i) { + if (!RunCallback(options.callbacks[i], iteration_summary, summary)) { + return; + } + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h new file mode 100644 index 00000000000..d00bb9095be --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h @@ -0,0 +1,65 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Implmentation of Levenberg Marquardt algorithm based on "Methods for +// Nonlinear Least Squares" by K. Madsen, H.B. Nielsen and +// O. Tingleff. Available to download from +// +// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf +// + +#ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ +#define CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ + +#include "ceres/minimizer.h" +#include "ceres/solver.h" + +namespace ceres { +namespace internal { + +class Evaluator; +class LinearSolver; + +class LevenbergMarquardt : public Minimizer { + public: + virtual ~LevenbergMarquardt(); + + virtual void Minimize(const Minimizer::Options& options, + Evaluator* evaluator, + LinearSolver* linear_solver, + const double* initial_parameters, + double* final_parameters, + Solver::Summary* summary); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc new file mode 100644 index 00000000000..cca9f442fe7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc @@ -0,0 +1,744 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/linear_least_squares_problems.h" + +#include +#include +#include +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/casts.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/file.h" +#include "ceres/matrix_proto.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/stringprintf.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) { + switch (id) { + case 0: + return LinearLeastSquaresProblem0(); + case 1: + return LinearLeastSquaresProblem1(); + case 2: + return LinearLeastSquaresProblem2(); + case 3: + return LinearLeastSquaresProblem3(); + default: + LOG(FATAL) << "Unknown problem id requested " << id; + } + return NULL; +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( + const string& filename) { + LinearLeastSquaresProblemProto problem_proto; + { + string serialized_proto; + ReadFileToStringOrDie(filename, &serialized_proto); + CHECK(problem_proto.ParseFromString(serialized_proto)); + } + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + const SparseMatrixProto& A = problem_proto.a(); + + if (A.has_block_matrix()) { + problem->A.reset(new BlockSparseMatrix(A)); + } else if (A.has_triplet_matrix()) { + problem->A.reset(new TripletSparseMatrix(A)); + } else { + problem->A.reset(new CompressedRowSparseMatrix(A)); + } + + if (problem_proto.b_size() > 0) { + problem->b.reset(new double[problem_proto.b_size()]); + for (int i = 0; i < problem_proto.b_size(); ++i) { + problem->b[i] = problem_proto.b(i); + } + } + + if (problem_proto.d_size() > 0) { + problem->D.reset(new double[problem_proto.d_size()]); + for (int i = 0; i < problem_proto.d_size(); ++i) { + problem->D[i] = problem_proto.d(i); + } + } + + if (problem_proto.d_size() > 0) { + if (problem_proto.x_size() > 0) { + problem->x_D.reset(new double[problem_proto.x_size()]); + for (int i = 0; i < problem_proto.x_size(); ++i) { + problem->x_D[i] = problem_proto.x(i); + } + } + } else { + if (problem_proto.x_size() > 0) { + problem->x.reset(new double[problem_proto.x_size()]); + for (int i = 0; i < problem_proto.x_size(); ++i) { + problem->x[i] = problem_proto.x(i); + } + } + } + + problem->num_eliminate_blocks = 0; + if (problem_proto.has_num_eliminate_blocks()) { + problem->num_eliminate_blocks = problem_proto.num_eliminate_blocks(); + } + + return problem; +} +#else +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( + const string& filename) { + LOG(FATAL) + << "Loading a least squares problem from disk requires " + << "Ceres to be built with Protocol Buffers support."; + return NULL; +} +#endif // CERES_DONT_HAVE_PROTOCOL_BUFFERS + +/* +A = [1 2] + [3 4] + [6 -10] + +b = [ 8 + 18 + -18] + +x = [2 + 3] + +D = [1 + 2] + +x_D = [1.78448275; + 2.82327586;] + */ +LinearLeastSquaresProblem* LinearLeastSquaresProblem0() { + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + + TripletSparseMatrix* A = new TripletSparseMatrix(3, 2, 6); + problem->b.reset(new double[3]); + problem->D.reset(new double[2]); + + problem->x.reset(new double[2]); + problem->x_D.reset(new double[2]); + + int* Ai = A->mutable_rows(); + int* Aj = A->mutable_cols(); + double* Ax = A->mutable_values(); + + int counter = 0; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j< 2; ++j) { + Ai[counter]=i; + Aj[counter]=j; + ++counter; + } + }; + + Ax[0] = 1.; + Ax[1] = 2.; + Ax[2] = 3.; + Ax[3] = 4.; + Ax[4] = 6; + Ax[5] = -10; + A->set_num_nonzeros(6); + problem->A.reset(A); + + problem->b[0] = 8; + problem->b[1] = 18; + problem->b[2] = -18; + + problem->x[0] = 2.0; + problem->x[1] = 3.0; + + problem->D[0] = 1; + problem->D[1] = 2; + + problem->x_D[0] = 1.78448275; + problem->x_D[1] = 2.82327586; + return problem; +} + + +/* + A = [1 0 | 2 0 0 + 3 0 | 0 4 0 + 0 5 | 0 0 6 + 0 7 | 8 0 0 + 0 9 | 1 0 0 + 0 0 | 1 1 1] + + b = [0 + 1 + 2 + 3 + 4 + 5] + + c = A'* b = [ 3 + 67 + 33 + 9 + 17] + + A'A = [10 0 2 12 0 + 0 155 65 0 30 + 2 65 70 1 1 + 12 0 1 17 1 + 0 30 1 1 37] + + S = [ 42.3419 -1.4000 -11.5806 + -1.4000 2.6000 1.0000 + 11.5806 1.0000 31.1935] + + r = [ 4.3032 + 5.4000 + 5.0323] + + S\r = [ 0.2102 + 2.1367 + 0.1388] + + A\b = [-2.3061 + 0.3172 + 0.2102 + 2.1367 + 0.1388] +*/ +// The following two functions create a TripletSparseMatrix and a +// BlockSparseMatrix version of this problem. + +// TripletSparseMatrix version. +LinearLeastSquaresProblem* LinearLeastSquaresProblem1() { + int num_rows = 6; + int num_cols = 5; + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + TripletSparseMatrix* A = new TripletSparseMatrix(num_rows, + num_cols, + num_rows * num_cols); + problem->b.reset(new double[num_rows]); + problem->D.reset(new double[num_cols]); + problem->num_eliminate_blocks = 2; + + int* rows = A->mutable_rows(); + int* cols = A->mutable_cols(); + double* values = A->mutable_values(); + + int nnz = 0; + + // Row 1 + { + rows[nnz] = 0; + cols[nnz] = 0; + values[nnz++] = 1; + + rows[nnz] = 0; + cols[nnz] = 2; + values[nnz++] = 2; + } + + // Row 2 + { + rows[nnz] = 1; + cols[nnz] = 0; + values[nnz++] = 3; + + rows[nnz] = 1; + cols[nnz] = 3; + values[nnz++] = 4; + } + + // Row 3 + { + rows[nnz] = 2; + cols[nnz] = 1; + values[nnz++] = 5; + + rows[nnz] = 2; + cols[nnz] = 4; + values[nnz++] = 6; + } + + // Row 4 + { + rows[nnz] = 3; + cols[nnz] = 1; + values[nnz++] = 7; + + rows[nnz] = 3; + cols[nnz] = 2; + values[nnz++] = 8; + } + + // Row 5 + { + rows[nnz] = 4; + cols[nnz] = 1; + values[nnz++] = 9; + + rows[nnz] = 4; + cols[nnz] = 2; + values[nnz++] = 1; + } + + // Row 6 + { + rows[nnz] = 5; + cols[nnz] = 2; + values[nnz++] = 1; + + rows[nnz] = 5; + cols[nnz] = 3; + values[nnz++] = 1; + + rows[nnz] = 5; + cols[nnz] = 4; + values[nnz++] = 1; + } + + A->set_num_nonzeros(nnz); + CHECK(A->IsValid()); + + problem->A.reset(A); + + for (int i = 0; i < num_cols; ++i) { + problem->D.get()[i] = 1; + } + + for (int i = 0; i < num_rows; ++i) { + problem->b.get()[i] = i; + } + + return problem; +} + +// BlockSparseMatrix version +LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { + int num_rows = 6; + int num_cols = 5; + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + + problem->b.reset(new double[num_rows]); + problem->D.reset(new double[num_cols]); + problem->num_eliminate_blocks = 2; + + CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; + scoped_array values(new double[num_rows * num_cols]); + + for (int c = 0; c < num_cols; ++c) { + bs->cols.push_back(Block()); + bs->cols.back().size = 1; + bs->cols.back().position = c; + } + + int nnz = 0; + + // Row 1 + { + values[nnz++] = 1; + values[nnz++] = 2; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 0; + row.cells.push_back(Cell(0, 0)); + row.cells.push_back(Cell(2, 1)); + } + + // Row 2 + { + values[nnz++] = 3; + values[nnz++] = 4; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 1; + row.cells.push_back(Cell(0, 2)); + row.cells.push_back(Cell(3, 3)); + } + + // Row 3 + { + values[nnz++] = 5; + values[nnz++] = 6; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 2; + row.cells.push_back(Cell(1, 4)); + row.cells.push_back(Cell(4, 5)); + } + + // Row 4 + { + values[nnz++] = 7; + values[nnz++] = 8; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 3; + row.cells.push_back(Cell(1, 6)); + row.cells.push_back(Cell(2, 7)); + } + + // Row 5 + { + values[nnz++] = 9; + values[nnz++] = 1; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 4; + row.cells.push_back(Cell(1, 8)); + row.cells.push_back(Cell(2, 9)); + } + + // Row 6 + { + values[nnz++] = 1; + values[nnz++] = 1; + values[nnz++] = 1; + + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 5; + row.cells.push_back(Cell(2, 10)); + row.cells.push_back(Cell(3, 11)); + row.cells.push_back(Cell(4, 12)); + } + + BlockSparseMatrix* A = new BlockSparseMatrix(bs); + memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); + + for (int i = 0; i < num_cols; ++i) { + problem->D.get()[i] = 1; + } + + for (int i = 0; i < num_rows; ++i) { + problem->b.get()[i] = i; + } + + problem->A.reset(A); + + return problem; +} + + +/* + A = [1 0 + 3 0 + 0 5 + 0 7 + 0 9 + 0 0] + + b = [0 + 1 + 2 + 3 + 4 + 5] +*/ +// BlockSparseMatrix version +LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { + int num_rows = 5; + int num_cols = 2; + + LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + + problem->b.reset(new double[num_rows]); + problem->D.reset(new double[num_cols]); + problem->num_eliminate_blocks = 2; + + CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; + scoped_array values(new double[num_rows * num_cols]); + + for (int c = 0; c < num_cols; ++c) { + bs->cols.push_back(Block()); + bs->cols.back().size = 1; + bs->cols.back().position = c; + } + + int nnz = 0; + + // Row 1 + { + values[nnz++] = 1; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 0; + row.cells.push_back(Cell(0, 0)); + } + + // Row 2 + { + values[nnz++] = 3; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 1; + row.cells.push_back(Cell(0, 1)); + } + + // Row 3 + { + values[nnz++] = 5; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 2; + row.cells.push_back(Cell(1, 2)); + } + + // Row 4 + { + values[nnz++] = 7; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 3; + row.cells.push_back(Cell(1, 3)); + } + + // Row 5 + { + values[nnz++] = 9; + bs->rows.push_back(CompressedRow()); + CompressedRow& row = bs->rows.back(); + row.block.size = 1; + row.block.position = 4; + row.cells.push_back(Cell(1, 4)); + } + + BlockSparseMatrix* A = new BlockSparseMatrix(bs); + memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); + + for (int i = 0; i < num_cols; ++i) { + problem->D.get()[i] = 1; + } + + for (int i = 0; i < num_rows; ++i) { + problem->b.get()[i] = i; + } + + problem->A.reset(A); + + return problem; +} + +bool DumpLinearLeastSquaresProblemToConsole(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + CHECK_NOTNULL(A); + Matrix AA; + A->ToDenseMatrix(&AA); + LOG(INFO) << "A^T: \n" << AA.transpose(); + + if (D != NULL) { + LOG(INFO) << "A's appended diagonal:\n" + << ConstVectorRef(D, A->num_cols()); + } + + if (b != NULL) { + LOG(INFO) << "b: \n" << ConstVectorRef(b, A->num_rows()); + } + + if (x != NULL) { + LOG(INFO) << "x: \n" << ConstVectorRef(x, A->num_cols()); + } + return true; +}; + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + CHECK_NOTNULL(A); + LinearLeastSquaresProblemProto lsqp; + A->ToProto(lsqp.mutable_a()); + + if (D != NULL) { + for (int i = 0; i < A->num_cols(); ++i) { + lsqp.add_d(D[i]); + } + } + + if (b != NULL) { + for (int i = 0; i < A->num_rows(); ++i) { + lsqp.add_b(b[i]); + } + } + + if (x != NULL) { + for (int i = 0; i < A->num_cols(); ++i) { + lsqp.add_x(x[i]); + } + } + + lsqp.set_num_eliminate_blocks(num_eliminate_blocks); + string format_string = JoinPath(directory, + "lm_iteration_%03d.lsqp"); + string filename = + StringPrintf(format_string.c_str(), iteration); + LOG(INFO) << "Dumping least squares problem for iteration " << iteration + << " to disk. File: " << filename; + WriteStringToFileOrDie(lsqp.SerializeAsString(), filename); + return true; +} +#else +bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + LOG(ERROR) << "Dumping least squares problems is only " + << "supported when Ceres is compiled with " + << "protocol buffer support."; + return false; +} +#endif + +void WriteArrayToFileOrDie(const string& filename, + const double* x, + const int size) { + CHECK_NOTNULL(x); + VLOG(2) << "Writing array to: " << filename; + FILE* fptr = fopen(filename.c_str(), "w"); + CHECK_NOTNULL(fptr); + for (int i = 0; i < size; ++i) { + fprintf(fptr, "%17f\n", x[i]); + } + fclose(fptr); +} + +bool DumpLinearLeastSquaresProblemToTextFile(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + CHECK_NOTNULL(A); + string format_string = JoinPath(directory, + "lm_iteration_%03d"); + string filename_prefix = + StringPrintf(format_string.c_str(), iteration); + + { + string filename = filename_prefix + "_A.txt"; + LOG(INFO) << "writing to: " << filename; + FILE* fptr = fopen(filename.c_str(), "w"); + CHECK_NOTNULL(fptr); + A->ToTextFile(fptr); + fclose(fptr); + } + + if (D != NULL) { + string filename = filename_prefix + "_D.txt"; + WriteArrayToFileOrDie(filename, D, A->num_cols()); + } + + if (b != NULL) { + string filename = filename_prefix + "_b.txt"; + WriteArrayToFileOrDie(filename, b, A->num_rows()); + } + + if (x != NULL) { + string filename = filename_prefix + "_x.txt"; + WriteArrayToFileOrDie(filename, x, A->num_cols()); + } + + return true; +} + +bool DumpLinearLeastSquaresProblem(const string& directory, + int iteration, + DumpFormatType dump_format_type, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { + switch (dump_format_type) { + case (CONSOLE): + return DumpLinearLeastSquaresProblemToConsole(directory, + iteration, + A, D, b, x, + num_eliminate_blocks); + case (PROTOBUF): + return DumpLinearLeastSquaresProblemToProtocolBuffer( + directory, + iteration, + A, D, b, x, + num_eliminate_blocks); + case (TEXTFILE): + return DumpLinearLeastSquaresProblemToTextFile(directory, + iteration, + A, D, b, x, + num_eliminate_blocks); + default: + LOG(FATAL) << "Unknown DumpFormatType " << dump_format_type; + }; + + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h new file mode 100644 index 00000000000..553cc0d3db3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h @@ -0,0 +1,87 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ +#define CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ + +#include +#include +#include "ceres/sparse_matrix.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// Structure defining a linear least squares problem and if possible +// ground truth solutions. To be used by various LinearSolver tests. +struct LinearLeastSquaresProblem { + LinearLeastSquaresProblem() + : A(NULL), b(NULL), D(NULL), num_eliminate_blocks(0), + x(NULL), x_D(NULL) { + } + + scoped_ptr A; + scoped_array b; + scoped_array D; + // If using the schur eliminator then how many of the variable + // blocks are e_type blocks. + int num_eliminate_blocks; + + // Solution to min_x |Ax - b|^2 + scoped_array x; + // Solution to min_x |Ax - b|^2 + |Dx|^2 + scoped_array x_D; +}; + +// Factories for linear least squares problem. +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id); +LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( + const string& filename); + +LinearLeastSquaresProblem* LinearLeastSquaresProblem0(); +LinearLeastSquaresProblem* LinearLeastSquaresProblem1(); +LinearLeastSquaresProblem* LinearLeastSquaresProblem2(); +LinearLeastSquaresProblem* LinearLeastSquaresProblem3(); + +// Write the linear least squares problem to disk. The exact format +// depends on dump_format_type. +bool DumpLinearLeastSquaresProblem(const string& directory, + int iteration, + DumpFormatType dump_format_type, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks); +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc new file mode 100644 index 00000000000..4b59fa13009 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.cc @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/linear_operator.h" + +namespace ceres { +namespace internal { + +LinearOperator::~LinearOperator() { +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_operator.h b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.h new file mode 100644 index 00000000000..d5c15cee6a9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_operator.h @@ -0,0 +1,59 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Base classes for access to an linear operator. + +#ifndef CERES_INTERNAL_LINEAR_OPERATOR_H_ +#define CERES_INTERNAL_LINEAR_OPERATOR_H_ + +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// This is an abstract base class for linear operators. It supports +// access to size information and left and right multiply operators. +class LinearOperator { + public: + virtual ~LinearOperator(); + + // y = y + Ax; + virtual void RightMultiply(const double* x, double* y) const = 0; + // y = y + A'x; + virtual void LeftMultiply(const double* x, double* y) const = 0; + + virtual int num_rows() const = 0; + virtual int num_cols() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINEAR_OPERATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc new file mode 100644 index 00000000000..b2e3941eea1 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc @@ -0,0 +1,87 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/linear_solver.h" + +#include +#include "ceres/cgnr_solver.h" +#include "ceres/dense_qr_solver.h" +#include "ceres/iterative_schur_complement_solver.h" +#include "ceres/schur_complement_solver.h" +#include "ceres/sparse_normal_cholesky_solver.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +LinearSolver::~LinearSolver() { +} + +LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { + switch (options.type) { + case CGNR: + return new CgnrSolver(options); + + case SPARSE_NORMAL_CHOLESKY: +#ifndef CERES_NO_SUITESPARSE + return new SparseNormalCholeskySolver(options); +#else + LOG(WARNING) << "SPARSE_NORMAL_CHOLESKY is not available. Please " + << "build Ceres with SuiteSparse. Returning NULL."; + return NULL; +#endif // CERES_NO_SUITESPARSE + + case SPARSE_SCHUR: +#ifndef CERES_NO_SUITESPARSE + return new SparseSchurComplementSolver(options); +#else + LOG(WARNING) << "SPARSE_SCHUR is not available. Please " + << "build Ceres with SuiteSparse. Returning NULL."; + return NULL; +#endif // CERES_NO_SUITESPARSE + + case DENSE_SCHUR: + return new DenseSchurComplementSolver(options); + + case ITERATIVE_SCHUR: + return new IterativeSchurComplementSolver(options); + + case DENSE_QR: + return new DenseQRSolver(options); + + default: + LOG(FATAL) << "Unknown linear solver type :" + << options.type; + return NULL; // MSVC doesn't understand that LOG(FATAL) never returns. + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h new file mode 100644 index 00000000000..5860ecc8a77 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h @@ -0,0 +1,291 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Abstract interface for objects solving linear systems of various +// kinds. + +#ifndef CERES_INTERNAL_LINEAR_SOLVER_H_ +#define CERES_INTERNAL_LINEAR_SOLVER_H_ + +#include + +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/casts.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/dense_sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class LinearOperator; + +// Abstract base class for objects that implement algorithms for +// solving linear systems +// +// Ax = b +// +// It is expected that a single instance of a LinearSolver object +// maybe used multiple times for solving different linear +// systems. This allows them to cache and reuse information across +// solves if for example the sparsity of the linear system remains +// constant. +// +// Subclasses of LinearSolver use two structs to configure themselves. +// The Options struct configures the LinearSolver object for its +// lifetime. The PerSolveOptions struct is used to specify options for +// a particular Solve call. +class LinearSolver { + public: + struct Options { + Options() + : type(SPARSE_NORMAL_CHOLESKY), + preconditioner_type(JACOBI), + min_num_iterations(1), + max_num_iterations(1), + num_threads(1), + constant_sparsity(false), + num_eliminate_blocks(0), + residual_reset_period(10), + row_block_size(Dynamic), + e_block_size(Dynamic), + f_block_size(Dynamic) { + } + + LinearSolverType type; + + PreconditionerType preconditioner_type; + + // Number of internal iterations that the solver uses. This + // parameter only makes sense for iterative solvers like CG. + int min_num_iterations; + int max_num_iterations; + + // If possible, how many threads can the solver use. + int num_threads; + + // If possible cache and reuse the symbolic factorization across + // multiple calls. + bool constant_sparsity; + + // Eliminate 0 to num_eliminate_blocks - 1 from the Normal + // equations to form a schur complement. Only used by the Schur + // complement based solver. The most common use for this parameter + // is in the case of structure from motion problems where we have + // camera blocks and point blocks. Then setting the + // num_eliminate_blocks to the number of points allows the solver + // to use the Schur complement trick. For more details see the + // description of this parameter in solver.h. + int num_eliminate_blocks; + + // Iterative solvers, e.g. Preconditioned Conjugate Gradients + // maintain a cheap estimate of the residual which may become + // inaccurate over time. Thus for non-zero values of this + // parameter, the solver can be told to recalculate the value of + // the residual using a |b - Ax| evaluation. + int residual_reset_period; + + // If the block sizes in a BlockSparseMatrix are fixed, then in + // some cases the Schur complement based solvers can detect and + // specialize on them. + // + // It is expected that these parameters are set programmatically + // rather than manually. + // + // Please see explicit_schur_complement_solver_impl.h for more + // details. + int row_block_size; + int e_block_size; + int f_block_size; + }; + + // Options for the Solve method. + struct PerSolveOptions { + PerSolveOptions() + : D(NULL), + preconditioner(NULL), + r_tolerance(0.0), + q_tolerance(0.0) { + } + + // This option only makes sense for unsymmetric linear solvers + // that can solve rectangular linear systems. + // + // Given a matrix A, an optional diagonal matrix D as a vector, + // and a vector b, the linear solver will solve for + // + // | A | x = | b | + // | D | | 0 | + // + // If D is null, then it is treated as zero, and the solver returns + // the solution to + // + // A x = b + // + // In either case, x is the vector that solves the following + // optimization problem. + // + // arg min_x ||Ax - b||^2 + ||Dx||^2 + // + // Here A is a matrix of size m x n, with full column rank. If A + // does not have full column rank, the results returned by the + // solver cannot be relied on. D, if it is not null is an array of + // size n. b is an array of size m and x is an array of size n. + double * D; + + // This option only makes sense for iterative solvers. + // + // In general the performance of an iterative linear solver + // depends on the condition number of the matrix A. For example + // the convergence rate of the conjugate gradients algorithm + // is proportional to the square root of the condition number. + // + // One particularly useful technique for improving the + // conditioning of a linear system is to precondition it. In its + // simplest form a preconditioner is a matrix M such that instead + // of solving Ax = b, we solve the linear system AM^{-1} y = b + // instead, where M is such that the condition number k(AM^{-1}) + // is smaller than the conditioner k(A). Given the solution to + // this system, x = M^{-1} y. The iterative solver takes care of + // the mechanics of solving the preconditioned system and + // returning the corrected solution x. The user only needs to + // supply a linear operator. + // + // A null preconditioner is equivalent to an identity matrix being + // used a preconditioner. + LinearOperator* preconditioner; + + + // The following tolerance related options only makes sense for + // iterative solvers. Direct solvers ignore them. + + // Solver terminates when + // + // |Ax - b| <= r_tolerance * |b|. + // + // This is the most commonly used termination criterion for + // iterative solvers. + double r_tolerance; + + // For PSD matrices A, let + // + // Q(x) = x'Ax - 2b'x + // + // be the cost of the quadratic function defined by A and b. Then, + // the solver terminates at iteration i if + // + // i * (Q(x_i) - Q(x_i-1)) / Q(x_i) < q_tolerance. + // + // This termination criterion is more useful when using CG to + // solve the Newton step. This particular convergence test comes + // from Stephen Nash's work on truncated Newton + // methods. References: + // + // 1. Stephen G. Nash & Ariela Sofer, Assessing A Search + // Direction Within A Truncated Newton Method, Operation + // Research Letters 9(1990) 219-221. + // + // 2. Stephen G. Nash, A Survey of Truncated Newton Methods, + // Journal of Computational and Applied Mathematics, + // 124(1-2), 45-59, 2000. + // + double q_tolerance; + }; + + // Summary of a call to the Solve method. We should move away from + // the true/false method for determining solver success. We should + // let the summary object do the talking. + struct Summary { + Summary() + : residual_norm(0.0), + num_iterations(-1), + termination_type(FAILURE) { + } + + double residual_norm; + int num_iterations; + LinearSolverTerminationType termination_type; + }; + + virtual ~LinearSolver(); + + // Solve Ax = b. + virtual Summary Solve(LinearOperator* A, + const double* b, + const PerSolveOptions& per_solve_options, + double* x) = 0; + + static LinearSolver* Create(const Options& options); +}; + +// This templated subclass of LinearSolver serves as a base class for +// other linear solvers that depend on the particular matrix layout of +// the underlying linear operator. For example some linear solvers +// need low level access to the TripletSparseMatrix implementing the +// LinearOperator interface. This class hides those implementation +// details behind a private virtual method, and has the Solve method +// perform the necessary upcasting. +template +class TypedLinearSolver : public LinearSolver { + public: + virtual ~TypedLinearSolver() {} + virtual LinearSolver::Summary Solve( + LinearOperator* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(b); + CHECK_NOTNULL(x); + return SolveImpl(down_cast(A), b, per_solve_options, x); + } + + private: + virtual LinearSolver::Summary SolveImpl( + MatrixType* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) = 0; +}; + +// Linear solvers that depend on acccess to the low level structure of +// a SparseMatrix. +typedef TypedLinearSolver BlockSparseMatrixSolver; // NOLINT +typedef TypedLinearSolver BlockSparseMatrixBaseSolver; // NOLINT +typedef TypedLinearSolver CompressedRowSparseMatrixSolver; // NOLINT +typedef TypedLinearSolver DenseSparseMatrixSolver; // NOLINT +typedef TypedLinearSolver TripletSparseMatrixSolver; // NOLINT + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINEAR_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc new file mode 100644 index 00000000000..eeae74e3f95 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc @@ -0,0 +1,140 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include "ceres/internal/eigen.h" +#include "ceres/local_parameterization.h" +#include "ceres/rotation.h" + +namespace ceres { + +IdentityParameterization::IdentityParameterization(const int size) + : size_(size) { + CHECK_GT(size, 0); +} + +bool IdentityParameterization::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + VectorRef(x_plus_delta, size_) = + ConstVectorRef(x, size_) + ConstVectorRef(delta, size_); + return true; +} + +bool IdentityParameterization::ComputeJacobian(const double* x, + double* jacobian) const { + MatrixRef(jacobian, size_, size_) = Matrix::Identity(size_, size_); + return true; +} + +SubsetParameterization::SubsetParameterization( + int size, + const vector& constant_parameters) + : local_size_(size - constant_parameters.size()), + constancy_mask_(size, 0) { + CHECK_GT(constant_parameters.size(), 0) + << "The set of constant parameters should contain at least " + << "one element. If you do not wish to hold any parameters " + << "constant, then do not use a SubsetParameterization"; + + vector constant = constant_parameters; + sort(constant.begin(), constant.end()); + CHECK(unique(constant.begin(), constant.end()) == constant.end()) + << "The set of constant parameters cannot contain duplicates"; + CHECK_LT(constant_parameters.size(), size) + << "Number of parameters held constant should be less " + << "than the size of the parameter block. If you wish " + << "to hold the entire parameter block constant, then a " + << "efficient way is to directly mark it as constant " + << "instead of using a LocalParameterization to do so."; + CHECK_GE(*min_element(constant.begin(), constant.end()), 0); + CHECK_LT(*max_element(constant.begin(), constant.end()), size); + + for (int i = 0; i < constant_parameters.size(); ++i) { + constancy_mask_[constant_parameters[i]] = 1; + } +} + +bool SubsetParameterization::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) { + if (constancy_mask_[i]) { + x_plus_delta[i] = x[i]; + } else { + x_plus_delta[i] = x[i] + delta[j++]; + } + } + return true; +} + +bool SubsetParameterization::ComputeJacobian(const double* x, + double* jacobian) const { + MatrixRef m(jacobian, constancy_mask_.size(), local_size_); + m.setZero(); + for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) { + if (!constancy_mask_[i]) { + m(i, j++) = 1.0; + } + } + return true; +} + +bool QuaternionParameterization::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + const double norm_delta = + sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]); + if (norm_delta > 0.0) { + const double sin_delta_by_delta = (sin(norm_delta) / norm_delta); + double q_delta[4]; + q_delta[0] = cos(norm_delta); + q_delta[1] = sin_delta_by_delta * delta[0]; + q_delta[2] = sin_delta_by_delta * delta[1]; + q_delta[3] = sin_delta_by_delta * delta[2]; + QuaternionProduct(q_delta, x, x_plus_delta); + } else { + for (int i = 0; i < 4; ++i) { + x_plus_delta[i] = x[i]; + } + } + return true; +} + +bool QuaternionParameterization::ComputeJacobian(const double* x, + double* jacobian) const { + jacobian[0] = -x[1]; jacobian[1] = -x[2]; jacobian[2] = -x[3]; // NOLINT + jacobian[3] = x[0]; jacobian[4] = x[3]; jacobian[5] = -x[2]; // NOLINT + jacobian[6] = -x[3]; jacobian[7] = x[0]; jacobian[8] = x[1]; // NOLINT + jacobian[9] = x[2]; jacobian[10] = -x[1]; jacobian[11] = x[0]; // NOLINT + return true; +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc new file mode 100644 index 00000000000..00b2b184729 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc @@ -0,0 +1,93 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Purpose: See .h file. + +#include "ceres/loss_function.h" + +#include +#include + +namespace ceres { + +void TrivialLoss::Evaluate(double s, double rho[3]) const { + rho[0] = s; + rho[1] = 1; + rho[2] = 0; +} + +void HuberLoss::Evaluate(double s, double rho[3]) const { + if (s > b_) { + // Outlier region. + // 'r' is always positive. + const double r = sqrt(s); + rho[0] = 2 * a_ * r - b_; + rho[1] = a_ / r; + rho[2] = - rho[1] / (2 * s); + } else { + // Inlier region. + rho[0] = s; + rho[1] = 1; + rho[2] = 0; + } +} + +void SoftLOneLoss::Evaluate(double s, double rho[3]) const { + const double sum = 1 + s * c_; + const double tmp = sqrt(sum); + // 'sum' and 'tmp' are always positive, assuming that 's' is. + rho[0] = 2 * b_ * (tmp - 1); + rho[1] = 1 / tmp; + rho[2] = - (c_ * rho[1]) / (2 * sum); +} + +void CauchyLoss::Evaluate(double s, double rho[3]) const { + const double sum = 1 + s * c_; + const double inv = 1 / sum; + // 'sum' and 'inv' are always positive, assuming that 's' is. + rho[0] = b_ * log(sum); + rho[1] = inv; + rho[2] = - c_ * (inv * inv); +} + +void ScaledLoss::Evaluate(double s, double rho[3]) const { + if (rho_.get() == NULL) { + rho[0] = a_ * s; + rho[1] = a_; + rho[2] = 0.0; + } else { + rho_->Evaluate(s, rho); + rho[0] *= a_; + rho[1] *= a_; + rho[2] *= a_; + } +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/map_util.h b/extern/libmv/third_party/ceres/internal/ceres/map_util.h new file mode 100644 index 00000000000..ddf1252f674 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/map_util.h @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Originally by Anton Carver + +#ifndef CERES_INTERNAL_MAP_UTIL_H_ +#define CERES_INTERNAL_MAP_UTIL_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// Perform a lookup in a map or hash_map, assuming that the key exists. +// Crash if it does not. +// +// This is intended as a replacement for operator[] as an rvalue (for reading) +// when the key is guaranteed to exist. +// +// operator[] is discouraged for several reasons: +// * It has a side-effect of inserting missing keys +// * It is not thread-safe (even when it is not inserting, it can still +// choose to resize the underlying storage) +// * It invalidates iterators (when it chooses to resize) +// * It default constructs a value object even if it doesn't need to +// +// This version assumes the key is printable, and includes it in the fatal log +// message. +template +const typename Collection::value_type::second_type& +FindOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Perform a lookup in a map or hash_map. +// If the key is present in the map then the value associated with that +// key is returned, otherwise the value passed as a default is returned. +template +const typename Collection::value_type::second_type& +FindWithDefault(const Collection& collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return value; + } + return it->second; +} + +// Insert a new key and value into a map or hash_map. +// If the key is not present in the map the key and value are +// inserted, otherwise nothing happens. True indicates that an insert +// took place, false indicates the key was already present. +template +bool InsertIfNotPresent( + Collection * const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + pair ret = + collection->insert(typename Collection::value_type(key, value)); + return ret.second; +} + +// Perform a lookup in a map or hash_map. +// Same as above but the returned pointer is not const and can be used to change +// the stored value. +template +typename Collection::value_type::second_type* +FindOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Test to see if a set, map, hash_set or hash_map contains a particular key. +// Returns true if the key is in the collection. +template +bool ContainsKey(const Collection& collection, const Key& key) { + typename Collection::const_iterator it = collection.find(key); + return it != collection.end(); +} + +// Inserts a new key/value into a map or hash_map. +// Dies if the key is already present. +template +void InsertOrDie(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + typedef typename Collection::value_type value_type; + CHECK(collection->insert(value_type(key, data)).second) + << "duplicate key: " << key; +} + +} // namespace ceres + +#endif // CERES_INTERNAL_MAP_UTIL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h new file mode 100644 index 00000000000..b8a3a1a6de6 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A portability header to make optional protocol buffer support less intrusive. + +#ifndef CERES_INTERNAL_MATRIX_PROTO_H_ +#define CERES_INTERNAL_MATRIX_PROTO_H_ + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#include "ceres/matrix.pb.h" +#endif + +#endif // CERES_INTERNAL_MATRIX_PROTO_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h new file mode 100644 index 00000000000..77cb00cb6b4 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h @@ -0,0 +1,104 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_MINIMIZER_H_ +#define CERES_INTERNAL_MINIMIZER_H_ + +#include +#include "ceres/solver.h" +#include "ceres/iteration_callback.h" + +namespace ceres { +namespace internal { + +class Evaluator; +class LinearSolver; + +// Interface for non-linear least squares solvers. +class Minimizer { + public: + // Options struct to control the behaviour of the Minimizer. Please + // see solver.h for detailed information about the meaning and + // default values of each of these parameters. + struct Options { + explicit Options(const Solver::Options& options) { + max_num_iterations = options.max_num_iterations; + max_solver_time_sec = options.max_solver_time_sec; + gradient_tolerance = options.gradient_tolerance; + parameter_tolerance = options.parameter_tolerance; + function_tolerance = options.function_tolerance; + min_relative_decrease = options.min_relative_decrease; + eta = options.eta; + tau = options.tau; + jacobi_scaling = options.jacobi_scaling; + crash_and_dump_lsqp_on_failure = options.crash_and_dump_lsqp_on_failure; + lsqp_dump_directory = options.lsqp_dump_directory; + lsqp_iterations_to_dump = options.lsqp_iterations_to_dump; + lsqp_dump_format_type = options.lsqp_dump_format_type; + num_eliminate_blocks = options.num_eliminate_blocks; + logging_type = options.logging_type; + } + + int max_num_iterations; + int max_solver_time_sec; + double gradient_tolerance; + double parameter_tolerance; + double function_tolerance; + double min_relative_decrease; + double eta; + double tau; + bool jacobi_scaling; + bool crash_and_dump_lsqp_on_failure; + vector lsqp_iterations_to_dump; + DumpFormatType lsqp_dump_format_type; + string lsqp_dump_directory; + int num_eliminate_blocks; + LoggingType logging_type; + + // List of callbacks that are executed by the Minimizer at the end + // of each iteration. + // + // Client owns these pointers. + vector callbacks; + }; + + virtual ~Minimizer() {} + virtual void Minimize(const Options& options, + Evaluator* evaluator, + LinearSolver* linear_solver, + const double* initial_parameters, + double* final_parameters, + Solver::Summary* summary) = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_MINIMIZER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/mutex.h b/extern/libmv/third_party/ceres/internal/ceres/mutex.h new file mode 100644 index 00000000000..6514b107041 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/mutex.h @@ -0,0 +1,312 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: Craig Silverstein. +// +// A simple mutex wrapper, supporting locks and read-write locks. +// You should assume the locks are *not* re-entrant. +// +// This class is meant to be internal-only and should be wrapped by an +// internal namespace. Before you use this module, please give the +// name of your internal namespace for this module. Or, if you want +// to expose it, you'll want to move it to the Google namespace. We +// cannot put this class in global namespace because there can be some +// problems when we have multiple versions of Mutex in each shared object. +// +// NOTE: by default, we have #ifdef'ed out the TryLock() method. +// This is for two reasons: +// 1) TryLock() under Windows is a bit annoying (it requires a +// #define to be defined very early). +// 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG +// mode. +// If you need TryLock(), and either these two caveats are not a +// problem for you, or you're willing to work around them, then +// feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs +// in the code below. +// +// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy: +// http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html +// Because of that, we might as well use windows locks for +// cygwin. They seem to be more reliable than the cygwin pthreads layer. +// +// TRICKY IMPLEMENTATION NOTE: +// This class is designed to be safe to use during +// dynamic-initialization -- that is, by global constructors that are +// run before main() starts. The issue in this case is that +// dynamic-initialization happens in an unpredictable order, and it +// could be that someone else's dynamic initializer could call a +// function that tries to acquire this mutex -- but that all happens +// before this mutex's constructor has run. (This can happen even if +// the mutex and the function that uses the mutex are in the same .cc +// file.) Basically, because Mutex does non-trivial work in its +// constructor, it's not, in the naive implementation, safe to use +// before dynamic initialization has run on it. +// +// The solution used here is to pair the actual mutex primitive with a +// bool that is set to true when the mutex is dynamically initialized. +// (Before that it's false.) Then we modify all mutex routines to +// look at the bool, and not try to lock/unlock until the bool makes +// it to true (which happens after the Mutex constructor has run.) +// +// This works because before main() starts -- particularly, during +// dynamic initialization -- there are no threads, so a) it's ok that +// the mutex operations are a no-op, since we don't need locking then +// anyway; and b) we can be quite confident our bool won't change +// state between a call to Lock() and a call to Unlock() (that would +// require a global constructor in one translation unit to call Lock() +// and another global constructor in another translation unit to call +// Unlock() later, which is pretty perverse). +// +// That said, it's tricky, and can conceivably fail; it's safest to +// avoid trying to acquire a mutex in a global constructor, if you +// can. One way it can fail is that a really smart compiler might +// initialize the bool to true at static-initialization time (too +// early) rather than at dynamic-initialization time. To discourage +// that, we set is_safe_ to true in code (not the constructor +// colon-initializer) and set it to true via a function that always +// evaluates to true, but that the compiler can't know always +// evaluates to true. This should be good enough. + +#ifndef CERES_INTERNAL_MUTEX_H_ +#define CERES_INTERNAL_MUTEX_H_ + +#if defined(NO_THREADS) + typedef int MutexType; // to keep a lock-count +#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__) +# define WIN32_LEAN_AND_MEAN // We only need minimal includes +# ifdef GMUTEX_TRYLOCK + // We need Windows NT or later for TryEnterCriticalSection(). If you + // don't need that functionality, you can remove these _WIN32_WINNT + // lines, and change TryLock() to assert(0) or something. +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +# endif +# endif +// To avoid macro definition of ERROR. +# define NOGDI +// To avoid macro definition of min/max. +# define NOMINMAX +# include + typedef CRITICAL_SECTION MutexType; +#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK) + // Needed for pthread_rwlock_*. If it causes problems, you could take it + // out, but then you'd have to unset CERES_HAVE_RWLOCK (at least on linux -- + // it *does* cause problems for FreeBSD, or MacOSX, but isn't needed for + // locking there.) +# if defined(__linux__) && !defined(_XOPEN_SOURCE) +# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls +# endif +# include + typedef pthread_rwlock_t MutexType; +#elif defined(CERES_HAVE_PTHREAD) +# include + typedef pthread_mutex_t MutexType; +#else +# error Need to implement mutex.h for your architecture, or #define NO_THREADS +#endif + +// We need to include these header files after defining _XOPEN_SOURCE +// as they may define the _XOPEN_SOURCE macro. +#include +#include // for abort() + +namespace ceres { +namespace internal { + +class Mutex { + public: + // Create a Mutex that is not held by anybody. This constructor is + // typically used for Mutexes allocated on the heap or the stack. + // See below for a recommendation for constructing global Mutex + // objects. + inline Mutex(); + + // Destructor + inline ~Mutex(); + + inline void Lock(); // Block if needed until free then acquire exclusively + inline void Unlock(); // Release a lock acquired via Lock() +#ifdef GMUTEX_TRYLOCK + inline bool TryLock(); // If free, Lock() and return true, else return false +#endif + // Note that on systems that don't support read-write locks, these may + // be implemented as synonyms to Lock() and Unlock(). So you can use + // these for efficiency, but don't use them anyplace where being able + // to do shared reads is necessary to avoid deadlock. + inline void ReaderLock(); // Block until free or shared then acquire a share + inline void ReaderUnlock(); // Release a read share of this Mutex + inline void WriterLock() { Lock(); } // Acquire an exclusive lock + inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() + + // TODO(hamaji): Do nothing, implement correctly. + inline void AssertHeld() {} + + private: + MutexType mutex_; + // We want to make sure that the compiler sets is_safe_ to true only + // when we tell it to, and never makes assumptions is_safe_ is + // always true. volatile is the most reliable way to do that. + volatile bool is_safe_; + + inline void SetIsSafe() { is_safe_ = true; } + + // Catch the error of writing Mutex when intending MutexLock. + Mutex(Mutex* /*ignored*/) {} + // Disallow "evil" constructors + Mutex(const Mutex&); + void operator=(const Mutex&); +}; + +// Now the implementation of Mutex for various systems +#if defined(NO_THREADS) + +// When we don't have threads, we can be either reading or writing, +// but not both. We can have lots of readers at once (in no-threads +// mode, that's most likely to happen in recursive function calls), +// but only one writer. We represent this by having mutex_ be -1 when +// writing and a number > 0 when reading (and 0 when no lock is held). +// +// In debug mode, we assert these invariants, while in non-debug mode +// we do nothing, for efficiency. That's why everything is in an +// assert. + +Mutex::Mutex() : mutex_(0) { } +Mutex::~Mutex() { assert(mutex_ == 0); } +void Mutex::Lock() { assert(--mutex_ == -1); } +void Mutex::Unlock() { assert(mutex_++ == -1); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } +#endif +void Mutex::ReaderLock() { assert(++mutex_ > 0); } +void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } + +#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__) + +Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); } +Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } +void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); } +void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { return is_safe_ ? + TryEnterCriticalSection(&mutex_) != 0 : true; } +#endif +void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks +void Mutex::ReaderUnlock() { Unlock(); } + +#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK) + +#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +} while (0) + +Mutex::Mutex() { + SetIsSafe(); + if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); +} +Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); } +void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } +void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { return is_safe_ ? + pthread_rwlock_trywrlock(&mutex_) == 0 : + true; } +#endif +void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } +void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } +#undef SAFE_PTHREAD + +#elif defined(CERES_HAVE_PTHREAD) + +#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +} while (0) + +Mutex::Mutex() { + SetIsSafe(); + if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); +} +Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } +void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } +void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } +#ifdef GMUTEX_TRYLOCK +bool Mutex::TryLock() { return is_safe_ ? + pthread_mutex_trylock(&mutex_) == 0 : true; } +#endif +void Mutex::ReaderLock() { Lock(); } +void Mutex::ReaderUnlock() { Unlock(); } +#undef SAFE_PTHREAD + +#endif + +// -------------------------------------------------------------------------- +// Some helper classes + +// MutexLock(mu) acquires mu when constructed and releases it when destroyed. +class MutexLock { + public: + explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } + ~MutexLock() { mu_->Unlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + MutexLock(const MutexLock&); + void operator=(const MutexLock&); +}; + +// ReaderMutexLock and WriterMutexLock do the same, for rwlocks +class ReaderMutexLock { + public: + explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } + ~ReaderMutexLock() { mu_->ReaderUnlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + ReaderMutexLock(const ReaderMutexLock&); + void operator=(const ReaderMutexLock&); +}; + +class WriterMutexLock { + public: + explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } + ~WriterMutexLock() { mu_->WriterUnlock(); } + private: + Mutex * const mu_; + // Disallow "evil" constructors + WriterMutexLock(const WriterMutexLock&); + void operator=(const WriterMutexLock&); +}; + +// Catch bug where variable name is omitted, e.g. MutexLock (&mu); +#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) +#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) +#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_MUTEX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc new file mode 100644 index 00000000000..f30bbc8b46b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc @@ -0,0 +1,67 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/normal_prior.h" + +#include +#include + +#include +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +NormalPrior::NormalPrior(const Matrix& A, const Vector& b) + : A_(A), b_(b) { + CHECK_GT(b_.rows(), 0); + CHECK_GT(A_.rows(), 0); + CHECK_EQ(b_.rows(), A.cols()); + set_num_residuals(A_.rows()); + mutable_parameter_block_sizes()->push_back(b_.rows()); +} + +bool NormalPrior::Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + ConstVectorRef p(parameters[0], parameter_block_sizes()[0]); + VectorRef r(residuals, num_residuals()); + // The following line should read + // r = A_ * (p - b_); + // The extra eval is to get around a bug in the eigen library. + r = A_ * (p - b_).eval(); + if ((jacobians != NULL) && (jacobians[0] != NULL)) { + MatrixRef(jacobians[0], num_residuals(), parameter_block_sizes()[0]) = A_; + } + return true; +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h new file mode 100644 index 00000000000..4bac1a85828 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h @@ -0,0 +1,256 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_PARAMETER_BLOCK_H_ +#define CERES_INTERNAL_PARAMETER_BLOCK_H_ + +#include +#include "ceres/integral_types.h" +#include +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/local_parameterization.h" +#include "ceres/residual_block_utils.h" + +namespace ceres { +namespace internal { + +class ProblemImpl; + +// The parameter block encodes the location of the user's original value, and +// also the "current state" of the parameter. The evaluator uses whatever is in +// the current state of the parameter when evaluating. This is inlined since the +// methods are performance sensitive. +// +// The class is not thread-safe, unless only const methods are called. The +// parameter block may also hold a pointer to a local parameterization; the +// parameter block does not take ownership of this pointer, so the user is +// responsible for the proper disposal of the local parameterization. +class ParameterBlock { + public: + ParameterBlock(double* user_state, int size) { + Init(user_state, size, NULL); + } + ParameterBlock(double* user_state, + int size, + LocalParameterization* local_parameterization) { + Init(user_state, size, local_parameterization); + } + + // The size of the parameter block. + int Size() const { return size_; } + + // Manipulate the parameter state. + bool SetState(const double* x) { + CHECK(x != NULL) + << "Tried to set the state of constant parameter " + << "with user location " << user_state_; + CHECK(!is_constant_) + << "Tried to set the state of constant parameter " + << "with user location " << user_state_; + + state_ = x; + return UpdateLocalParameterizationJacobian(); + } + + // Copy the current parameter state out to x. This is "GetState()" rather than + // simply "state()" since it is actively copying the data into the passed + // pointer. + void GetState(double *x) const { + if (x != state_) { + memcpy(x, state_, sizeof(*state_) * size_); + } + } + + // Direct pointers to the current state. + const double* state() const { return state_; } + const double* user_state() const { return user_state_; } + double* mutable_user_state() { return user_state_; } + LocalParameterization* local_parameterization() const { + return local_parameterization_; + } + LocalParameterization* mutable_local_parameterization() { + return local_parameterization_; + } + + // Set this parameter block to vary or not. + void SetConstant() { is_constant_ = true; } + void SetVarying() { is_constant_ = false; } + bool IsConstant() const { return is_constant_; } + + // This parameter block's index in an array. + int index() const { return index_; } + void set_index(int index) { index_ = index; } + + // This parameter offset inside a larger state vector. + int state_offset() const { return state_offset_; } + void set_state_offset(int state_offset) { state_offset_ = state_offset; } + + // This parameter offset inside a larger delta vector. + int delta_offset() const { return delta_offset_; } + void set_delta_offset(int delta_offset) { delta_offset_ = delta_offset; } + + // Methods relating to the parameter block's parameterization. + + // The local to global jacobian. Returns NULL if there is no local + // parameterization for this parameter block. The returned matrix is row-major + // and has Size() rows and LocalSize() columns. + const double* LocalParameterizationJacobian() const { + return local_parameterization_jacobian_.get(); + } + + int LocalSize() const { + return (local_parameterization_ == NULL) + ? size_ + : local_parameterization_->LocalSize(); + } + + // Set the parameterization. The parameterization can be set exactly once; + // multiple calls to set the parameterization to different values will crash. + // It is an error to pass NULL for the parameterization. The parameter block + // does not take ownership of the parameterization. + void SetParameterization(LocalParameterization* new_parameterization) { + CHECK(new_parameterization != NULL) << "NULL parameterization invalid."; + CHECK(new_parameterization->GlobalSize() == size_) + << "Invalid parameterization for parameter block. The parameter block " + << "has size " << size_ << " while the parameterization has a global " + << "size of " << new_parameterization->GlobalSize() << ". Did you " + << "accidentally use the wrong parameter block or parameterization?"; + if (new_parameterization != local_parameterization_) { + CHECK(local_parameterization_ == NULL) + << "Can't re-set the local parameterization; it leads to " + << "ambiguous ownership."; + local_parameterization_ = new_parameterization; + local_parameterization_jacobian_.reset( + new double[local_parameterization_->GlobalSize() * + local_parameterization_->LocalSize()]); + CHECK(UpdateLocalParameterizationJacobian()) + "Local parameterization Jacobian computation failed" + "for x: " << ConstVectorRef(state_, Size()).transpose(); + } else { + // Ignore the case that the parameterizations match. + } + } + + // Generalization of the addition operation. This is the same as + // LocalParameterization::Plus() but uses the parameter's current state + // instead of operating on a passed in pointer. + bool Plus(const double *x, const double* delta, double* x_plus_delta) { + if (local_parameterization_ == NULL) { + VectorRef(x_plus_delta, size_) = ConstVectorRef(x, size_) + + ConstVectorRef(delta, size_); + return true; + } + return local_parameterization_->Plus(x, delta, x_plus_delta); + } + + private: + void Init(double* user_state, + int size, + LocalParameterization* local_parameterization) { + user_state_ = user_state; + size_ = size; + is_constant_ = false; + state_ = user_state_; + + local_parameterization_ = NULL; + if (local_parameterization != NULL) { + SetParameterization(local_parameterization); + } + + index_ = -1; + state_offset_ = -1; + delta_offset_ = -1; + } + + bool UpdateLocalParameterizationJacobian() { + if (local_parameterization_ == NULL) { + return true; + } + + // Update the local to global Jacobian. In some cases this is + // wasted effort; if this is a bottleneck, we will find a solution + // at that time. + + const int jacobian_size = Size() * LocalSize(); + InvalidateArray(jacobian_size, + local_parameterization_jacobian_.get()); + if (!local_parameterization_->ComputeJacobian( + state_, + local_parameterization_jacobian_.get())) { + LOG(WARNING) << "Local parameterization Jacobian computation failed" + "for x: " << ConstVectorRef(state_, Size()).transpose(); + return false; + } + + if (!IsArrayValid(jacobian_size, local_parameterization_jacobian_.get())) { + LOG(WARNING) << "Local parameterization Jacobian computation returned" + << "an invalid matrix for x: " + << ConstVectorRef(state_, Size()).transpose() + << "\n Jacobian matrix : " + << ConstMatrixRef(local_parameterization_jacobian_.get(), + Size(), + LocalSize()); + return false; + } + return true; + } + + double* user_state_; + int size_; + bool is_constant_; + LocalParameterization* local_parameterization_; + + // The "state" of the parameter. These fields are only needed while the + // solver is running. While at first glance using mutable is a bad idea, this + // ends up simplifying the internals of Ceres enough to justify the potential + // pitfalls of using "mutable." + mutable const double* state_; + mutable scoped_array local_parameterization_jacobian_; + + // The index of the parameter. This is used by various other parts of Ceres to + // permit switching from a ParameterBlock* to an index in another array. + int32 index_; + + // The offset of this parameter block inside a larger state vector. + int32 state_offset_; + + // The offset of this parameter block inside a larger delta vector. + int32 delta_offset_; + + // Necessary so ProblemImpl can clean up the parameterizations. + friend class ProblemImpl; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PARAMETER_BLOCK_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc new file mode 100644 index 00000000000..fcf8fd53aed --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc @@ -0,0 +1,315 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 10 + +#include "ceres/partitioned_matrix_view.h" + +#include +#include +#include +#include +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +PartitionedMatrixView::PartitionedMatrixView( + const BlockSparseMatrixBase& matrix, + int num_col_blocks_a) + : matrix_(matrix), + num_col_blocks_e_(num_col_blocks_a) { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + CHECK_NOTNULL(bs); + + num_col_blocks_f_ = bs->cols.size() - num_col_blocks_a; + + // Compute the number of row blocks in E. The number of row blocks + // in E maybe less than the number of row blocks in the input matrix + // as some of the row blocks at the bottom may not have any + // e_blocks. For a definition of what an e_block is, please see + // explicit_schur_complement_solver.h + num_row_blocks_e_ = 0; + for (int r = 0; r < bs->rows.size(); ++r) { + const vector& cells = bs->rows[r].cells; + if (cells[0].block_id < num_col_blocks_a) { + ++num_row_blocks_e_; + } + } + + // Compute the number of columns in E and F. + num_cols_e_ = 0; + num_cols_f_ = 0; + + for (int c = 0; c < bs->cols.size(); ++c) { + const Block& block = bs->cols[c]; + if (c < num_col_blocks_a) { + num_cols_e_ += block.size; + } else { + num_cols_f_ += block.size; + } + } + + CHECK_EQ(num_cols_e_ + num_cols_f_, matrix_.num_cols()); +} + +PartitionedMatrixView::~PartitionedMatrixView() { +} + +// The next four methods don't seem to be particularly cache +// friendly. This is an artifact of how the BlockStructure of the +// input matrix is constructed. These methods will benefit from +// multithreading as well as improved data layout. + +void PartitionedMatrixView::RightMultiplyE(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over the first num_row_blocks_e_ row blocks, and multiply + // by the first cell in each row block. + for (int r = 0; r < num_row_blocks_e_; ++r) { + const double* row_values = matrix_.RowBlockValues(r); + const Cell& cell = bs->rows[r].cells[0]; + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + const int col_block_id = cell.block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + ConstVectorRef xref(x + col_block_pos, col_block_size); + VectorRef yref(y + row_block_pos, row_block_size); + ConstMatrixRef m(row_values + cell.position, + row_block_size, + col_block_size); + yref += m.lazyProduct(xref); + } +} + +void PartitionedMatrixView::RightMultiplyF(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over row blocks, and if the row block is in E, then + // multiply by all the cells except the first one which is of type + // E. If the row block is not in E (i.e its in the bottom + // num_row_blocks - num_row_blocks_e row blocks), then all the cells + // are of type F and multiply by them all. + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + VectorRef yref(y + row_block_pos, row_block_size); + const vector& cells = bs->rows[r].cells; + for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) { + const double* row_values = matrix_.RowBlockValues(r); + const int col_block_id = cells[c].block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + ConstVectorRef xref(x + col_block_pos - num_cols_e(), + col_block_size); + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + yref += m.lazyProduct(xref); + } + } +} + +void PartitionedMatrixView::LeftMultiplyE(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over the first num_row_blocks_e_ row blocks, and multiply + // by the first cell in each row block. + for (int r = 0; r < num_row_blocks_e_; ++r) { + const Cell& cell = bs->rows[r].cells[0]; + const double* row_values = matrix_.RowBlockValues(r); + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + const int col_block_id = cell.block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + ConstVectorRef xref(x + row_block_pos, row_block_size); + VectorRef yref(y + col_block_pos, col_block_size); + ConstMatrixRef m(row_values + cell.position, + row_block_size, + col_block_size); + yref += m.transpose().lazyProduct(xref); + } +} + +void PartitionedMatrixView::LeftMultiplyF(const double* x, double* y) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + + // Iterate over row blocks, and if the row block is in E, then + // multiply by all the cells except the first one which is of type + // E. If the row block is not in E (i.e its in the bottom + // num_row_blocks - num_row_blocks_e row blocks), then all the cells + // are of type F and multiply by them all. + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_pos = bs->rows[r].block.position; + const int row_block_size = bs->rows[r].block.size; + ConstVectorRef xref(x + row_block_pos, row_block_size); + const vector& cells = bs->rows[r].cells; + for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) { + const double* row_values = matrix_.RowBlockValues(r); + const int col_block_id = cells[c].block_id; + const int col_block_pos = bs->cols[col_block_id].position; + const int col_block_size = bs->cols[col_block_id].size; + + VectorRef yref(y + col_block_pos - num_cols_e(), col_block_size); + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + yref += m.transpose().lazyProduct(xref); + } + } +} + +// Given a range of columns blocks of a matrix m, compute the block +// structure of the block diagonal of the matrix m(:, +// start_col_block:end_col_block)'m(:, start_col_block:end_col_block) +// and return a BlockSparseMatrix with the this block structure. The +// caller owns the result. +BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalMatrixLayout( + int start_col_block, int end_col_block) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + CompressedRowBlockStructure* block_diagonal_structure = + new CompressedRowBlockStructure; + + int block_position = 0; + int diagonal_cell_position = 0; + + // Iterate over the column blocks, creating a new diagonal block for + // each column block. + for (int c = start_col_block; c < end_col_block; ++c) { + const Block& block = bs->cols[c]; + block_diagonal_structure->cols.push_back(Block()); + Block& diagonal_block = block_diagonal_structure->cols.back(); + diagonal_block.size = block.size; + diagonal_block.position = block_position; + + block_diagonal_structure->rows.push_back(CompressedRow()); + CompressedRow& row = block_diagonal_structure->rows.back(); + row.block = diagonal_block; + + row.cells.push_back(Cell()); + Cell& cell = row.cells.back(); + cell.block_id = c - start_col_block; + cell.position = diagonal_cell_position; + + block_position += block.size; + diagonal_cell_position += block.size * block.size; + } + + // Build a BlockSparseMatrix with the just computed block + // structure. + return new BlockSparseMatrix(block_diagonal_structure); +} + +BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalEtE() const { + BlockSparseMatrix* block_diagonal = + CreateBlockDiagonalMatrixLayout(0, num_col_blocks_e_); + UpdateBlockDiagonalEtE(block_diagonal); + return block_diagonal; +} + +BlockSparseMatrix* PartitionedMatrixView::CreateBlockDiagonalFtF() const { + BlockSparseMatrix* block_diagonal = + CreateBlockDiagonalMatrixLayout( + num_col_blocks_e_, num_col_blocks_e_ + num_col_blocks_f_); + UpdateBlockDiagonalFtF(block_diagonal); + return block_diagonal; +} + +// Similar to the code in RightMultiplyE, except instead of the matrix +// vector multiply its an outer product. +// +// block_diagonal = block_diagonal(E'E) +void PartitionedMatrixView::UpdateBlockDiagonalEtE( + BlockSparseMatrix* block_diagonal) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + const CompressedRowBlockStructure* block_diagonal_structure = + block_diagonal->block_structure(); + + block_diagonal->SetZero(); + + for (int r = 0; r < num_row_blocks_e_ ; ++r) { + const double* row_values = matrix_.RowBlockValues(r); + const Cell& cell = bs->rows[r].cells[0]; + const int row_block_size = bs->rows[r].block.size; + const int block_id = cell.block_id; + const int col_block_size = bs->cols[block_id].size; + ConstMatrixRef m(row_values + cell.position, + row_block_size, + col_block_size); + + const int cell_position = + block_diagonal_structure->rows[block_id].cells[0].position; + + MatrixRef(block_diagonal->mutable_values() + cell_position, + col_block_size, col_block_size).noalias() += m.transpose() * m; + } +} + +// Similar to the code in RightMultiplyF, except instead of the matrix +// vector multiply its an outer product. +// +// block_diagonal = block_diagonal(F'F) +// +void PartitionedMatrixView::UpdateBlockDiagonalFtF( + BlockSparseMatrix* block_diagonal) const { + const CompressedRowBlockStructure* bs = matrix_.block_structure(); + const CompressedRowBlockStructure* block_diagonal_structure = + block_diagonal->block_structure(); + + block_diagonal->SetZero(); + for (int r = 0; r < bs->rows.size(); ++r) { + const int row_block_size = bs->rows[r].block.size; + const vector& cells = bs->rows[r].cells; + const double* row_values = matrix_.RowBlockValues(r); + for (int c = (r < num_row_blocks_e_) ? 1 : 0; c < cells.size(); ++c) { + const int col_block_id = cells[c].block_id; + const int col_block_size = bs->cols[col_block_id].size; + ConstMatrixRef m(row_values + cells[c].position, + row_block_size, + col_block_size); + const int diagonal_block_id = col_block_id - num_col_blocks_e_; + const int cell_position = + block_diagonal_structure->rows[diagonal_block_id].cells[0].position; + + MatrixRef(block_diagonal->mutable_values() + cell_position, + col_block_size, col_block_size).noalias() += m.transpose() * m; + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h new file mode 100644 index 00000000000..cfe4de5b436 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.h @@ -0,0 +1,121 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// For generalized bi-partite Jacobian matrices that arise in +// Structure from Motion related problems, it is sometimes useful to +// have access to the two parts of the matrix as linear operators +// themselves. This class provides that functionality. + +#ifndef CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ +#define CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ + +#include "ceres/block_sparse_matrix.h" + +namespace ceres { +namespace internal { + +// Given generalized bi-partite matrix A = [E F], with the same block +// structure as required by the Schur complement based solver, found +// in explicit_schur_complement_solver.h, provide access to the +// matrices E and F and their outer products E'E and F'F with +// themselves. +// +// Lack of BlockStructure object will result in a crash and if the +// block structure of the matrix does not satisfy the requirements of +// the Schur complement solver it will result in unpredictable and +// wrong output. +// +// This class lives in the internal name space as its a utility class +// to be used by the IterativeSchurComplementSolver class, found in +// iterative_schur_complement_solver.h, and is not meant for general +// consumption. +class PartitionedMatrixView { + public: + // matrix = [E F], where the matrix E contains the first + // num_col_blocks_a column blocks. + PartitionedMatrixView(const BlockSparseMatrixBase& matrix, + int num_col_blocks_a); + ~PartitionedMatrixView(); + + // y += E'x + void LeftMultiplyE(const double* x, double* y) const; + + // y += F'x + void LeftMultiplyF(const double* x, double* y) const; + + // y += Ex + void RightMultiplyE(const double* x, double* y) const; + + // y += Fx + void RightMultiplyF(const double* x, double* y) const; + + // Create and return the block diagonal of the matrix E'E. + BlockSparseMatrix* CreateBlockDiagonalEtE() const; + + // Create and return the block diagonal of the matrix F'F. + BlockSparseMatrix* CreateBlockDiagonalFtF() const; + + // Compute the block diagonal of the matrix E'E and store it in + // block_diagonal. The matrix block_diagonal is expected to have a + // BlockStructure (preferably created using + // CreateBlockDiagonalMatrixEtE) which is has the same structure as + // the block diagonal of E'E. + void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const; + + // Compute the block diagonal of the matrix F'F and store it in + // block_diagonal. The matrix block_diagonal is expected to have a + // BlockStructure (preferably created using + // CreateBlockDiagonalMatrixFtF) which is has the same structure as + // the block diagonal of F'F. + void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const; + + int num_col_blocks_e() const { return num_col_blocks_e_; } + int num_col_blocks_f() const { return num_col_blocks_f_; } + int num_cols_e() const { return num_cols_e_; } + int num_cols_f() const { return num_cols_f_; } + int num_rows() const { return matrix_.num_rows(); } + int num_cols() const { return matrix_.num_cols(); } + + private: + BlockSparseMatrix* CreateBlockDiagonalMatrixLayout(int start_col_block, + int end_col_block) const; + + const BlockSparseMatrixBase& matrix_; + int num_row_blocks_e_; + int num_col_blocks_e_; + int num_col_blocks_f_; + int num_cols_e_; + int num_cols_f_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem.cc b/extern/libmv/third_party/ceres/internal/ceres/problem.cc new file mode 100644 index 00000000000..b8c25d9db84 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/problem.cc @@ -0,0 +1,149 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) + +#include "ceres/problem.h" + +#include +#include "ceres/problem_impl.h" + +namespace ceres { + +class ResidualBlock; + +Problem::Problem() : problem_impl_(new internal::ProblemImpl) {} +Problem::Problem(const Problem::Options& options) + : problem_impl_(new internal::ProblemImpl(options)) {} +Problem::~Problem() {} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + parameter_blocks); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2, x3); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2, x3, x4); +} + +ResidualBlockId Problem::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4, double* x5) { + return problem_impl_->AddResidualBlock(cost_function, + loss_function, + x0, x1, x2, x3, x4, x5); +} + +void Problem::AddParameterBlock(double* values, int size) { + problem_impl_->AddParameterBlock(values, size); +} + +void Problem::AddParameterBlock(double* values, + int size, + LocalParameterization* local_parameterization) { + problem_impl_->AddParameterBlock(values, size, local_parameterization); +} + +void Problem::SetParameterBlockConstant(double* values) { + problem_impl_->SetParameterBlockConstant(values); +} + +void Problem::SetParameterBlockVariable(double* values) { + problem_impl_->SetParameterBlockVariable(values); +} + +void Problem::SetParameterization( + double* values, + LocalParameterization* local_parameterization) { + problem_impl_->SetParameterization(values, local_parameterization); +} + +int Problem::NumParameterBlocks() const { + return problem_impl_->NumParameterBlocks(); +} + +int Problem::NumParameters() const { + return problem_impl_->NumParameters(); +} + +int Problem::NumResidualBlocks() const { + return problem_impl_->NumResidualBlocks(); +} + +int Problem::NumResiduals() const { + return problem_impl_->NumResiduals(); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc new file mode 100644 index 00000000000..68242477d6f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc @@ -0,0 +1,359 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) + +#include "ceres/problem_impl.h" + +#include +#include +#include +#include +#include +#include + +#include +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/stl_util.h" +#include "ceres/map_util.h" +#include "ceres/stringprintf.h" +#include "ceres/cost_function.h" +#include "ceres/loss_function.h" + +namespace ceres { +namespace internal { + +typedef map ParameterMap; + +// Returns true if two regions of memory, a and b, with sizes size_a and size_b +// respectively, overlap. +static bool RegionsAlias(const double* a, int size_a, + const double* b, int size_b) { + return (a < b) ? b < (a + size_a) + : a < (b + size_b); +} + +static void CheckForNoAliasing(double* existing_block, + int existing_block_size, + double* new_block, + int new_block_size) { + CHECK(!RegionsAlias(existing_block, existing_block_size, + new_block, new_block_size)) + << "Aliasing detected between existing parameter block at memory " + << "location " << existing_block + << " and has size " << existing_block_size << " with new parameter " + << "block that has memory adderss " << new_block << " and would have " + << "size " << new_block_size << "."; +} + +static ParameterBlock* InternalAddParameterBlock( + double* values, + int size, + ParameterMap* parameter_map, + vector* parameter_blocks) { + CHECK(values) << "Null pointer passed to AddParameterBlock for a parameter " + << "with size " << size; + + // Ignore the request if there is a block for the given pointer already. + ParameterMap::iterator it = parameter_map->find(values); + if (it != parameter_map->end()) { + int existing_size = it->second->Size(); + CHECK(size == existing_size) + << "Tried adding a parameter block with the same double pointer, " + << values << ", twice, but with different block sizes. Original " + << "size was " << existing_size << " but new size is " + << size; + return it->second; + } + // Before adding the parameter block, also check that it doesn't alias any + // other parameter blocks. + if (!parameter_map->empty()) { + ParameterMap::iterator lb = parameter_map->lower_bound(values); + + // If lb is not the first block, check the previous block for aliasing. + if (lb != parameter_map->begin()) { + ParameterMap::iterator previous = lb; + --previous; + CheckForNoAliasing(previous->first, + previous->second->Size(), + values, + size); + } + + // If lb is not off the end, check lb for aliasing. + if (lb != parameter_map->end()) { + CheckForNoAliasing(lb->first, + lb->second->Size(), + values, + size); + } + } + ParameterBlock* new_parameter_block = new ParameterBlock(values, size); + (*parameter_map)[values] = new_parameter_block; + parameter_blocks->push_back(new_parameter_block); + return new_parameter_block; +} + +ProblemImpl::ProblemImpl() : program_(new internal::Program) {} +ProblemImpl::ProblemImpl(const Problem::Options& options) + : options_(options), + program_(new internal::Program) {} + +ProblemImpl::~ProblemImpl() { + // Collect the unique cost/loss functions and delete the residuals. + set cost_functions; + set loss_functions; + for (int i = 0; i < program_->residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = program_->residual_blocks_[i]; + + // The const casts here are legit, since ResidualBlock holds these + // pointers as const pointers but we have ownership of them and + // have the right to destroy them when the destructor is called. + if (options_.cost_function_ownership == TAKE_OWNERSHIP) { + cost_functions.insert( + const_cast(residual_block->cost_function())); + } + if (options_.loss_function_ownership == TAKE_OWNERSHIP) { + loss_functions.insert( + const_cast(residual_block->loss_function())); + } + + delete residual_block; + } + + // Collect the unique parameterizations and delete the parameters. + set local_parameterizations; + for (int i = 0; i < program_->parameter_blocks_.size(); ++i) { + ParameterBlock* parameter_block = program_->parameter_blocks_[i]; + + if (options_.local_parameterization_ownership == TAKE_OWNERSHIP) { + local_parameterizations.insert(parameter_block->local_parameterization_); + } + + delete parameter_block; + } + + // Delete the owned cost/loss functions and parameterizations. + STLDeleteContainerPointers(local_parameterizations.begin(), + local_parameterizations.end()); + STLDeleteContainerPointers(cost_functions.begin(), + cost_functions.end()); + STLDeleteContainerPointers(loss_functions.begin(), + loss_functions.end()); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks) { + CHECK_NOTNULL(cost_function); + CHECK_EQ(parameter_blocks.size(), + cost_function->parameter_block_sizes().size()); + + // Check the sizes match. + const vector& parameter_block_sizes = + cost_function->parameter_block_sizes(); + CHECK_EQ(parameter_block_sizes.size(), parameter_blocks.size()) + << "Number of blocks input is different than the number of blocks " + << "that the cost function expects."; + + // Check for duplicate parameter blocks. + vector sorted_parameter_blocks(parameter_blocks); + sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end()); + vector::const_iterator duplicate_items = + unique(sorted_parameter_blocks.begin(), + sorted_parameter_blocks.end()); + if (duplicate_items != sorted_parameter_blocks.end()) { + string blocks; + for (int i = 0; i < parameter_blocks.size(); ++i) { + blocks += internal::StringPrintf(" %p ", parameter_blocks[i]); + } + + LOG(FATAL) << "Duplicate parameter blocks in a residual parameter " + << "are not allowed. Parameter block pointers: [" + << blocks << "]"; + } + + // Add parameter blocks and convert the double*'s to parameter blocks. + vector parameter_block_ptrs(parameter_blocks.size()); + for (int i = 0; i < parameter_blocks.size(); ++i) { + parameter_block_ptrs[i] = + InternalAddParameterBlock(parameter_blocks[i], + parameter_block_sizes[i], + ¶meter_block_map_, + &program_->parameter_blocks_); + } + + // Check that the block sizes match the block sizes expected by the + // cost_function. + for (int i = 0; i < parameter_block_ptrs.size(); ++i) { + CHECK_EQ(cost_function->parameter_block_sizes()[i], + parameter_block_ptrs[i]->Size()) + << "The cost function expects parameter block " << i + << " of size " << cost_function->parameter_block_sizes()[i] + << " but was given a block of size " + << parameter_block_ptrs[i]->Size(); + } + + ResidualBlock* new_residual_block = + new ResidualBlock(cost_function, + loss_function, + parameter_block_ptrs); + program_->residual_blocks_.push_back(new_residual_block); + return new_residual_block; +} + +// Unfortunately, macros don't help much to reduce this code, and var args don't +// work because of the ambiguous case that there is no loss function. +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0) { + vector residual_parameters; + residual_parameters.push_back(x0); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + residual_parameters.push_back(x3); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + residual_parameters.push_back(x3); + residual_parameters.push_back(x4); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + +const ResidualBlock* ProblemImpl::AddResidualBlock( + CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, double* x3, double* x4, double* x5) { + vector residual_parameters; + residual_parameters.push_back(x0); + residual_parameters.push_back(x1); + residual_parameters.push_back(x2); + residual_parameters.push_back(x3); + residual_parameters.push_back(x4); + residual_parameters.push_back(x5); + return AddResidualBlock(cost_function, loss_function, residual_parameters); +} + + +void ProblemImpl::AddParameterBlock(double* values, int size) { + InternalAddParameterBlock(values, + size, + ¶meter_block_map_, + &program_->parameter_blocks_); +} + +void ProblemImpl::AddParameterBlock( + double* values, + int size, + LocalParameterization* local_parameterization) { + ParameterBlock* parameter_block = + InternalAddParameterBlock(values, + size, + ¶meter_block_map_, + &program_->parameter_blocks_); + if (local_parameterization != NULL) { + parameter_block->SetParameterization(local_parameterization); + } +} + +void ProblemImpl::SetParameterBlockConstant(double* values) { + FindOrDie(parameter_block_map_, values)->SetConstant(); +} + +void ProblemImpl::SetParameterBlockVariable(double* values) { + FindOrDie(parameter_block_map_, values)->SetVarying(); +} + +void ProblemImpl::SetParameterization( + double* values, + LocalParameterization* local_parameterization) { + FindOrDie(parameter_block_map_, values) + ->SetParameterization(local_parameterization); +} + +int ProblemImpl::NumParameterBlocks() const { + return program_->NumParameterBlocks(); +} + +int ProblemImpl::NumParameters() const { + return program_->NumParameters(); +} + +int ProblemImpl::NumResidualBlocks() const { + return program_->NumResidualBlocks(); +} + +int ProblemImpl::NumResiduals() const { + return program_->NumResiduals(); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h new file mode 100644 index 00000000000..523860e652a --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// This is the implementation of the public Problem API. The pointer to +// implementation (PIMPL) idiom makes it possible for Ceres internal code to +// refer to the private data members without needing to exposing it to the +// world. An alternative to PIMPL is to have a factory which returns instances +// of a virtual base class; while that approach would work, it requires clients +// to always put a Problem object into a scoped pointer; this needlessly muddies +// client code for little benefit. Therefore, the PIMPL comprise was chosen. + +#ifndef CERES_PUBLIC_PROBLEM_IMPL_H_ +#define CERES_PUBLIC_PROBLEM_IMPL_H_ + +#include +#include + +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/problem.h" +#include "ceres/types.h" + +namespace ceres { + +class CostFunction; +class LossFunction; +class LocalParameterization; + +namespace internal { + +class Program; +class ResidualBlock; + +class ProblemImpl { + public: + typedef map ParameterMap; + + ProblemImpl(); + explicit ProblemImpl(const Problem::Options& options); + + ~ProblemImpl(); + + // See the public problem.h file for description of these methods. + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + const vector& parameter_blocks); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4); + ResidualBlockId AddResidualBlock(CostFunction* cost_function, + LossFunction* loss_function, + double* x0, double* x1, double* x2, + double* x3, double* x4, double* x5); + void AddParameterBlock(double* values, int size); + void AddParameterBlock(double* values, + int size, + LocalParameterization* local_parameterization); + void SetParameterBlockConstant(double* values); + void SetParameterBlockVariable(double* values); + void SetParameterization(double* values, + LocalParameterization* local_parameterization); + int NumParameterBlocks() const; + int NumParameters() const; + int NumResidualBlocks() const; + int NumResiduals() const; + + const Program& program() const { return *program_; } + Program* mutable_program() { return program_.get(); } + + const ParameterMap& parameter_map() const { return parameter_block_map_; } + + private: + const Problem::Options options_; + + // The mapping from user pointers to parameter blocks. + map parameter_block_map_; + + internal::scoped_ptr program_; + DISALLOW_COPY_AND_ASSIGN(ProblemImpl); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_PUBLIC_PROBLEM_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.cc b/extern/libmv/third_party/ceres/internal/ceres/program.cc new file mode 100644 index 00000000000..444b1020253 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/program.cc @@ -0,0 +1,233 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/program.h" + +#include +#include +#include "ceres/parameter_block.h" +#include "ceres/residual_block.h" +#include "ceres/stl_util.h" +#include "ceres/map_util.h" +#include "ceres/problem.h" +#include "ceres/cost_function.h" +#include "ceres/loss_function.h" +#include "ceres/local_parameterization.h" + +namespace ceres { +namespace internal { + +Program::Program() {} + +Program::Program(const Program& program) + : parameter_blocks_(program.parameter_blocks_), + residual_blocks_(program.residual_blocks_) { +} + +const vector& Program::parameter_blocks() const { + return parameter_blocks_; +} + +const vector& Program::residual_blocks() const { + return residual_blocks_; +} + +vector* Program::mutable_parameter_blocks() { + return ¶meter_blocks_; +} + +vector* Program::mutable_residual_blocks() { + return &residual_blocks_; +} + +bool Program::StateVectorToParameterBlocks(const double *state) { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + if (!parameter_blocks_[i]->SetState(state)) { + return false; + } + state += parameter_blocks_[i]->Size(); + } + return true; +} + +void Program::ParameterBlocksToStateVector(double *state) const { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->GetState(state); + state += parameter_blocks_[i]->Size(); + } +} + +void Program::CopyParameterBlockStateToUserState() { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->GetState( + parameter_blocks_[i]->mutable_user_state()); + } +} + +bool Program::Plus(const double* state, + const double* delta, + double* state_plus_delta) const { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + if (!parameter_blocks_[i]->Plus(state, delta, state_plus_delta)) { + return false; + } + state += parameter_blocks_[i]->Size(); + delta += parameter_blocks_[i]->LocalSize(); + state_plus_delta += parameter_blocks_[i]->Size(); + } + return true; +} + +void Program::SetParameterOffsetsAndIndex() { + // Set positions for all parameters appearing as arguments to residuals to one + // past the end of the parameter block array. + for (int i = 0; i < residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = residual_blocks_[i]; + for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) { + residual_block->parameter_blocks()[j]->set_index(-1); + } + } + // For parameters that appear in the program, set their position and offset. + int state_offset = 0; + int delta_offset = 0; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->set_index(i); + parameter_blocks_[i]->set_state_offset(state_offset); + parameter_blocks_[i]->set_delta_offset(delta_offset); + state_offset += parameter_blocks_[i]->Size(); + delta_offset += parameter_blocks_[i]->LocalSize(); + } +} + +int Program::NumResidualBlocks() const { + return residual_blocks_.size(); +} + +int Program::NumParameterBlocks() const { + return parameter_blocks_.size(); +} + +int Program::NumResiduals() const { + int num_residuals = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + num_residuals += residual_blocks_[i]->NumResiduals(); + } + return num_residuals; +} + +int Program::NumParameters() const { + int num_parameters = 0; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + num_parameters += parameter_blocks_[i]->Size(); + } + return num_parameters; +} + +int Program::NumEffectiveParameters() const { + int num_parameters = 0; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + num_parameters += parameter_blocks_[i]->LocalSize(); + } + return num_parameters; +} + +int Program::MaxScratchDoublesNeededForEvaluate() const { + // Compute the scratch space needed for evaluate. + int max_scratch_bytes_for_evaluate = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + max_scratch_bytes_for_evaluate = + max(max_scratch_bytes_for_evaluate, + residual_blocks_[i]->NumScratchDoublesForEvaluate()); + } + return max_scratch_bytes_for_evaluate; +} + +int Program::MaxDerivativesPerResidualBlock() const { + int max_derivatives = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + int derivatives = 0; + ResidualBlock* residual_block = residual_blocks_[i]; + int num_parameters = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameters; ++j) { + derivatives += residual_block->NumResiduals() * + residual_block->parameter_blocks()[j]->LocalSize(); + } + max_derivatives = max(max_derivatives, derivatives); + } + return max_derivatives; +} + +int Program::MaxParametersPerResidualBlock() const { + int max_parameters = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + max_parameters = max(max_parameters, + residual_blocks_[i]->NumParameterBlocks()); + } + return max_parameters; +} + +bool Program::Evaluate(double* cost, double* residuals) { + *cost = 0.0; + + // Scratch space is only needed if residuals is NULL. + scoped_array scratch; + if (residuals == NULL) { + scratch.reset(new double[MaxScratchDoublesNeededForEvaluate()]); + } else { + // TODO(keir): Is this needed? Check by removing the equivalent statement in + // dense_evaluator.cc and running the tests. + VectorRef(residuals, NumResiduals()).setZero(); + } + + for (int i = 0; i < residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = residual_blocks_[i]; + + // Evaluate the cost function for this residual. + double residual_cost; + if (!residual_block->Evaluate(&residual_cost, + residuals, + NULL, // No jacobian. + scratch.get())) { + return false; + } + + // Accumulate residual cost into the total cost. + *cost += residual_cost; + + // Update the residuals cursor. + if (residuals != NULL) { + residuals += residual_block->NumResiduals(); + } + } + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.h b/extern/libmv/third_party/ceres/internal/ceres/program.h new file mode 100644 index 00000000000..113d352d562 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/program.h @@ -0,0 +1,128 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_PROGRAM_H_ +#define CERES_INTERNAL_PROGRAM_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class ParameterBlock; +class ProblemImpl; +class ResidualBlock; + +// A nonlinear least squares optimization problem. This is different from the +// similarly-named "Problem" object, which offers a mutation interface for +// adding and modifying parameters and residuals. The Program contains the core +// part of the Problem, which is the parameters and the residuals, stored in a +// particular ordering. The ordering is critical, since it defines the mapping +// between (residual, parameter) pairs and a position in the jacobian of the +// objective function. Various parts of Ceres transform one Program into +// another; for example, the first stage of solving involves stripping all +// constant parameters and residuals. This is in contrast with Problem, which is +// not built for transformation. +class Program { + public: + Program(); + explicit Program(const Program& program); + + // The ordered parameter and residual blocks for the program. + const vector& parameter_blocks() const; + const vector& residual_blocks() const; + vector* mutable_parameter_blocks(); + vector* mutable_residual_blocks(); + + // Serialize to/from the program and update states. + // + // NOTE: Setting the state of a parameter block can trigger the + // computation of the Jacobian of its local parameterization. If + // this computation fails for some reason, then this method returns + // false and the state of the parameter blocks cannot be trusted. + bool StateVectorToParameterBlocks(const double *state); + void ParameterBlocksToStateVector(double *state) const; + + // Copy internal state out to the user's parameters. + void CopyParameterBlockStateToUserState(); + + // Update a state vector for the program given a delta. + bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const; + + // Set the parameter indices and offsets. This permits mapping backward + // from a ParameterBlock* to an index in the parameter_blocks() vector. For + // any parameter block p, after calling SetParameterOffsetsAndIndex(), it + // is true that + // + // parameter_blocks()[p->index()] == p + // + // If a parameter appears in a residual but not in the parameter block, then + // it will have an index of -1. + // + // This also updates p->state_offset() and p->delta_offset(), which are the + // position of the parameter in the state and delta vector respectively. + void SetParameterOffsetsAndIndex(); + + // See problem.h for what these do. + int NumParameterBlocks() const; + int NumParameters() const; + int NumEffectiveParameters() const; + int NumResidualBlocks() const; + int NumResiduals() const; + + int MaxScratchDoublesNeededForEvaluate() const; + int MaxDerivativesPerResidualBlock() const; + int MaxParametersPerResidualBlock() const; + + // Evaluate the cost and maybe the residuals for the program. If residuals is + // NULL, then residuals are not calculated. If the jacobian is needed, instead + // use the various evaluators (e.g. dense_evaluator.h). + // + // This is a trivial implementation of evaluate not intended for use in the + // core solving loop. The other evaluators, which support constructing the + // jacobian in addition to the cost and residuals, are considerably + // complicated by the need to construct the jacobian. + bool Evaluate(double* cost, double* residuals); + + private: + // The Program does not own the ParameterBlock or ResidualBlock objects. + vector parameter_blocks_; + vector residual_blocks_; + + friend class ProblemImpl; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PROGRAM_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h new file mode 100644 index 00000000000..7ec74b1b269 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h @@ -0,0 +1,279 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// The ProgramEvaluator runs the cost functions contained in each residual block +// and stores the result into a jacobian. The particular type of jacobian is +// abstracted out using two template parameters: +// +// - An "EvaluatePreparer" that is responsible for creating the array with +// pointers to the jacobian blocks where the cost function evaluates to. +// - A "JacobianWriter" that is responsible for storing the resulting +// jacobian blocks in the passed sparse matrix. +// +// This abstraction affords an efficient evaluator implementation while still +// supporting writing to multiple sparse matrix formats. For example, when the +// ProgramEvaluator is parameterized for writing to block sparse matrices, the +// residual jacobians are written directly into their final position in the +// block sparse matrix by the user's CostFunction; there is no copying. +// +// The evaluation is threaded with OpenMP. +// +// The EvaluatePreparer and JacobianWriter interfaces are as follows: +// +// class EvaluatePreparer { +// // Prepare the jacobians array for use as the destination of a call to +// // a cost function's evaluate method. +// void Prepare(const ResidualBlock* residual_block, +// int residual_block_index, +// SparseMatrix* jacobian, +// double** jacobians); +// } +// +// class JacobianWriter { +// // Create a jacobian that this writer can write. Same as +// // Evaluator::CreateJacobian. +// SparseMatrix* CreateJacobian() const; +// +// // Create num_threads evaluate preparers. Caller owns result which must +// // be freed with delete[]. Resulting preparers are valid while *this is. +// EvaluatePreparer* CreateEvaluatePreparers(int num_threads); +// +// // Write the block jacobians from a residual block evaluation to the +// // larger sparse jacobian. +// void Write(int residual_id, +// int residual_offset, +// double** jacobians, +// SparseMatrix* jacobian); +// } +// +// Note: The ProgramEvaluator is not thread safe, since internally it maintains +// some per-thread scratch space. + +#ifndef CERES_INTERNAL_PROGRAM_EVALUATOR_H_ +#define CERES_INTERNAL_PROGRAM_EVALUATOR_H_ + +#ifdef CERES_USE_OPENMP +#include +#endif + +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +template +class ProgramEvaluator : public Evaluator { + public: + ProgramEvaluator(const Evaluator::Options &options, Program* program) + : options_(options), + program_(program), + jacobian_writer_(options, program), + evaluate_preparers_( + jacobian_writer_.CreateEvaluatePreparers(options.num_threads)) { +#ifndef CERES_USE_OPENMP + CHECK_EQ(1, options_.num_threads) + << "OpenMP support is not compiled into this binary; " + << "only options.num_threads=1 is supported."; +#endif + + BuildResidualLayout(*program, &residual_layout_); + evaluate_scratch_.reset(CreateEvaluatorScratch(*program, + options.num_threads)); + } + + // Implementation of Evaluator interface. + SparseMatrix* CreateJacobian() const { + return jacobian_writer_.CreateJacobian(); + } + + bool Evaluate(const double* state, + double* cost, + double* residuals, + SparseMatrix* jacobian) { + // The parameters are stateful, so set the state before evaluating. + if (!program_->StateVectorToParameterBlocks(state)) { + return false; + } + + if (jacobian) { + jacobian->SetZero(); + } + + // Each thread gets it's own cost and evaluate scratch space. + for (int i = 0; i < options_.num_threads; ++i) { + evaluate_scratch_[i].cost = 0.0; + } + + // This bool is used to disable the loop if an error is encountered + // without breaking out of it. The remaining loop iterations are still run, + // but with an empty body, and so will finish quickly. + bool abort = false; + int num_residual_blocks = program_->NumResidualBlocks(); +#pragma omp parallel for num_threads(options_.num_threads) + for (int i = 0; i < num_residual_blocks; ++i) { +// Disable the loop instead of breaking, as required by OpenMP. +#pragma omp flush(abort) + if (abort) { + continue; + } + +#ifdef CERES_USE_OPENMP + int thread_id = omp_get_thread_num(); +#else + int thread_id = 0; +#endif + EvaluatePreparer* preparer = &evaluate_preparers_[thread_id]; + EvaluateScratch* scratch = &evaluate_scratch_[thread_id]; + + // Prepare block residuals if requested. + const ResidualBlock* residual_block = program_->residual_blocks()[i]; + double* block_residuals = (residuals != NULL) + ? (residuals + residual_layout_[i]) + : NULL; + + // Prepare block jacobians if requested. + double** block_jacobians = NULL; + if (jacobian != NULL) { + preparer->Prepare(residual_block, + i, + jacobian, + scratch->jacobian_block_ptrs.get()); + block_jacobians = scratch->jacobian_block_ptrs.get(); + } + + // Evaluate the cost, residuals, and jacobians. + double block_cost; + if (!residual_block->Evaluate(&block_cost, + block_residuals, + block_jacobians, + scratch->scratch.get())) { + abort = true; +// This ensures that the OpenMP threads have a consistent view of 'abort'. Do +// the flush inside the failure case so that there is usually only one +// synchronization point per loop iteration instead of two. +#pragma omp flush(abort) + continue; + } + + scratch->cost += block_cost; + + if (jacobian != NULL) { + jacobian_writer_.Write(i, + residual_layout_[i], + block_jacobians, + jacobian); + } + } + + if (!abort) { + // Sum the cost from each thread. + (*cost) = 0.0; + for (int i = 0; i < options_.num_threads; ++i) { + (*cost) += evaluate_scratch_[i].cost; + } + } + return !abort; + } + + bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const { + return program_->Plus(state, delta, state_plus_delta); + } + + int NumParameters() const { + return program_->NumParameters(); + } + int NumEffectiveParameters() const { + return program_->NumEffectiveParameters(); + } + + int NumResiduals() const { + return program_->NumResiduals(); + } + + private: + struct EvaluateScratch { + void Init(int max_parameters_per_residual_block, + int max_scratch_doubles_needed_for_evaluate) { + jacobian_block_ptrs.reset( + new double*[max_parameters_per_residual_block]); + scratch.reset(new double[max_scratch_doubles_needed_for_evaluate]); + } + + double cost; + scoped_array scratch; + scoped_array jacobian_block_ptrs; + }; + + static void BuildResidualLayout(const Program& program, + vector* residual_layout) { + const vector& residual_blocks = program.residual_blocks(); + residual_layout->resize(program.NumResidualBlocks()); + int residual_pos = 0; + for (int i = 0; i < residual_blocks.size(); ++i) { + const int num_residuals = residual_blocks[i]->NumResiduals(); + (*residual_layout)[i] = residual_pos; + residual_pos += num_residuals; + } + } + + // Create scratch space for each thread evaluating the program. + static EvaluateScratch* CreateEvaluatorScratch(const Program& program, + int num_threads) { + int max_parameters_per_residual_block = + program.MaxParametersPerResidualBlock(); + int max_scratch_doubles_needed_for_evaluate = + program.MaxScratchDoublesNeededForEvaluate(); + + EvaluateScratch* evaluate_scratch = new EvaluateScratch[num_threads]; + for (int i = 0; i < num_threads; i++) { + evaluate_scratch[i].Init(max_parameters_per_residual_block, + max_scratch_doubles_needed_for_evaluate); + } + return evaluate_scratch; + } + + Evaluator::Options options_; + Program* program_; + JacobianWriter jacobian_writer_; + scoped_array evaluate_preparers_; + scoped_array evaluate_scratch_; + vector residual_layout_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PROGRAM_EVALUATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/random.h b/extern/libmv/third_party/ceres/internal/ceres/random.h new file mode 100644 index 00000000000..769e0b4dd27 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/random.h @@ -0,0 +1,47 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_RANDOM_H_ +#define CERES_INTERNAL_RANDOM_H_ + +namespace ceres { + +inline double RandDouble() { + double r = rand(); + return r / RAND_MAX; +} + +inline int Uniform(int n) { + return rand() % n; +} + +} // namespace ceres + +#endif // CERES_INTERNAL_RANDOM_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc new file mode 100644 index 00000000000..03867891dba --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc @@ -0,0 +1,212 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/residual_block.h" + +#include +#include +#include + +#include "ceres/corrector.h" +#include "ceres/parameter_block.h" +#include "ceres/residual_block_utils.h" +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/fixed_array.h" +#include "ceres/local_parameterization.h" +#include "ceres/loss_function.h" + +namespace ceres { +namespace internal { + +ResidualBlock::ResidualBlock(const CostFunction* cost_function, + const LossFunction* loss_function, + const vector& parameter_blocks) + : cost_function_(cost_function), + loss_function_(loss_function), + parameter_blocks_( + new ParameterBlock* [ + cost_function->parameter_block_sizes().size()]) { + std::copy(parameter_blocks.begin(), + parameter_blocks.end(), + parameter_blocks_.get()); +} + +bool ResidualBlock::Evaluate(double* cost, + double* residuals, + double** jacobians, + double* scratch) const { + const int num_parameter_blocks = NumParameterBlocks(); + const int num_residuals = cost_function_->num_residuals(); + + // Collect the parameters from their blocks. This will rarely allocate, since + // residuals taking more than 8 parameter block arguments are rare. + FixedArray parameters(num_parameter_blocks); + for (int i = 0; i < num_parameter_blocks; ++i) { + parameters[i] = parameter_blocks_[i]->state(); + } + + // Put pointers into the scratch space into global_jacobians as appropriate. + FixedArray global_jacobians(num_parameter_blocks); + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + if (jacobians[i] != NULL && + parameter_block->LocalParameterizationJacobian() != NULL) { + global_jacobians[i] = scratch; + scratch += num_residuals * parameter_block->Size(); + } else { + global_jacobians[i] = jacobians[i]; + } + } + } + + // If the caller didn't request residuals, use the scratch space for them. + bool outputting_residuals = (residuals != NULL); + if (!outputting_residuals) { + residuals = scratch; + } + + // Invalidate the evaluation buffers so that we can check them after + // the CostFunction::Evaluate call, to see if all the return values + // that were required were written to and that they are finite. + double** eval_jacobians = (jacobians != NULL) ? global_jacobians.get() : NULL; + + InvalidateEvaluation(*this, cost, residuals, eval_jacobians); + + if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians) || + !IsEvaluationValid(*this, + parameters.get(), + cost, + residuals, + eval_jacobians)) { + string message = + "\n\n" + "Error in evaluating the ResidualBlock.\n\n" + "There are two possible reasons. Either the CostFunction did not evaluate and fill all \n" // NOLINT + "residual and jacobians that were requested or there was a non-finite value (nan/infinite)\n" // NOLINT + "generated during the or jacobian computation. \n\n" + + EvaluationToString(*this, + parameters.get(), + cost, + residuals, + eval_jacobians); + LOG(WARNING) << message; + return false; + } + + double squared_norm = VectorRef(residuals, num_residuals).squaredNorm(); + + // Update the jacobians with the local parameterizations. + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + if (jacobians[i] != NULL) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + + // Apply local reparameterization to the jacobians. + if (parameter_block->LocalParameterizationJacobian() != NULL) { + ConstMatrixRef local_to_global( + parameter_block->LocalParameterizationJacobian(), + parameter_block->Size(), + parameter_block->LocalSize()); + MatrixRef global_jacobian(global_jacobians[i], + num_residuals, + parameter_block->Size()); + MatrixRef local_jacobian(jacobians[i], + num_residuals, + parameter_block->LocalSize()); + local_jacobian.noalias() = global_jacobian * local_to_global; + } + } + } + } + + if (loss_function_ == NULL) { + *cost = 0.5 * squared_norm; + return true; + } + + double rho[3]; + loss_function_->Evaluate(squared_norm, rho); + *cost = 0.5 * rho[0]; + + // No jacobians and not outputting residuals? All done. Doing an early exit + // here avoids constructing the "Corrector" object below in a common case. + if (jacobians == NULL && !outputting_residuals) { + return true; + } + + // Correct for the effects of the loss function. The jacobians need to be + // corrected before the residuals, since they use the uncorrected residuals. + Corrector correct(squared_norm, rho); + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + if (jacobians[i] != NULL) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + + // Correct the jacobians for the loss function. + correct.CorrectJacobian(num_residuals, + parameter_block->LocalSize(), + residuals, + jacobians[i]); + } + } + } + + // Correct the residuals with the loss function. + if (outputting_residuals) { + correct.CorrectResiduals(num_residuals, residuals); + } + return true; +} + +int ResidualBlock::NumScratchDoublesForEvaluate() const { + // Compute the amount of scratch space needed to store the full-sized + // jacobians. For parameters that have no local parameterization no storage + // is needed and the passed-in jacobian array is used directly. Also include + // space to store the residuals, which is needed for cost-only evaluations. + // This is slightly pessimistic, since both won't be needed all the time, but + // the amount of excess should not cause problems for the caller. + int num_parameters = NumParameterBlocks(); + int scratch_doubles = 1; + for (int i = 0; i < num_parameters; ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + if (!parameter_block->IsConstant() && + parameter_block->LocalParameterizationJacobian() != NULL) { + scratch_doubles += parameter_block->Size(); + } + } + scratch_doubles *= NumResiduals(); + return scratch_doubles; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block.h new file mode 100644 index 00000000000..e0a06e78958 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.h @@ -0,0 +1,124 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.com (Keir Mierle) +// +// Purpose : Class and struct definitions for parameter and residual blocks. + +#ifndef CERES_INTERNAL_RESIDUAL_BLOCK_H_ +#define CERES_INTERNAL_RESIDUAL_BLOCK_H_ + +#include + +#include "ceres/cost_function.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { + +class LossFunction; + +namespace internal { + +class ParameterBlock; + +// A term in the least squares problem. The mathematical form of each term in +// the overall least-squares cost function is: +// +// 1 +// --- loss_function( || cost_function(block1, block2, ...) ||^2 ), +// 2 +// +// Storing the cost function and the loss function separately permits optimizing +// the problem with standard non-linear least techniques, without requiring a +// more general non-linear solver. +// +// The residual block stores pointers to but does not own the cost functions, +// loss functions, and parameter blocks. +class ResidualBlock { + public: + ResidualBlock(const CostFunction* cost_function, + const LossFunction* loss_function, + const vector& parameter_blocks); + + // Evaluates the residual term, storing the scalar cost in *cost, the residual + // components in *residuals, and the jacobians between the parameters and + // residuals in jacobians[i], in row-major order. If residuals is NULL, the + // residuals are not computed. If jacobians is NULL, no jacobians are + // computed. If jacobians[i] is NULL, then the jacobian for that parameter is + // not computed. + // + // Evaluate needs scratch space which must be supplied by the caller via + // scratch. The array should have at least NumScratchDoublesForEvaluate() + // space available. + // + // The return value indicates the success or failure. If the function returns + // false, the caller should expect the the output memory locations to have + // been modified. + // + // The returned cost and jacobians have had robustification and local + // parameterizations applied already; for example, the jacobian for a + // 4-dimensional quaternion parameter using the "QuaternionParameterization" + // is num_residuals by 3 instead of num_residuals by 4. + bool Evaluate(double* cost, + double* residuals, + double** jacobians, + double* scratch) const; + + const CostFunction* cost_function() const { return cost_function_; } + const LossFunction* loss_function() const { return loss_function_; } + + // Access the parameter blocks for this residual. The array has size + // NumParameterBlocks(). + ParameterBlock* const* parameter_blocks() const { + return parameter_blocks_.get(); + } + + // Number of variable blocks that this residual term depends on. + int NumParameterBlocks() const { + return cost_function_->parameter_block_sizes().size(); + } + + // The size of the residual vector returned by this residual function. + int NumResiduals() const { return cost_function_->num_residuals(); } + + // The minimum amount of scratch space needed to pass to Evaluate(). + int NumScratchDoublesForEvaluate() const; + + private: + const CostFunction* cost_function_; + const LossFunction* loss_function_; + scoped_array parameter_blocks_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_RESIDUAL_BLOCK_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc new file mode 100644 index 00000000000..28e03130844 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc @@ -0,0 +1,185 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/residual_block_utils.h" + +#include +#include +#include +#include +#include "ceres/residual_block.h" +#include "ceres/parameter_block.h" +#include "ceres/stringprintf.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" + +#ifdef _MSC_VER +# define isfinite _finite +#endif + +namespace ceres { +namespace internal { + +// It is a near impossibility that user code generates this exact +// value in normal operation, thus we will use it to fill arrays +// before passing them to user code. If on return an element of the +// array still contains this value, we will assume that the user code +// did not write to that memory location. +static const double kImpossibleValue = 1e302; + +bool IsArrayValid(const int size, const double* x) { + if (x != NULL) { + for (int i = 0; i < size; ++i) { + if (!isfinite(x[i]) || (x[i] == kImpossibleValue)) { + return false; + } + } + } + return true; +} + +void InvalidateArray(const int size, double* x) { + if (x != NULL) { + for (int i = 0; i < size; ++i) { + x[i] = kImpossibleValue; + } + } +} + +void InvalidateEvaluation(const ResidualBlock& block, + double* cost, + double* residuals, + double** jacobians) { + const int num_parameter_blocks = block.NumParameterBlocks(); + const int num_residuals = block.NumResiduals(); + + InvalidateArray(1, cost); + InvalidateArray(num_residuals, residuals); + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + const int parameter_block_size = block.parameter_blocks()[i]->Size(); + InvalidateArray(num_residuals * parameter_block_size, jacobians[i]); + } + } +} + +// Utility routine to print an array of doubles to a string. If the +// array pointer is NULL, it is treated as an array of zeros. +void AppendArrayToString(const int size, const double* x, string* result) { + for (int i = 0; i < size; ++i) { + if (x == NULL) { + StringAppendF(result, "Not Computed "); + } else { + if (x[i] == kImpossibleValue) { + StringAppendF(result, "Uninitialized "); + } else { + StringAppendF(result, "%12g ", x[i]); + } + } + } +} + +string EvaluationToString(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians) { + CHECK_NOTNULL(cost); + CHECK_NOTNULL(residuals); + + const int num_parameter_blocks = block.NumParameterBlocks(); + const int num_residuals = block.NumResiduals(); + string result = ""; + + StringAppendF(&result, + "Residual Block size: %d parameter blocks x %d residuals\n\n", + num_parameter_blocks, num_residuals); + result += + "For each parameter block, the value of the parameters are printed in the first column \n" // NOLINT + "and the value of the jacobian under the corresponding residual. If a ParameterBlock was \n" // NOLINT + "held constant then the corresponding jacobian is printed as 'Not Computed'. If an entry \n" // NOLINT + "of the Jacobian/residual array was requested but was not written to by user code, it is \n" // NOLINT + "indicated by 'Uninitialized'. This is an error. Residuals or Jacobian values evaluating \n" // NOLINT + "to Inf or NaN is also an error. \n\n"; // NOLINT + + string space = "Residuals: "; + result += space; + AppendArrayToString(num_residuals, residuals, &result); + StringAppendF(&result, "\n\n"); + + for (int i = 0; i < num_parameter_blocks; ++i) { + const int parameter_block_size = block.parameter_blocks()[i]->Size(); + StringAppendF( + &result, "Parameter Block %d, size: %d\n", i, parameter_block_size); + StringAppendF(&result, "\n"); + for (int j = 0; j < parameter_block_size; ++j) { + AppendArrayToString(1, parameters[i] + j, &result); + StringAppendF(&result, "| "); + for (int k = 0; k < num_residuals; ++k) { + AppendArrayToString(1, + (jacobians != NULL && jacobians[i] != NULL) + ? jacobians[i] + k * parameter_block_size + j + : NULL, + &result); + } + StringAppendF(&result, "\n"); + } + StringAppendF(&result, "\n"); + } + StringAppendF(&result, "\n"); + return result; +} + +bool IsEvaluationValid(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians) { + const int num_parameter_blocks = block.NumParameterBlocks(); + const int num_residuals = block.NumResiduals(); + + if (!IsArrayValid(num_residuals, residuals)) { + return false; + } + + if (jacobians != NULL) { + for (int i = 0; i < num_parameter_blocks; ++i) { + const int parameter_block_size = block.parameter_blocks()[i]->Size(); + if (!IsArrayValid(num_residuals * parameter_block_size, jacobians[i])) { + return false; + } + } + } + + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h new file mode 100644 index 00000000000..228867cc60c --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h @@ -0,0 +1,89 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Utility routines for ResidualBlock evaluation. +// +// These are useful for detecting two common class of errors. +// +// 1. Uninitialized memory - where the user for some reason did not +// compute part of a cost/residual/jacobian. +// +// 2. Numerical failure while computing the cost/residual/jacobian, +// e.g. NaN, infinities etc. This is particularly useful since the +// automatic differentiation code does computations that are not +// evident to the user and can silently generate hard to debug errors. + +#ifndef CERES_INTERNAL_RESIDUAL_BLOCK_UTILS_H_ +#define CERES_INTERNAL_RESIDUAL_BLOCK_UTILS_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class ResidualBlock; + +// Fill the array x with an impossible value that the user code is +// never expected to compute. +void InvalidateArray(int size, double* x); + +// Check if all the entries of the array x are valid, i.e. all the +// values in the array should be finite and none of them should be +// equal to the "impossible" value used by InvalidateArray. +bool IsArrayValid(int size, const double* x); + +// Invalidate cost, resdual and jacobian arrays (if not NULL). +void InvalidateEvaluation(const ResidualBlock& block, + double* cost, + double* residuals, + double** jacobians); + +// Check if any of the arrays cost, residuals or jacobians contains an +// NaN, return true if it does. +bool IsEvaluationValid(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians); + +// Create a string representation of the Residual block containing the +// value of the parameters, residuals and jacobians if present. +// Useful for debugging output. +string EvaluationToString(const ResidualBlock& block, + double const* const* parameters, + double* cost, + double* residuals, + double** jacobians); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_RESIDUAL_BLOCK_UTILS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc new file mode 100644 index 00000000000..ac6d8aa279a --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc @@ -0,0 +1,218 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Based on the templated version in public/numeric_diff_cost_function.h. + +#include "ceres/runtime_numeric_diff_cost_function.h" + +#include +#include +#include + +#include +#include "Eigen/Dense" +#include "ceres/cost_function.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { +namespace { + +bool EvaluateJacobianForParameterBlock(const CostFunction* function, + int parameter_block_size, + int parameter_block, + RuntimeNumericDiffMethod method, + double relative_step_size, + double const* residuals_at_eval_point, + double** parameters, + double** jacobians) { + using Eigen::Map; + using Eigen::Matrix; + using Eigen::Dynamic; + using Eigen::RowMajor; + + typedef Matrix ResidualVector; + typedef Matrix ParameterVector; + typedef Matrix JacobianMatrix; + + int num_residuals = function->num_residuals(); + + Map parameter_jacobian(jacobians[parameter_block], + num_residuals, + parameter_block_size); + + // Mutate one element at a time and then restore. + Map x_plus_delta(parameters[parameter_block], + parameter_block_size); + ParameterVector x(x_plus_delta); + ParameterVector step_size = x.array().abs() * relative_step_size; + + // To handle cases where a paremeter is exactly zero, instead use the mean + // step_size for the other dimensions. + double fallback_step_size = step_size.sum() / step_size.rows(); + if (fallback_step_size == 0.0) { + // If all the parameters are zero, there's no good answer. Use the given + // relative step_size as absolute step_size and hope for the best. + fallback_step_size = relative_step_size; + } + + // For each parameter in the parameter block, use finite differences to + // compute the derivative for that parameter. + for (int j = 0; j < parameter_block_size; ++j) { + if (step_size(j) == 0.0) { + // The parameter is exactly zero, so compromise and use the mean step_size + // from the other parameters. This can break in many cases, but it's hard + // to pick a good number without problem specific knowledge. + step_size(j) = fallback_step_size; + } + x_plus_delta(j) = x(j) + step_size(j); + + ResidualVector residuals(num_residuals); + if (!function->Evaluate(parameters, &residuals[0], NULL)) { + // Something went wrong; bail. + return false; + } + + // Compute this column of the jacobian in 3 steps: + // 1. Store residuals for the forward part. + // 2. Subtract residuals for the backward (or 0) part. + // 3. Divide out the run. + parameter_jacobian.col(j) = residuals; + + double one_over_h = 1 / step_size(j); + if (method == CENTRAL) { + // Compute the function on the other side of x(j). + x_plus_delta(j) = x(j) - step_size(j); + + if (!function->Evaluate(parameters, &residuals[0], NULL)) { + // Something went wrong; bail. + return false; + } + parameter_jacobian.col(j) -= residuals; + one_over_h /= 2; + } else { + // Forward difference only; reuse existing residuals evaluation. + parameter_jacobian.col(j) -= + Map(residuals_at_eval_point, num_residuals); + } + x_plus_delta(j) = x(j); // Restore x_plus_delta. + + // Divide out the run to get slope. + parameter_jacobian.col(j) *= one_over_h; + } + return true; +} + +class RuntimeNumericDiffCostFunction : public CostFunction { + public: + RuntimeNumericDiffCostFunction(const CostFunction* function, + RuntimeNumericDiffMethod method, + double relative_step_size) + : function_(function), + method_(method), + relative_step_size_(relative_step_size) { + *mutable_parameter_block_sizes() = function->parameter_block_sizes(); + set_num_residuals(function->num_residuals()); + } + + virtual ~RuntimeNumericDiffCostFunction() { } + + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + // Get the function value (residuals) at the the point to evaluate. + bool success = function_->Evaluate(parameters, residuals, NULL); + if (!success) { + // Something went wrong; ignore the jacobian. + return false; + } + if (!jacobians) { + // Nothing to do; just forward. + return true; + } + + const vector& block_sizes = function_->parameter_block_sizes(); + CHECK(!block_sizes.empty()); + + // Create local space for a copy of the parameters which will get mutated. + int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0); + vector parameters_copy(parameters_size); + vector parameters_references_copy(block_sizes.size()); + parameters_references_copy[0] = ¶meters_copy[0]; + for (int block = 1; block < block_sizes.size(); ++block) { + parameters_references_copy[block] = parameters_references_copy[block - 1] + + block_sizes[block - 1]; + } + + // Copy the parameters into the local temp space. + for (int block = 0; block < block_sizes.size(); ++block) { + memcpy(parameters_references_copy[block], + parameters[block], + block_sizes[block] * sizeof(*parameters[block])); + } + + for (int block = 0; block < block_sizes.size(); ++block) { + if (!jacobians[block]) { + // No jacobian requested for this parameter / residual pair. + continue; + } + if (!EvaluateJacobianForParameterBlock(function_, + block_sizes[block], + block, + method_, + relative_step_size_, + residuals, + ¶meters_references_copy[0], + jacobians)) { + return false; + } + } + return true; + } + + private: + const CostFunction* function_; + RuntimeNumericDiffMethod method_; + double relative_step_size_; +}; + +} // namespace + +CostFunction* CreateRuntimeNumericDiffCostFunction( + const CostFunction* cost_function, + RuntimeNumericDiffMethod method, + double relative_step_size) { + return new RuntimeNumericDiffCostFunction(cost_function, + method, + relative_step_size); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h new file mode 100644 index 00000000000..01b57f92ef3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.h @@ -0,0 +1,87 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// Create CostFunctions as needed by the least squares framework with jacobians +// computed via numeric differentiation. +// +// To get a numerically differentiated cost function, define a subclass of +// CostFunction such that the Evaluate() function ignores the jacobian +// parameter. The numeric differentiation wrapper will fill in the jacobian +// parameter if nececssary by repeatedly calling the Evaluate() function with +// small changes to the appropriate parameters, and computing the slope. This +// implementation is not templated (hence the "Runtime" prefix), which is a bit +// slower than but is more convenient than the templated version in +// numeric_diff_cost_function.h +// +// The numerically differentiated version of a cost function for a cost function +// can be constructed as follows: +// +// CostFunction* cost_function = +// CreateRuntimeNumericDiffCostFunction(new MyCostFunction(...), +// CENTRAL, +// TAKE_OWNERSHIP); +// +// The central difference method is considerably more accurate; consider using +// to start and only after that works, trying forward difference. +// +// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives. + +#ifndef CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_ +#define CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_ + +#include "ceres/cost_function.h" + +namespace ceres { +namespace internal { + +enum RuntimeNumericDiffMethod { + CENTRAL, + FORWARD, +}; + +// Create a cost function that evaluates the derivative with finite differences. +// The base cost_function's implementation of Evaluate() only needs to fill in +// the "residuals" argument and not the "jacobians". Any data written to the +// jacobians by the base cost_function is overwritten. +// +// Forward difference or central difference is selected with CENTRAL or FORWARD. +// The relative eps, which determines the step size for forward and central +// differencing, is set with relative eps. Caller owns the resulting cost +// function, and the resulting cost function does not own the base cost +// function. +CostFunction *CreateRuntimeNumericDiffCostFunction( + const CostFunction *cost_function, + RuntimeNumericDiffMethod method, + double relative_eps); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_RUNTIME_NUMERIC_DIFF_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc new file mode 100644 index 00000000000..2bc8cdd6bec --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc @@ -0,0 +1,285 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include +#include +#include +#include "Eigen/Dense" +#include "ceres/block_random_access_dense_matrix.h" +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_random_access_sparse_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/detect_structure.h" +#include "ceres/linear_solver.h" +#include "ceres/schur_complement_solver.h" +#include "ceres/suitesparse.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +LinearSolver::Summary SchurComplementSolver::SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + const time_t start_time = time(NULL); + if (!options_.constant_sparsity || (eliminator_.get() == NULL)) { + InitStorage(A->block_structure()); + DetectStructure(*A->block_structure(), + options_.num_eliminate_blocks, + &options_.row_block_size, + &options_.e_block_size, + &options_.f_block_size); + eliminator_.reset(CHECK_NOTNULL(SchurEliminatorBase::Create(options_))); + eliminator_->Init(options_.num_eliminate_blocks, A->block_structure()); + }; + const time_t init_time = time(NULL); + fill(x, x + A->num_cols(), 0.0); + + LinearSolver::Summary summary; + summary.num_iterations = 1; + summary.termination_type = FAILURE; + eliminator_->Eliminate(A, b, per_solve_options.D, lhs_.get(), rhs_.get()); + const time_t eliminate_time = time(NULL); + + double* reduced_solution = x + A->num_cols() - lhs_->num_cols(); + const bool status = SolveReducedLinearSystem(reduced_solution); + const time_t solve_time = time(NULL); + + if (!status) { + return summary; + } + + eliminator_->BackSubstitute(A, b, per_solve_options.D, reduced_solution, x); + const time_t backsubstitute_time = time(NULL); + summary.termination_type = TOLERANCE; + + VLOG(2) << "time (sec) total: " << backsubstitute_time - start_time + << " init: " << init_time - start_time + << " eliminate: " << eliminate_time - init_time + << " solve: " << solve_time - eliminate_time + << " backsubstitute: " << backsubstitute_time - solve_time; + return summary; +} + +// Initialize a BlockRandomAccessDenseMatrix to store the Schur +// complement. +void DenseSchurComplementSolver::InitStorage( + const CompressedRowBlockStructure* bs) { + const int num_eliminate_blocks = options().num_eliminate_blocks; + const int num_col_blocks = bs->cols.size(); + + vector blocks(num_col_blocks - num_eliminate_blocks, 0); + for (int i = num_eliminate_blocks, j = 0; + i < num_col_blocks; + ++i, ++j) { + blocks[j] = bs->cols[i].size; + } + + set_lhs(new BlockRandomAccessDenseMatrix(blocks)); + set_rhs(new double[lhs()->num_rows()]); +} + +// Solve the system Sx = r, assuming that the matrix S is stored in a +// BlockRandomAccessDenseMatrix. The linear system is solved using +// Eigen's Cholesky factorization. +bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { + const BlockRandomAccessDenseMatrix* m = + down_cast(lhs()); + const int num_rows = m->num_rows(); + + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + return true; + } + + // TODO(sameeragarwal): Add proper error handling; this completely ignores + // the quality of the solution to the solve. + VectorRef(solution, num_rows) = + ConstMatrixRef(m->values(), num_rows, num_rows) + .selfadjointView() + .ldlt() + .solve(ConstVectorRef(rhs(), num_rows)); + + return true; +} + +#ifndef CERES_NO_SUITESPARSE +SparseSchurComplementSolver::SparseSchurComplementSolver( + const LinearSolver::Options& options) + : SchurComplementSolver(options), + symbolic_factor_(NULL) { +} + +SparseSchurComplementSolver::~SparseSchurComplementSolver() { + if (symbolic_factor_ != NULL) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } +} + +// Determine the non-zero blocks in the Schur Complement matrix, and +// initialize a BlockRandomAccessSparseMatrix object. +void SparseSchurComplementSolver::InitStorage( + const CompressedRowBlockStructure* bs) { + const int num_eliminate_blocks = options().num_eliminate_blocks; + const int num_col_blocks = bs->cols.size(); + const int num_row_blocks = bs->rows.size(); + + vector blocks(num_col_blocks - num_eliminate_blocks, 0); + for (int i = num_eliminate_blocks; i < num_col_blocks; ++i) { + blocks[i - num_eliminate_blocks] = bs->cols[i].size; + } + + set > block_pairs; + for (int i = 0; i < blocks.size(); ++i) { + block_pairs.insert(make_pair(i, i)); + } + + int r = 0; + while (r < num_row_blocks) { + int e_block_id = bs->rows[r].cells.front().block_id; + if (e_block_id >= num_eliminate_blocks) { + break; + } + vector f_blocks; + + // Add to the chunk until the first block in the row is + // different than the one in the first row for the chunk. + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs->rows[r]; + if (row.cells.front().block_id != e_block_id) { + break; + } + + // Iterate over the blocks in the row, ignoring the first + // block since it is the one to be eliminated. + for (int c = 1; c < row.cells.size(); ++c) { + const Cell& cell = row.cells[c]; + f_blocks.push_back(cell.block_id - num_eliminate_blocks); + } + } + + sort(f_blocks.begin(), f_blocks.end()); + f_blocks.erase(unique(f_blocks.begin(), f_blocks.end()), f_blocks.end()); + for (int i = 0; i < f_blocks.size(); ++i) { + for (int j = i + 1; j < f_blocks.size(); ++j) { + block_pairs.insert(make_pair(f_blocks[i], f_blocks[j])); + } + } + } + + // Remaing rows do not contribute to the chunks and directly go + // into the schur complement via an outer product. + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs->rows[r]; + CHECK_GE(row.cells.front().block_id, num_eliminate_blocks); + for (int i = 0; i < row.cells.size(); ++i) { + int r_block1_id = row.cells[i].block_id - num_eliminate_blocks; + for (int j = 0; j < row.cells.size(); ++j) { + int r_block2_id = row.cells[j].block_id - num_eliminate_blocks; + if (r_block1_id <= r_block2_id) { + block_pairs.insert(make_pair(r_block1_id, r_block2_id)); + } + } + } + } + + set_lhs(new BlockRandomAccessSparseMatrix(blocks, block_pairs)); + set_rhs(new double[lhs()->num_rows()]); +} + +// Solve the system Sx = r, assuming that the matrix S is stored in a +// BlockRandomAccessSparseMatrix. The linear system is solved using +// CHOLMOD's sparse cholesky factorization routines. +bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { + // Extract the TripletSparseMatrix that is used for actually storing S. + TripletSparseMatrix* tsm = + const_cast( + down_cast(lhs())->matrix()); + + const int num_rows = tsm->num_rows(); + + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + return true; + } + + cholmod_sparse* cholmod_lhs = ss_.CreateSparseMatrix(tsm); + // The matrix is symmetric, and the upper triangular part of the + // matrix contains the values. + cholmod_lhs->stype = 1; + + cholmod_dense* cholmod_rhs = + ss_.CreateDenseVector(const_cast(rhs()), num_rows, num_rows); + + // Symbolic factorization is computed if we don't already have one handy. + if (symbolic_factor_ == NULL) { + symbolic_factor_ = ss_.AnalyzeCholesky(cholmod_lhs); + } + + cholmod_dense* cholmod_solution = + ss_.SolveCholesky(cholmod_lhs, symbolic_factor_, cholmod_rhs); + + ss_.Free(cholmod_lhs); + cholmod_lhs = NULL; + ss_.Free(cholmod_rhs); + cholmod_rhs = NULL; + + // If sparsity is not constant across calls, then reset the symbolic + // factorization. + if (!options().constant_sparsity) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } + + if (cholmod_solution == NULL) { + LOG(ERROR) << "CHOLMOD solve failed."; + return false; + } + + VectorRef(solution, num_rows) + = VectorRef(static_cast(cholmod_solution->x), num_rows); + ss_.Free(cholmod_solution); + return true; +} +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h new file mode 100644 index 00000000000..039bc09e3ce --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h @@ -0,0 +1,182 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ +#define CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ + +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/suitesparse.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class BlockSparseMatrixBase; + +// Base class for Schur complement based linear least squares +// solvers. It assumes that the input linear system Ax = b can be +// partitioned into +// +// E y + F z = b +// +// Where x = [y;z] is a partition of the variables. The paritioning +// of the variables is such that, E'E is a block diagonal +// matrix. Further, the rows of A are ordered so that for every +// variable block in y, all the rows containing that variable block +// occur as a vertically contiguous block. i.e the matrix A looks like +// +// E F +// A = [ y1 0 0 0 | z1 0 0 0 z5] +// [ y1 0 0 0 | z1 z2 0 0 0] +// [ 0 y2 0 0 | 0 0 z3 0 0] +// [ 0 0 y3 0 | z1 z2 z3 z4 z5] +// [ 0 0 y3 0 | z1 0 0 0 z5] +// [ 0 0 0 y4 | 0 0 0 0 z5] +// [ 0 0 0 y4 | 0 z2 0 0 0] +// [ 0 0 0 y4 | 0 0 0 0 0] +// [ 0 0 0 0 | z1 0 0 0 0] +// [ 0 0 0 0 | 0 0 z3 z4 z5] +// +// This structure should be reflected in the corresponding +// CompressedRowBlockStructure object associated with A. The linear +// system Ax = b should either be well posed or the array D below +// should be non-null and the diagonal matrix corresponding to it +// should be non-singular. +// +// SchurComplementSolver has two sub-classes. +// +// DenseSchurComplementSolver: For problems where the Schur complement +// matrix is small and dense, or if CHOLMOD/SuiteSparse is not +// installed. For structure from motion problems, this is solver can +// be used for problems with upto a few hundred cameras. +// +// SparseSchurComplementSolver: For problems where the Schur +// complement matrix is large and sparse. It requires that +// CHOLMOD/SuiteSparse be installed, as it uses CHOLMOD to find a +// sparse Cholesky factorization of the Schur complement. This solver +// can be used for solving structure from motion problems with tens of +// thousands of cameras, though depending on the exact sparsity +// structure, it maybe better to use an iterative solver. +// +// The two solvers can be instantiated by calling +// LinearSolver::CreateLinearSolver with LinearSolver::Options::type +// set to DENSE_SCHUR and SPARSE_SCHUR +// respectively. LinearSolver::Options::num_eliminate_blocks should be +// at least 1. +class SchurComplementSolver : public BlockSparseMatrixBaseSolver { + public: + explicit SchurComplementSolver(const LinearSolver::Options& options) + : options_(options) { + CHECK_GT(options.num_eliminate_blocks, 0); + } + + // LinearSolver methods + virtual ~SchurComplementSolver() {} + virtual LinearSolver::Summary SolveImpl( + BlockSparseMatrixBase* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + protected: + const LinearSolver::Options& options() const { return options_; } + + const BlockRandomAccessMatrix* lhs() const { return lhs_.get(); } + void set_lhs(BlockRandomAccessMatrix* lhs) { lhs_.reset(lhs); } + const double* rhs() const { return rhs_.get(); } + void set_rhs(double* rhs) { rhs_.reset(rhs); } + + private: + virtual void InitStorage(const CompressedRowBlockStructure* bs) = 0; + virtual bool SolveReducedLinearSystem(double* solution) = 0; + + LinearSolver::Options options_; + + scoped_ptr eliminator_; + scoped_ptr lhs_; + scoped_array rhs_; + + DISALLOW_COPY_AND_ASSIGN(SchurComplementSolver); +}; + +// Dense Cholesky factorization based solver. +class DenseSchurComplementSolver : public SchurComplementSolver { + public: + explicit DenseSchurComplementSolver(const LinearSolver::Options& options) + : SchurComplementSolver(options) {} + virtual ~DenseSchurComplementSolver() {} + + private: + virtual void InitStorage(const CompressedRowBlockStructure* bs); + virtual bool SolveReducedLinearSystem(double* solution); + + DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver); +}; + +#ifndef CERES_NO_SUITESPARSE +// Sparse Cholesky factorization based solver. +class SparseSchurComplementSolver : public SchurComplementSolver { + public: + explicit SparseSchurComplementSolver(const LinearSolver::Options& options); + virtual ~SparseSchurComplementSolver(); + + private: + virtual void InitStorage(const CompressedRowBlockStructure* bs); + virtual bool SolveReducedLinearSystem(double* solution); + + + SuiteSparse ss_; + // Symbolic factorization of the reduced linear system. Precomputed + // once and reused if constant_sparsity_ is true. + cholmod_factor* symbolic_factor_; + DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver); +}; +#else // CERES_NO_SUITESPARSE +class SparseSchurComplementSolver : public SchurComplementSolver { + public: + explicit SparseSchurComplementSolver(const LinearSolver::Options& options) + : SchurComplementSolver(options) { + LOG(FATAL) << "SPARSE_SCHUR is not available. Please " + "build Ceres with SuiteSparse."; + } + + virtual ~SparseSchurComplementSolver() {} +}; +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc new file mode 100644 index 00000000000..44f5be3b4e9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc @@ -0,0 +1,141 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_template_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +SchurEliminatorBase* +SchurEliminatorBase::Create(const LinearSolver::Options& options) { +#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == 2)) { + return new SchurEliminator<2, 2, 2>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == 3)) { + return new SchurEliminator<2, 2, 3>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == 4)) { + return new SchurEliminator<2, 2, 4>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 2) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<2, 2, Dynamic>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == 3)) { + return new SchurEliminator<2, 3, 3>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == 4)) { + return new SchurEliminator<2, 3, 4>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == 9)) { + return new SchurEliminator<2, 3, 9>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 3) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<2, 3, Dynamic>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 4) && + (options.f_block_size == 3)) { + return new SchurEliminator<2, 4, 3>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 4) && + (options.f_block_size == 4)) { + return new SchurEliminator<2, 4, 4>(options); + } + if ((options.row_block_size == 2) && + (options.e_block_size == 4) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<2, 4, Dynamic>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == 2)) { + return new SchurEliminator<4, 4, 2>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == 3)) { + return new SchurEliminator<4, 4, 3>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == 4)) { + return new SchurEliminator<4, 4, 4>(options); + } + if ((options.row_block_size == 4) && + (options.e_block_size == 4) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator<4, 4, Dynamic>(options); + } + if ((options.row_block_size == Dynamic) && + (options.e_block_size == Dynamic) && + (options.f_block_size == Dynamic)) { + return new SchurEliminator(options); + } + +#endif + VLOG(1) << "Template specializations not found for <" + << options.row_block_size << "," + << options.e_block_size << "," + << options.f_block_size << ">"; + return new SchurEliminator(options); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h new file mode 100644 index 00000000000..c24fe435f54 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h @@ -0,0 +1,339 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_SCHUR_ELIMINATOR_H_ +#define CERES_INTERNAL_SCHUR_ELIMINATOR_H_ + +#include +#include +#include "ceres/mutex.h" +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/linear_solver.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// Classes implementing the SchurEliminatorBase interface implement +// variable elimination for linear least squares problems. Assuming +// that the input linear system Ax = b can be partitioned into +// +// E y + F z = b +// +// Where x = [y;z] is a partition of the variables. The paritioning +// of the variables is such that, E'E is a block diagonal matrix. Or +// in other words, the parameter blocks in E form an independent set +// of the of the graph implied by the block matrix A'A. Then, this +// class provides the functionality to compute the Schur complement +// system +// +// S z = r +// +// where +// +// S = F'F - F'E (E'E)^{-1} E'F and r = F'b - F'E(E'E)^(-1) E'b +// +// This is the Eliminate operation, i.e., construct the linear system +// obtained by eliminating the variables in E. +// +// The eliminator also provides the reverse functionality, i.e. given +// values for z it can back substitute for the values of y, by solving the +// linear system +// +// Ey = b - F z +// +// which is done by observing that +// +// y = (E'E)^(-1) [E'b - E'F z] +// +// The eliminator has a number of requirements. +// +// The rows of A are ordered so that for every variable block in y, +// all the rows containing that variable block occur as a vertically +// contiguous block. i.e the matrix A looks like +// +// E F chunk +// A = [ y1 0 0 0 | z1 0 0 0 z5] 1 +// [ y1 0 0 0 | z1 z2 0 0 0] 1 +// [ 0 y2 0 0 | 0 0 z3 0 0] 2 +// [ 0 0 y3 0 | z1 z2 z3 z4 z5] 3 +// [ 0 0 y3 0 | z1 0 0 0 z5] 3 +// [ 0 0 0 y4 | 0 0 0 0 z5] 4 +// [ 0 0 0 y4 | 0 z2 0 0 0] 4 +// [ 0 0 0 y4 | 0 0 0 0 0] 4 +// [ 0 0 0 0 | z1 0 0 0 0] non chunk blocks +// [ 0 0 0 0 | 0 0 z3 z4 z5] non chunk blocks +// +// This structure should be reflected in the corresponding +// CompressedRowBlockStructure object associated with A. The linear +// system Ax = b should either be well posed or the array D below +// should be non-null and the diagonal matrix corresponding to it +// should be non-singular. For simplicity of exposition only the case +// with a null D is described. +// +// The usual way to do the elimination is as follows. Starting with +// +// E y + F z = b +// +// we can form the normal equations, +// +// E'E y + E'F z = E'b +// F'E y + F'F z = F'b +// +// multiplying both sides of the first equation by (E'E)^(-1) and then +// by F'E we get +// +// F'E y + F'E (E'E)^(-1) E'F z = F'E (E'E)^(-1) E'b +// F'E y + F'F z = F'b +// +// now subtracting the two equations we get +// +// [FF' - F'E (E'E)^(-1) E'F] z = F'b - F'E(E'E)^(-1) E'b +// +// Instead of forming the normal equations and operating on them as +// general sparse matrices, the algorithm here deals with one +// parameter block in y at a time. The rows corresponding to a single +// parameter block yi are known as a chunk, and the algorithm operates +// on one chunk at a time. The mathematics remains the same since the +// reduced linear system can be shown to be the sum of the reduced +// linear systems for each chunk. This can be seen by observing two +// things. +// +// 1. E'E is a block diagonal matrix. +// +// 2. When E'F is computed, only the terms within a single chunk +// interact, i.e for y1 column blocks when transposed and multiplied +// with F, the only non-zero contribution comes from the blocks in +// chunk1. +// +// Thus, the reduced linear system +// +// FF' - F'E (E'E)^(-1) E'F +// +// can be re-written as +// +// sum_k F_k F_k' - F_k'E_k (E_k'E_k)^(-1) E_k' F_k +// +// Where the sum is over chunks and E_k'E_k is dense matrix of size y1 +// x y1. +// +// Advanced usage. Uptil now it has been assumed that the user would +// be interested in all of the Schur Complement S. However, it is also +// possible to use this eliminator to obtain an arbitrary submatrix of +// the full Schur complement. When the eliminator is generating the +// blocks of S, it asks the RandomAccessBlockMatrix instance passed to +// it if it has storage for that block. If it does, the eliminator +// computes/updates it, if not it is skipped. This is useful when one +// is interested in constructing a preconditioner based on the Schur +// Complement, e.g., computing the block diagonal of S so that it can +// be used as a preconditioner for an Iterative Substructuring based +// solver [See Agarwal et al, Bundle Adjustment in the Large, ECCV +// 2008 for an example of such use]. +// +// Example usage: Please see schur_complement_solver.cc +class SchurEliminatorBase { + public: + virtual ~SchurEliminatorBase() {} + + // Initialize the eliminator. It is the user's responsibilty to call + // this function before calling Eliminate or BackSubstitute. It is + // also the caller's responsibilty to ensure that the + // CompressedRowBlockStructure object passed to this method is the + // same one (or is equivalent to) the one associated with the + // BlockSparseMatrixBase objects below. + virtual void Init(int num_eliminate_blocks, + const CompressedRowBlockStructure* bs) = 0; + + // Compute the Schur complement system from the augmented linear + // least squares problem [A;D] x = [b;0]. The left hand side and the + // right hand side of the reduced linear system are returned in lhs + // and rhs respectively. + // + // It is the caller's responsibility to construct and initialize + // lhs. Depending upon the structure of the lhs object passed here, + // the full or a submatrix of the Schur complement will be computed. + // + // Since the Schur complement is a symmetric matrix, only the upper + // triangular part of the Schur complement is computed. + virtual void Eliminate(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + BlockRandomAccessMatrix* lhs, + double* rhs) = 0; + + // Given values for the variables z in the F block of A, solve for + // the optimal values of the variables y corresponding to the E + // block in A. + virtual void BackSubstitute(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + const double* z, + double* y) = 0; + // Factory + static SchurEliminatorBase* Create(const LinearSolver::Options& options); +}; + +// Templated implementation of the SchurEliminatorBase interface. The +// templating is on the sizes of the row, e and f blocks sizes in the +// input matrix. In many problems, the sizes of one or more of these +// blocks are constant, in that case, its worth passing these +// parameters as template arguments so that they are visible to the +// compiler and can be used for compile time optimization of the low +// level linear algebra routines. +// +// This implementation is mulithreaded using OpenMP. The level of +// parallelism is controlled by LinearSolver::Options::num_threads. +template +class SchurEliminator : public SchurEliminatorBase { + public: + explicit SchurEliminator(const LinearSolver::Options& options) + : num_threads_(options.num_threads) { + } + + // SchurEliminatorBase Interface + virtual ~SchurEliminator(); + virtual void Init(int num_eliminate_blocks, + const CompressedRowBlockStructure* bs); + virtual void Eliminate(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + BlockRandomAccessMatrix* lhs, + double* rhs); + virtual void BackSubstitute(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + const double* z, + double* y); + + private: + // Chunk objects store combinatorial information needed to + // efficiently eliminate a whole chunk out of the least squares + // problem. Consider the first chunk in the example matrix above. + // + // [ y1 0 0 0 | z1 0 0 0 z5] + // [ y1 0 0 0 | z1 z2 0 0 0] + // + // One of the intermediate quantities that needs to be calculated is + // for each row the product of the y block transposed with the + // non-zero z block, and the sum of these blocks across rows. A + // temporary array "buffer_" is used for computing and storing them + // and the buffer_layout maps the indices of the z-blocks to + // position in the buffer_ array. The size of the chunk is the + // number of row blocks/residual blocks for the particular y block + // being considered. + // + // For the example chunk shown above, + // + // size = 2 + // + // The entries of buffer_layout will be filled in the following order. + // + // buffer_layout[z1] = 0 + // buffer_layout[z5] = y1 * z1 + // buffer_layout[z2] = y1 * z1 + y1 * z5 + typedef map BufferLayoutType; + struct Chunk { + Chunk() : size(0) {} + int size; + int start; + BufferLayoutType buffer_layout; + }; + + void ChunkDiagonalBlockAndGradient( + const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + typename EigenTypes::Matrix* eet, + typename EigenTypes::Vector* g, + double* buffer, + BlockRandomAccessMatrix* lhs); + + void UpdateRhs(const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + const Vector& inverse_ete_g, + double* rhs); + + void ChunkOuterProduct(const CompressedRowBlockStructure* bs, + const Matrix& inverse_eet, + const double* buffer, + const BufferLayoutType& buffer_layout, + BlockRandomAccessMatrix* lhs); + void EBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs); + + + void NoEBlockRowsUpdate(const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + BlockRandomAccessMatrix* lhs, + double* rhs); + + void NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs); + + int num_eliminate_blocks_; + + // Block layout of the columns of the reduced linear system. Since + // the f blocks can be of varying size, this vector stores the + // position of each f block in the row/col of the reduced linear + // system. Thus lhs_row_layout_[i] is the row/col position of the + // i^th f block. + vector lhs_row_layout_; + + // Combinatorial structure of the chunks in A. For more information + // see the documentation of the Chunk object above. + vector chunks_; + + // Buffer to store the products of the y and z blocks generated + // during the elimination phase. + scoped_array buffer_; + int buffer_size_; + int num_threads_; + int uneliminated_row_begins_; + + // Locks for the blocks in the right hand side of the reduced linear + // system. + vector rhs_locks_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_ELIMINATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h new file mode 100644 index 00000000000..a388d005424 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h @@ -0,0 +1,702 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// TODO(sameeragarwal): row_block_counter can perhaps be replaced by +// Chunk::start ? + +#ifndef CERES_INTERNAL_SCHUR_ELIMINATOR_IMPL_H_ +#define CERES_INTERNAL_SCHUR_ELIMINATOR_IMPL_H_ + +#ifdef CERES_USE_OPENMP +#include +#endif + +// Eigen has an internal threshold switching between different matrix +// multiplication algorithms. In particular for matrices larger than +// EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD it uses a cache friendly +// matrix matrix product algorithm that has a higher setup cost. For +// matrix sizes close to this threshold, especially when the matrices +// are thin and long, the default choice may not be optimal. This is +// the case for us, as the default choice causes a 30% performance +// regression when we moved from Eigen2 to Eigen3. +#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 10 + +#include +#include +#include +#include "Eigen/Dense" +#include "ceres/block_random_access_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/block_structure.h" +#include "ceres/map_util.h" +#include "ceres/schur_eliminator.h" +#include "ceres/stl_util.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +template +SchurEliminator::~SchurEliminator() { + STLDeleteElements(&rhs_locks_); +} + +template +void +SchurEliminator:: +Init(int num_eliminate_blocks, const CompressedRowBlockStructure* bs) { + CHECK_GT(num_eliminate_blocks, 0) + << "SchurComplementSolver cannot be initialized with " + << "num_eliminate_blocks = 0."; + + num_eliminate_blocks_ = num_eliminate_blocks; + + const int num_col_blocks = bs->cols.size(); + const int num_row_blocks = bs->rows.size(); + + buffer_size_ = 1; + chunks_.clear(); + lhs_row_layout_.clear(); + + int lhs_num_rows = 0; + // Add a map object for each block in the reduced linear system + // and build the row/column block structure of the reduced linear + // system. + lhs_row_layout_.resize(num_col_blocks - num_eliminate_blocks_); + for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) { + lhs_row_layout_[i - num_eliminate_blocks_] = lhs_num_rows; + lhs_num_rows += bs->cols[i].size; + } + + int r = 0; + // Iterate over the row blocks of A, and detect the chunks. The + // matrix should already have been ordered so that all rows + // containing the same y block are vertically contiguous. Along + // the way also compute the amount of space each chunk will need + // to perform the elimination. + while (r < num_row_blocks) { + const int chunk_block_id = bs->rows[r].cells.front().block_id; + if (chunk_block_id >= num_eliminate_blocks_) { + break; + } + + chunks_.push_back(Chunk()); + Chunk& chunk = chunks_.back(); + chunk.size = 0; + chunk.start = r; + int buffer_size = 0; + const int e_block_size = bs->cols[chunk_block_id].size; + + // Add to the chunk until the first block in the row is + // different than the one in the first row for the chunk. + while (r + chunk.size < num_row_blocks) { + const CompressedRow& row = bs->rows[r + chunk.size]; + if (row.cells.front().block_id != chunk_block_id) { + break; + } + + // Iterate over the blocks in the row, ignoring the first + // block since it is the one to be eliminated. + for (int c = 1; c < row.cells.size(); ++c) { + const Cell& cell = row.cells[c]; + if (InsertIfNotPresent( + &(chunk.buffer_layout), cell.block_id, buffer_size)) { + buffer_size += e_block_size * bs->cols[cell.block_id].size; + } + } + + buffer_size_ = max(buffer_size, buffer_size_); + ++chunk.size; + } + + CHECK_GT(chunk.size, 0); + r += chunk.size; + } + const Chunk& chunk = chunks_.back(); + + uneliminated_row_begins_ = chunk.start + chunk.size; + if (num_threads_ > 1) { + random_shuffle(chunks_.begin(), chunks_.end()); + } + + buffer_.reset(new double[buffer_size_ * num_threads_]); + + STLDeleteElements(&rhs_locks_); + rhs_locks_.resize(num_col_blocks - num_eliminate_blocks_); + for (int i = 0; i < num_col_blocks - num_eliminate_blocks_; ++i) { + rhs_locks_[i] = new Mutex; + } + + VLOG(1) << "Eliminator threads: " << num_threads_; +} + +template +void +SchurEliminator:: +Eliminate(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + BlockRandomAccessMatrix* lhs, + double* rhs) { + if (lhs->num_rows() > 0) { + lhs->SetZero(); + VectorRef(rhs, lhs->num_rows()).setZero(); + } + + const CompressedRowBlockStructure* bs = A->block_structure(); + const int num_col_blocks = bs->cols.size(); + + // Add the diagonal to the schur complement. + if (D != NULL) { +#pragma omp parallel for num_threads(num_threads_) schedule(dynamic) + for (int i = num_eliminate_blocks_; i < num_col_blocks; ++i) { + const int block_id = i - num_eliminate_blocks_; + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block_id, block_id, + &r, &c, + &row_stride, &col_stride); + if (cell_info != NULL) { + const int block_size = bs->cols[i].size; + typename EigenTypes::ConstVectorRef + diag(D + bs->cols[i].position, block_size); + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block_size, block_size).diagonal() + += diag.array().square().matrix(); + } + } + } + + // Eliminate y blocks one chunk at a time. For each chunk,x3 + // compute the entries of the normal equations and the gradient + // vector block corresponding to the y block and then apply + // Gaussian elimination to them. The matrix ete stores the normal + // matrix corresponding to the block being eliminated and array + // buffer_ contains the non-zero blocks in the row corresponding + // to this y block in the normal equations. This computation is + // done in ChunkDiagonalBlockAndGradient. UpdateRhs then applies + // gaussian elimination to the rhs of the normal equations, + // updating the rhs of the reduced linear system by modifying rhs + // blocks for all the z blocks that share a row block/residual + // term with the y block. EliminateRowOuterProduct does the + // corresponding operation for the lhs of the reduced linear + // system. +#pragma omp parallel for num_threads(num_threads_) schedule(dynamic) + for (int i = 0; i < chunks_.size(); ++i) { +#ifdef CERES_USE_OPENMP + int thread_id = omp_get_thread_num(); +#else + int thread_id = 0; +#endif + double* buffer = buffer_.get() + thread_id * buffer_size_; + const Chunk& chunk = chunks_[i]; + const int e_block_id = bs->rows[chunk.start].cells.front().block_id; + const int e_block_size = bs->cols[e_block_id].size; + + VectorRef(buffer, buffer_size_).setZero(); + + typename EigenTypes::Matrix + ete(e_block_size, e_block_size); + + if (D != NULL) { + const typename EigenTypes::ConstVectorRef + diag(D + bs->cols[e_block_id].position, e_block_size); + ete = diag.array().square().matrix().asDiagonal(); + } else { + ete.setZero(); + } + + typename EigenTypes::Vector g(e_block_size); + g.setZero(); + + // We are going to be computing + // + // S += F'F - F'E(E'E)^{-1}E'F + // + // for each Chunk. The computation is broken down into a number of + // function calls as below. + + // Compute the outer product of the e_blocks with themselves (ete + // = E'E). Compute the product of the e_blocks with the + // corresonding f_blocks (buffer = E'F), the gradient of the terms + // in this chunk (g) and add the outer product of the f_blocks to + // Schur complement (S += F'F). + ChunkDiagonalBlockAndGradient( + chunk, A, b, chunk.start, &ete, &g, buffer, lhs); + + // Normally one wouldn't compute the inverse explicitly, but + // e_block_size will typically be a small number like 3, in + // which case its much faster to compute the inverse once and + // use it to multiply other matrices/vectors instead of doing a + // Solve call over and over again. + typename EigenTypes::Matrix inverse_ete = + ete + .template selfadjointView() + .ldlt() + .solve(Matrix::Identity(e_block_size, e_block_size)); + + // For the current chunk compute and update the rhs of the reduced + // linear system. + // + // rhs = F'b - F'E(E'E)^(-1) E'b + UpdateRhs(chunk, A, b, chunk.start, inverse_ete * g, rhs); + + // S -= F'E(E'E)^{-1}E'F + ChunkOuterProduct(bs, inverse_ete, buffer, chunk.buffer_layout, lhs); + } + + // For rows with no e_blocks, the schur complement update reduces to + // S += F'F. + NoEBlockRowsUpdate(A, b, uneliminated_row_begins_, lhs, rhs); +} + +template +void +SchurEliminator:: +BackSubstitute(const BlockSparseMatrixBase* A, + const double* b, + const double* D, + const double* z, + double* y) { + const CompressedRowBlockStructure* bs = A->block_structure(); +#pragma omp parallel for num_threads(num_threads_) schedule(dynamic) + for (int i = 0; i < chunks_.size(); ++i) { + const Chunk& chunk = chunks_[i]; + const int e_block_id = bs->rows[chunk.start].cells.front().block_id; + const int e_block_size = bs->cols[e_block_id].size; + + typename EigenTypes::VectorRef y_block( + y + bs->cols[e_block_id].position, e_block_size); + + typename EigenTypes::Matrix + ete(e_block_size, e_block_size); + if (D != NULL) { + const typename EigenTypes::ConstVectorRef + diag(D + bs->cols[e_block_id].position, e_block_size); + ete = diag.array().square().matrix().asDiagonal(); + } else { + ete.setZero(); + } + + for (int j = 0; j < chunk.size; ++j) { + const CompressedRow& row = bs->rows[chunk.start + j]; + const double* row_values = A->RowBlockValues(chunk.start + j); + const Cell& e_cell = row.cells.front(); + DCHECK_EQ(e_block_id, e_cell.block_id); + const typename EigenTypes::ConstMatrixRef + e_block(row_values + e_cell.position, + row.block.size, + e_block_size); + + typename EigenTypes::Vector + sj = + typename EigenTypes::ConstVectorRef + (b + bs->rows[chunk.start + j].block.position, + row.block.size); + + for (int c = 1; c < row.cells.size(); ++c) { + const int f_block_id = row.cells[c].block_id; + const int f_block_size = bs->cols[f_block_id].size; + const typename EigenTypes::ConstMatrixRef + f_block(row_values + row.cells[c].position, + row.block.size, f_block_size); + const int r_block = f_block_id - num_eliminate_blocks_; + + sj -= f_block * + typename EigenTypes::ConstVectorRef + (z + lhs_row_layout_[r_block], f_block_size); + } + + y_block += e_block.transpose() * sj; + ete.template selfadjointView() + .rankUpdate(e_block.transpose(), 1.0); + } + + y_block = + ete + .template selfadjointView() + .ldlt() + .solve(y_block); + } +} + +// Update the rhs of the reduced linear system. Compute +// +// F'b - F'E(E'E)^(-1) E'b +template +void +SchurEliminator:: +UpdateRhs(const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + const Vector& inverse_ete_g, + double* rhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + const int e_block_size = inverse_ete_g.rows(); + int b_pos = bs->rows[row_block_counter].block.position; + for (int j = 0; j < chunk.size; ++j) { + const CompressedRow& row = bs->rows[row_block_counter + j]; + const double *row_values = A->RowBlockValues(row_block_counter + j); + const Cell& e_cell = row.cells.front(); + + const typename EigenTypes::ConstMatrixRef + e_block(row_values + e_cell.position, + row.block.size, + e_block_size); + + const typename EigenTypes::Vector + sj = + typename EigenTypes::ConstVectorRef + (b + b_pos, row.block.size) - e_block * (inverse_ete_g); + + for (int c = 1; c < row.cells.size(); ++c) { + const int block_id = row.cells[c].block_id; + const int block_size = bs->cols[block_id].size; + const typename EigenTypes::ConstMatrixRef + b(row_values + row.cells[c].position, + row.block.size, block_size); + + const int block = block_id - num_eliminate_blocks_; + MutexLock l(rhs_locks_[block]); + typename EigenTypes::VectorRef + (rhs + lhs_row_layout_[block], block_size).noalias() + += b.transpose() * sj; + } + b_pos += row.block.size; + } +} + +// Given a Chunk - set of rows with the same e_block, e.g. in the +// following Chunk with two rows. +// +// E F +// [ y11 0 0 0 | z11 0 0 0 z51] +// [ y12 0 0 0 | z12 z22 0 0 0] +// +// this function computes twp matrices. The diagonal block matrix +// +// ete = y11 * y11' + y12 * y12' +// +// and the off diagonal blocks in the Guass Newton Hessian. +// +// buffer = [y11'(z11 + z12), y12' * z22, y11' * z51] +// +// which are zero compressed versions of the block sparse matrices E'E +// and E'F. +// +// and the gradient of the e_block, E'b. +template +void +SchurEliminator:: +ChunkDiagonalBlockAndGradient( + const Chunk& chunk, + const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + typename EigenTypes::Matrix* ete, + typename EigenTypes::Vector* g, + double* buffer, + BlockRandomAccessMatrix* lhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + + int b_pos = bs->rows[row_block_counter].block.position; + const int e_block_size = ete->rows(); + + // Iterate over the rows in this chunk, for each row, compute the + // contribution of its F blocks to the Schur complement, the + // contribution of its E block to the matrix EE' (ete), and the + // corresponding block in the gradient vector. + for (int j = 0; j < chunk.size; ++j) { + const CompressedRow& row = bs->rows[row_block_counter + j]; + const double *row_values = A->RowBlockValues(row_block_counter + j); + + if (row.cells.size() > 1) { + EBlockRowOuterProduct(A, row_block_counter + j, lhs); + } + + // Extract the e_block, ETE += E_i' E_i + const Cell& e_cell = row.cells.front(); + const typename EigenTypes::ConstMatrixRef + e_block(row_values + e_cell.position, + row.block.size, + e_block_size); + + ete->template selfadjointView() + .rankUpdate(e_block.transpose(), 1.0); + + // g += E_i' b_i + g->noalias() += e_block.transpose() * + typename EigenTypes::ConstVectorRef + (b + b_pos, row.block.size); + + // buffer = E'F. This computation is done by iterating over the + // f_blocks for each row in the chunk. + for (int c = 1; c < row.cells.size(); ++c) { + const int f_block_id = row.cells[c].block_id; + const int f_block_size = bs->cols[f_block_id].size; + const typename EigenTypes::ConstMatrixRef + f_block(row_values + row.cells[c].position, + row.block.size, f_block_size); + + double* buffer_ptr = + buffer + FindOrDie(chunk.buffer_layout, f_block_id); + + typename EigenTypes::MatrixRef + (buffer_ptr, e_block_size, f_block_size).noalias() + += e_block.transpose() * f_block; + } + b_pos += row.block.size; + } +} + +// Compute the outer product F'E(E'E)^{-1}E'F and subtract it from the +// Schur complement matrix, i.e +// +// S -= F'E(E'E)^{-1}E'F. +template +void +SchurEliminator:: +ChunkOuterProduct(const CompressedRowBlockStructure* bs, + const Matrix& inverse_ete, + const double* buffer, + const BufferLayoutType& buffer_layout, + BlockRandomAccessMatrix* lhs) { + // This is the most computationally expensive part of this + // code. Profiling experiments reveal that the bottleneck is not the + // computation of the right-hand matrix product, but memory + // references to the left hand side. + const int e_block_size = inverse_ete.rows(); + BufferLayoutType::const_iterator it1 = buffer_layout.begin(); + // S(i,j) -= bi' * ete^{-1} b_j + for (; it1 != buffer_layout.end(); ++it1) { + const int block1 = it1->first - num_eliminate_blocks_; + const int block1_size = bs->cols[it1->first].size; + + const typename EigenTypes::ConstMatrixRef + b1(buffer + it1->second, e_block_size, block1_size); + const typename EigenTypes::Matrix + b1_transpose_inverse_ete = b1.transpose() * inverse_ete; + + BufferLayoutType::const_iterator it2 = it1; + for (; it2 != buffer_layout.end(); ++it2) { + const int block2 = it2->first - num_eliminate_blocks_; + + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + const int block2_size = bs->cols[it2->first].size; + const typename EigenTypes::ConstMatrixRef + b2(buffer + it2->second, e_block_size, block2_size); + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + + // We explicitly construct a block object here instead of using + // m.block(), as m.block() variant of the constructor does not + // allow mixing of template sizing and runtime sizing parameters + // like the Matrix class does. + Eigen::Block + block(m, r, c, block1_size, block2_size); + block.noalias() -= b1_transpose_inverse_ete * b2; + } + } +} + +// For rows with no e_blocks, the schur complement update reduces to S +// += F'F. This function iterates over the rows of A with no e_block, +// and calls NoEBlockRowOuterProduct on each row. +template +void +SchurEliminator:: +NoEBlockRowsUpdate(const BlockSparseMatrixBase* A, + const double* b, + int row_block_counter, + BlockRandomAccessMatrix* lhs, + double* rhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + for (; row_block_counter < bs->rows.size(); ++row_block_counter) { + const CompressedRow& row = bs->rows[row_block_counter]; + const double *row_values = A->RowBlockValues(row_block_counter); + for (int c = 0; c < row.cells.size(); ++c) { + const int block_id = row.cells[c].block_id; + const int block_size = bs->cols[block_id].size; + const int block = block_id - num_eliminate_blocks_; + VectorRef(rhs + lhs_row_layout_[block], block_size).noalias() + += (ConstMatrixRef(row_values + row.cells[c].position, + row.block.size, block_size).transpose() * + ConstVectorRef(b + row.block.position, row.block.size)); + } + NoEBlockRowOuterProduct(A, row_block_counter, lhs); + } +} + + +// A row r of A, which has no e_blocks gets added to the Schur +// Complement as S += r r'. This function is responsible for computing +// the contribution of a single row r to the Schur complement. It is +// very similar in structure to EBlockRowOuterProduct except for +// one difference. It does not use any of the template +// parameters. This is because the algorithm used for detecting the +// static structure of the matrix A only pays attention to rows with +// e_blocks. This is becase rows without e_blocks are rare and +// typically arise from regularization terms in the original +// optimization problem, and have a very different structure than the +// rows with e_blocks. Including them in the static structure +// detection will lead to most template parameters being set to +// dynamic. Since the number of rows without e_blocks is small, the +// lack of templating is not an issue. +template +void +SchurEliminator:: +NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + const CompressedRow& row = bs->rows[row_block_index]; + const double *row_values = A->RowBlockValues(row_block_index); + for (int i = 0; i < row.cells.size(); ++i) { + const int block1 = row.cells[i].block_id - num_eliminate_blocks_; + DCHECK_GE(block1, 0); + + const int block1_size = bs->cols[row.cells[i].block_id].size; + const ConstMatrixRef b1(row_values + row.cells[i].position, + row.block.size, block1_size); + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block1, + &r, &c, + &row_stride, &col_stride); + if (cell_info != NULL) { + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block1_size, block1_size) + .selfadjointView() + .rankUpdate(b1.transpose(), 1.0); + } + + for (int j = i + 1; j < row.cells.size(); ++j) { + const int block2 = row.cells[j].block_id - num_eliminate_blocks_; + DCHECK_GE(block2, 0); + DCHECK_LT(block1, block2); + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + const int block2_size = bs->cols[row.cells[j].block_id].size; + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block1_size, block2_size).noalias() += + b1.transpose() * ConstMatrixRef(row_values + row.cells[j].position, + row.block.size, + block2_size); + } + } +} + +// For a row with an e_block, compute the contribition S += F'F. This +// function has the same structure as NoEBlockRowOuterProduct, except +// that this function uses the template parameters. +template +void +SchurEliminator:: +EBlockRowOuterProduct(const BlockSparseMatrixBase* A, + int row_block_index, + BlockRandomAccessMatrix* lhs) { + const CompressedRowBlockStructure* bs = A->block_structure(); + const CompressedRow& row = bs->rows[row_block_index]; + const double *row_values = A->RowBlockValues(row_block_index); + for (int i = 1; i < row.cells.size(); ++i) { + const int block1 = row.cells[i].block_id - num_eliminate_blocks_; + DCHECK_GE(block1, 0); + + const int block1_size = bs->cols[row.cells[i].block_id].size; + const typename EigenTypes::ConstMatrixRef + b1(row_values + row.cells[i].position, + row.block.size, block1_size); + { + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block1, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + + Eigen::Block + block(m, r, c, block1_size, block1_size); + block.template selfadjointView() + .rankUpdate(b1.transpose(), 1.0); + } + + for (int j = i + 1; j < row.cells.size(); ++j) { + const int block2 = row.cells[j].block_id - num_eliminate_blocks_; + DCHECK_GE(block2, 0); + DCHECK_LT(block1, block2); + const int block2_size = bs->cols[row.cells[j].block_id].size; + int r, c, row_stride, col_stride; + CellInfo* cell_info = lhs->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + if (cell_info == NULL) { + continue; + } + + const typename EigenTypes::ConstMatrixRef + b2(row_values + row.cells[j].position, + row.block.size, + block2_size); + + MutexLock l(&cell_info->m); + MatrixRef m(cell_info->values, row_stride, col_stride); + Eigen::Block + block(m, r, c, block1_size, block2_size); + block.noalias() += b1.transpose() * b2; + } + } +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_ELIMINATOR_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc new file mode 100644 index 00000000000..c4fc1da3c2f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc @@ -0,0 +1,113 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/schur_ordering.h" + +#include +#include "ceres/graph.h" +#include "ceres/graph_algorithms.h" +#include "ceres/map_util.h" +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/internal/scoped_ptr.h" + +CERES_HASH_NAMESPACE_START + +// Allow us to hash pointers as if they were int's +template<> struct hash< ::ceres::internal::ParameterBlock*> { + size_t operator()(::ceres::internal::ParameterBlock* x) const { + return reinterpret_cast(x); + } +}; + +CERES_HASH_NAMESPACE_END + +namespace ceres { +namespace internal { + +int ComputeSchurOrdering(const Program& program, + vector* ordering) { + CHECK_NOTNULL(ordering)->clear(); + + scoped_ptr > graph( + CHECK_NOTNULL(CreateHessianGraph(program))); + int independent_set_size = + IndependentSetOrdering(*graph, ordering); + const vector& parameter_blocks = program.parameter_blocks(); + + // Add the excluded blocks to back of the ordering vector. + for (int i = 0; i < parameter_blocks.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks[i]; + if (parameter_block->IsConstant()) { + ordering->push_back(parameter_block); + } + } + + return independent_set_size; +} + +Graph* +CreateHessianGraph(const Program& program) { + Graph* graph = new Graph; + const vector& parameter_blocks = program.parameter_blocks(); + for (int i = 0; i < parameter_blocks.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks[i]; + if (!parameter_block->IsConstant()) { + graph->AddVertex(parameter_block); + } + } + + const vector& residual_blocks = program.residual_blocks(); + for (int i = 0; i < residual_blocks.size(); ++i) { + const ResidualBlock* residual_block = residual_blocks[i]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + ParameterBlock* const* parameter_blocks = + residual_block->parameter_blocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + if (parameter_blocks[j]->IsConstant()) { + continue; + } + + for (int k = j + 1; k < num_parameter_blocks; ++k) { + if (parameter_blocks[k]->IsConstant()) { + continue; + } + + graph->AddEdge(parameter_blocks[j], parameter_blocks[k]); + } + } + } + + return graph; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h new file mode 100644 index 00000000000..1f9a4ff354f --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h @@ -0,0 +1,74 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Compute a parameter block ordering for use with the Schur +// complement based algorithms. + +#ifndef CERES_INTERNAL_SCHUR_ORDERING_H_ +#define CERES_INTERNAL_SCHUR_ORDERING_H_ + +#include +#include "ceres/graph.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class Program; +class ParameterBlock; + +// Uses an approximate independent set ordering to order the parameter +// blocks of a problem so that it is suitable for use with Schur +// complement based solvers. The output variable ordering contains an +// ordering of the parameter blocks and the return value is size of +// the independent set or the number of e_blocks (see +// schur_complement_solver.h for an explanation). Constant parameters +// are added to the end. +// +// The ordering vector has the structure +// +// ordering = [independent set, +// complement of the independent set, +// fixed blocks] +int ComputeSchurOrdering(const Program& program, + vector* ordering); + + +// Builds a graph on the parameter blocks of a Problem, whose +// structure reflects the sparsity structure of the Hessian. Each +// vertex corresponds to a parameter block in the Problem except for +// parameter blocks that are marked constant. An edge connects two +// parameter blocks, if they co-occur in a residual block. +Graph* CreateHessianGraph(const Program& program); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCHUR_ORDERING_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc new file mode 100644 index 00000000000..6f0ceefd87d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.cc @@ -0,0 +1,78 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/scratch_evaluate_preparer.h" + +#include "ceres/parameter_block.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" + +namespace ceres { +namespace internal { + +ScratchEvaluatePreparer* ScratchEvaluatePreparer::Create( + const Program &program, + int num_threads) { + ScratchEvaluatePreparer* preparers = new ScratchEvaluatePreparer[num_threads]; + int max_derivatives_per_residual_block = + program.MaxDerivativesPerResidualBlock(); + for (int i = 0; i < num_threads; i++) { + preparers[i].Init(max_derivatives_per_residual_block); + } + return preparers; +} + +void ScratchEvaluatePreparer::Init(int max_derivatives_per_residual_block) { + jacobian_scratch_.reset( + new double[max_derivatives_per_residual_block]); +} + +// Point the jacobian blocks into the scratch area of this evaluate preparer. +void ScratchEvaluatePreparer::Prepare(const ResidualBlock* residual_block, + int /* residual_block_index */, + SparseMatrix* /* jacobian */, + double** jacobians) { + double* jacobian_block_cursor = jacobian_scratch_.get(); + int num_residuals = residual_block->NumResiduals(); + int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (parameter_block->IsConstant()) { + jacobians[j] = NULL; + } else { + jacobians[j] = jacobian_block_cursor; + jacobian_block_cursor += num_residuals * parameter_block->LocalSize(); + } + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h new file mode 100644 index 00000000000..6b127081976 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/scratch_evaluate_preparer.h @@ -0,0 +1,69 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// +// A scratch evaluate preparer provides temporary storage for the jacobians that +// are created when running user-provided cost functions. The evaluator takes +// care to avoid evaluating the jacobian for fixed parameters. + +#ifndef CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ +#define CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ + +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +class Program; +class ResidualBlock; +class SparseMatrix; + +class ScratchEvaluatePreparer { + public: + // Create num_threads ScratchEvaluatePreparers. + static ScratchEvaluatePreparer* Create(const Program &program, + int num_threads); + + // EvaluatePreparer interface + void Init(int max_derivatives_per_residual_block); + void Prepare(const ResidualBlock* residual_block, + int residual_block_index, + SparseMatrix* jacobian, + double** jacobians); + + private: + // Scratch space for the jacobians; each jacobian is packed one after another. + // There is enough scratch to hold all the jacobians for the largest residual. + scoped_array jacobian_scratch_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc new file mode 100644 index 00000000000..77f04d1d918 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc @@ -0,0 +1,230 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/solver.h" + +#include +#include "ceres/levenberg_marquardt.h" +#include "ceres/program.h" +#include "ceres/solver_impl.h" +#include "ceres/stringprintf.h" +#include "ceres/problem.h" + +namespace ceres { + +Solver::~Solver() {} + +// TODO(sameeragarwal): The timing code here should use a sub-second +// timer. +void Solver::Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary) { + time_t start_time_seconds = time(NULL); + internal::SolverImpl::Solve(options, problem, summary); + summary->total_time_in_seconds = time(NULL) - start_time_seconds; + summary->preprocessor_time_in_seconds = + summary->total_time_in_seconds - summary->minimizer_time_in_seconds; +} + +void Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary) { + time_t start_time_seconds = time(NULL); + internal::SolverImpl::Solve(options, problem, summary); + summary->total_time_in_seconds = time(NULL) - start_time_seconds; + summary->preprocessor_time_in_seconds = + summary->total_time_in_seconds - summary->minimizer_time_in_seconds; +} + +Solver::Summary::Summary() + // Invalid values for most fields, to ensure that we are not + // accidentally reporting default values. + : termination_type(DID_NOT_RUN), + initial_cost(-1.0), + final_cost(-1.0), + fixed_cost(-1.0), + num_successful_steps(-1), + num_unsuccessful_steps(-1), + preprocessor_time_in_seconds(-1.0), + minimizer_time_in_seconds(-1.0), + total_time_in_seconds(-1.0), + num_parameter_blocks(-1), + num_parameters(-1), + num_residual_blocks(-1), + num_residuals(-1), + num_parameter_blocks_reduced(-1), + num_parameters_reduced(-1), + num_residual_blocks_reduced(-1), + num_residuals_reduced(-1), + num_eliminate_blocks_given(-1), + num_eliminate_blocks_used(-1), + num_threads_given(-1), + num_threads_used(-1), + num_linear_solver_threads_given(-1), + num_linear_solver_threads_used(-1), + linear_solver_type_given(SPARSE_NORMAL_CHOLESKY), + linear_solver_type_used(SPARSE_NORMAL_CHOLESKY), + preconditioner_type(IDENTITY), + ordering_type(NATURAL) { +} + +string Solver::Summary::BriefReport() const { + string report = "Ceres Solver Report: "; + if (termination_type == DID_NOT_RUN) { + CHECK(!error.empty()) + << "Solver terminated with DID_NOT_RUN but the solver did not " + << "return a reason. This is a Ceres error. Please report this " + << "to the Ceres team"; + return report + "Termination: DID_NOT_RUN, because " + error; + } + + internal::StringAppendF(&report, "Iterations: %d", + num_successful_steps + num_unsuccessful_steps); + internal::StringAppendF(&report, ", Initial cost: %e", initial_cost); + + // If the solver failed or was aborted, then the final_cost has no + // meaning. + if (termination_type != NUMERICAL_FAILURE && + termination_type != USER_ABORT) { + internal::StringAppendF(&report, ", Final cost: %e", final_cost); + } + + internal::StringAppendF(&report, ", Termination: %s.", + SolverTerminationTypeToString(termination_type)); + return report; +}; + +string Solver::Summary::FullReport() const { + string report = + "\n" + "Ceres Solver Report\n" + "-------------------\n"; + + if (termination_type == DID_NOT_RUN) { + internal::StringAppendF(&report, " Original\n"); + internal::StringAppendF(&report, "Parameter blocks % 10d\n", + num_parameter_blocks); + internal::StringAppendF(&report, "Parameters % 10d\n", + num_parameters); + internal::StringAppendF(&report, "Residual blocks % 10d\n", + num_residual_blocks); + internal::StringAppendF(&report, "Residual % 10d\n\n", + num_residuals); + } else { + internal::StringAppendF(&report, "%45s %21s\n", "Original", "Reduced"); + internal::StringAppendF(&report, "Parameter blocks % 25d% 25d\n", + num_parameter_blocks, num_parameter_blocks_reduced); + internal::StringAppendF(&report, "Parameters % 25d% 25d\n", + num_parameters, num_parameters_reduced); + internal::StringAppendF(&report, "Residual blocks % 25d% 25d\n", + num_residual_blocks, num_residual_blocks_reduced); + internal::StringAppendF(&report, "Residual % 25d% 25d\n\n", + num_residuals, num_residuals_reduced); + } + + internal::StringAppendF(&report, "%45s %21s\n", "Given", "Used"); + internal::StringAppendF(&report, "Linear solver %25s%25s\n", + LinearSolverTypeToString(linear_solver_type_given), + LinearSolverTypeToString(linear_solver_type_used)); + + if (linear_solver_type_given == CGNR || + linear_solver_type_given == ITERATIVE_SCHUR) { + internal::StringAppendF(&report, "Preconditioner %25s%25s\n", + PreconditionerTypeToString(preconditioner_type), + PreconditionerTypeToString(preconditioner_type)); + } else { + internal::StringAppendF(&report, "Preconditioner %25s%25s\n", + "N/A", "N/A"); + } + + internal::StringAppendF(&report, "Ordering %25s%25s\n", + OrderingTypeToString(ordering_type), + OrderingTypeToString(ordering_type)); + + if (IsSchurType(linear_solver_type_given)) { + if (ordering_type == SCHUR) { + internal::StringAppendF(&report, "num_eliminate_blocks%25s% 25d\n", + "N/A", + num_eliminate_blocks_used); + } else { + internal::StringAppendF(&report, "num_eliminate_blocks% 25d% 25d\n", + num_eliminate_blocks_given, + num_eliminate_blocks_used); + } + } + + internal::StringAppendF(&report, "Threads: % 25d% 25d\n", + num_threads_given, num_threads_used); + internal::StringAppendF(&report, "Linear Solver Threads:% 23d% 25d\n", + num_linear_solver_threads_given, + num_linear_solver_threads_used); + + + if (termination_type == DID_NOT_RUN) { + CHECK(!error.empty()) + << "Solver terminated with DID_NOT_RUN but the solver did not " + << "return a reason. This is a Ceres error. Please report this " + << "to the Ceres team"; + internal::StringAppendF(&report, "Termination: %20s\n", + "DID_NOT_RUN"); + internal::StringAppendF(&report, "Reason: %s\n", error.c_str()); + return report; + } + + internal::StringAppendF(&report, "\nCost:\n"); + internal::StringAppendF(&report, "Initial % 30e\n", initial_cost); + if (termination_type != NUMERICAL_FAILURE && termination_type != USER_ABORT) { + internal::StringAppendF(&report, "Final % 30e\n", final_cost); + internal::StringAppendF(&report, "Change % 30e\n", + initial_cost - final_cost); + } + + internal::StringAppendF(&report, "\nNumber of iterations:\n"); + internal::StringAppendF(&report, "Successful % 20d\n", + num_successful_steps); + internal::StringAppendF(&report, "Unsuccessful % 20d\n", + num_unsuccessful_steps); + internal::StringAppendF(&report, "Total % 20d\n", + num_successful_steps + num_unsuccessful_steps); + internal::StringAppendF(&report, "\nTime (in seconds):\n"); + internal::StringAppendF(&report, "Preprocessor % 25e\n", + preprocessor_time_in_seconds); + internal::StringAppendF(&report, "Minimizer % 25e\n", + minimizer_time_in_seconds); + internal::StringAppendF(&report, "Total % 25e\n", + total_time_in_seconds); + + internal::StringAppendF(&report, "Termination: %25s\n", + SolverTerminationTypeToString(termination_type)); + return report; +}; + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc new file mode 100644 index 00000000000..ed07d9dc6d7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc @@ -0,0 +1,693 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include "ceres/solver_impl.h" + +#include // NOLINT +#include +#include "ceres/evaluator.h" +#include "ceres/gradient_checking_cost_function.h" +#include "ceres/levenberg_marquardt.h" +#include "ceres/linear_solver.h" +#include "ceres/map_util.h" +#include "ceres/minimizer.h" +#include "ceres/parameter_block.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/schur_ordering.h" +#include "ceres/stringprintf.h" +#include "ceres/iteration_callback.h" +#include "ceres/problem.h" + +namespace ceres { +namespace internal { +namespace { + +void EvaluateCostAndResiduals(ProblemImpl* problem_impl, + double* cost, + vector* residuals) { + CHECK_NOTNULL(cost); + Program* program = CHECK_NOTNULL(problem_impl)->mutable_program(); + if (residuals != NULL) { + residuals->resize(program->NumResiduals()); + program->Evaluate(cost, &(*residuals)[0]); + } else { + program->Evaluate(cost, NULL); + } +} + +// Callback for updating the user's parameter blocks. Updates are only +// done if the step is successful. +class StateUpdatingCallback : public IterationCallback { + public: + StateUpdatingCallback(Program* program, double* parameters) + : program_(program), parameters_(parameters) {} + + CallbackReturnType operator()(const IterationSummary& summary) { + if (summary.step_is_successful) { + program_->StateVectorToParameterBlocks(parameters_); + program_->CopyParameterBlockStateToUserState(); + } + return SOLVER_CONTINUE; + } + + private: + Program* program_; + double* parameters_; +}; + +// Callback for logging the state of the minimizer to STDERR or STDOUT +// depending on the user's preferences and logging level. +class LoggingCallback : public IterationCallback { + public: + explicit LoggingCallback(bool log_to_stdout) + : log_to_stdout_(log_to_stdout) {} + + ~LoggingCallback() {} + + CallbackReturnType operator()(const IterationSummary& summary) { + const char* kReportRowFormat = + "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " + "rho:% 3.2e mu:% 3.2e li:% 3d"; + string output = StringPrintf(kReportRowFormat, + summary.iteration, + summary.cost, + summary.cost_change, + summary.gradient_max_norm, + summary.step_norm, + summary.relative_decrease, + summary.mu, + summary.linear_solver_iterations); + if (log_to_stdout_) { + cout << output << endl; + } else { + VLOG(1) << output; + } + return SOLVER_CONTINUE; + } + + private: + const bool log_to_stdout_; +}; + +} // namespace + +void SolverImpl::Minimize(const Solver::Options& options, + Program* program, + Evaluator* evaluator, + LinearSolver* linear_solver, + double* initial_parameters, + double* final_parameters, + Solver::Summary* summary) { + Minimizer::Options minimizer_options(options); + + LoggingCallback logging_callback(options.minimizer_progress_to_stdout); + if (options.logging_type != SILENT) { + minimizer_options.callbacks.push_back(&logging_callback); + } + + StateUpdatingCallback updating_callback(program, initial_parameters); + if (options.update_state_every_iteration) { + minimizer_options.callbacks.push_back(&updating_callback); + } + + LevenbergMarquardt levenberg_marquardt; + + time_t start_minimizer_time_seconds = time(NULL); + levenberg_marquardt.Minimize(minimizer_options, + evaluator, + linear_solver, + initial_parameters, + final_parameters, + summary); + summary->minimizer_time_in_seconds = + time(NULL) - start_minimizer_time_seconds; +} + +void SolverImpl::Solve(const Solver::Options& original_options, + Problem* problem, + Solver::Summary* summary) { + Solver::Options options(original_options); + +#ifndef CERES_USE_OPENMP + if (options.num_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_threads=1 is supported. Switching" + << "to single threaded mode."; + options.num_threads = 1; + } + if (options.num_linear_solver_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_linear_solver_threads=1 is supported. Switching" + << "to single threaded mode."; + options.num_linear_solver_threads = 1; + } +#endif + + // Reset the summary object to its default values; + *CHECK_NOTNULL(summary) = Solver::Summary(); + summary->linear_solver_type_given = options.linear_solver_type; + summary->num_eliminate_blocks_given = original_options.num_eliminate_blocks; + summary->num_threads_given = original_options.num_threads; + summary->num_linear_solver_threads_given = + original_options.num_linear_solver_threads; + summary->ordering_type = original_options.ordering_type; + + ProblemImpl* problem_impl = CHECK_NOTNULL(problem)->problem_impl_.get(); + + summary->num_parameter_blocks = problem_impl->NumParameterBlocks(); + summary->num_parameters = problem_impl->NumParameters(); + summary->num_residual_blocks = problem_impl->NumResidualBlocks(); + summary->num_residuals = problem_impl->NumResiduals(); + + summary->num_threads_used = options.num_threads; + + // Evaluate the initial cost and residual vector (if needed). The + // initial cost needs to be computed on the original unpreprocessed + // problem, as it is used to determine the value of the "fixed" part + // of the objective function after the problem has undergone + // reduction. Also the initial residuals are in the order in which + // the user added the ResidualBlocks to the optimization problem. + EvaluateCostAndResiduals(problem_impl, + &summary->initial_cost, + options.return_initial_residuals + ? &summary->initial_residuals + : NULL); + + // If the user requests gradient checking, construct a new + // ProblemImpl by wrapping the CostFunctions of problem_impl inside + // GradientCheckingCostFunction and replacing problem_impl with + // gradient_checking_problem_impl. + scoped_ptr gradient_checking_problem_impl; + if (options.check_gradients) { + VLOG(1) << "Checking Gradients"; + gradient_checking_problem_impl.reset( + CreateGradientCheckingProblemImpl( + problem_impl, + options.numeric_derivative_relative_step_size, + options.gradient_check_relative_precision)); + + // From here on, problem_impl will point to the GradientChecking version. + problem_impl = gradient_checking_problem_impl.get(); + } + + // Create the three objects needed to minimize: the transformed program, the + // evaluator, and the linear solver. + + scoped_ptr reduced_program( + CreateReducedProgram(&options, problem_impl, &summary->error)); + if (reduced_program == NULL) { + return; + } + + summary->num_parameter_blocks_reduced = reduced_program->NumParameterBlocks(); + summary->num_parameters_reduced = reduced_program->NumParameters(); + summary->num_residual_blocks_reduced = reduced_program->NumResidualBlocks(); + summary->num_residuals_reduced = reduced_program->NumResiduals(); + + scoped_ptr + linear_solver(CreateLinearSolver(&options, &summary->error)); + summary->linear_solver_type_used = options.linear_solver_type; + summary->preconditioner_type = options.preconditioner_type; + summary->num_eliminate_blocks_used = options.num_eliminate_blocks; + summary->num_linear_solver_threads_used = options.num_linear_solver_threads; + + if (linear_solver == NULL) { + return; + } + + if (!MaybeReorderResidualBlocks(options, + reduced_program.get(), + &summary->error)) { + return; + } + + scoped_ptr evaluator( + CreateEvaluator(options, reduced_program.get(), &summary->error)); + if (evaluator == NULL) { + return; + } + + // The optimizer works on contiguous parameter vectors; allocate some. + Vector initial_parameters(reduced_program->NumParameters()); + Vector optimized_parameters(reduced_program->NumParameters()); + + // Collect the discontiguous parameters into a contiguous state vector. + reduced_program->ParameterBlocksToStateVector(&initial_parameters[0]); + + // Run the optimization. + Minimize(options, + reduced_program.get(), + evaluator.get(), + linear_solver.get(), + initial_parameters.data(), + optimized_parameters.data(), + summary); + + // If the user aborted mid-optimization or the optimization + // terminated because of a numerical failure, then return without + // updating user state. + if (summary->termination_type == USER_ABORT || + summary->termination_type == NUMERICAL_FAILURE) { + return; + } + + // Push the contiguous optimized parameters back to the user's parameters. + reduced_program->StateVectorToParameterBlocks(&optimized_parameters[0]); + reduced_program->CopyParameterBlockStateToUserState(); + + // Return the final cost and residuals for the original problem. + EvaluateCostAndResiduals(problem->problem_impl_.get(), + &summary->final_cost, + options.return_final_residuals + ? &summary->final_residuals + : NULL); + + // Stick a fork in it, we're done. + return; +} + +// Strips varying parameters and residuals, maintaining order, and updating +// num_eliminate_blocks. +bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program, + int* num_eliminate_blocks, + string* error) { + int original_num_eliminate_blocks = *num_eliminate_blocks; + vector* parameter_blocks = + program->mutable_parameter_blocks(); + + // Mark all the parameters as unused. Abuse the index member of the parameter + // blocks for the marking. + for (int i = 0; i < parameter_blocks->size(); ++i) { + (*parameter_blocks)[i]->set_index(-1); + } + + // Filter out residual that have all-constant parameters, and mark all the + // parameter blocks that appear in residuals. + { + vector* residual_blocks = + program->mutable_residual_blocks(); + int j = 0; + for (int i = 0; i < residual_blocks->size(); ++i) { + ResidualBlock* residual_block = (*residual_blocks)[i]; + int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Determine if the residual block is fixed, and also mark varying + // parameters that appear in the residual block. + bool all_constant = true; + for (int k = 0; k < num_parameter_blocks; k++) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[k]; + if (!parameter_block->IsConstant()) { + all_constant = false; + parameter_block->set_index(1); + } + } + + if (!all_constant) { + (*residual_blocks)[j++] = (*residual_blocks)[i]; + } + } + residual_blocks->resize(j); + } + + // Filter out unused or fixed parameter blocks, and update + // num_eliminate_blocks as necessary. + { + vector* parameter_blocks = + program->mutable_parameter_blocks(); + int j = 0; + for (int i = 0; i < parameter_blocks->size(); ++i) { + ParameterBlock* parameter_block = (*parameter_blocks)[i]; + if (parameter_block->index() == 1) { + (*parameter_blocks)[j++] = parameter_block; + } else if (i < original_num_eliminate_blocks) { + (*num_eliminate_blocks)--; + } + } + parameter_blocks->resize(j); + } + + CHECK(((program->NumResidualBlocks() == 0) && + (program->NumParameterBlocks() == 0)) || + ((program->NumResidualBlocks() != 0) && + (program->NumParameterBlocks() != 0))) + << "Congratulations, you found a bug in Ceres. Please report it."; + return true; +} + +Program* SolverImpl::CreateReducedProgram(Solver::Options* options, + ProblemImpl* problem_impl, + string* error) { + Program* original_program = problem_impl->mutable_program(); + scoped_ptr transformed_program(new Program(*original_program)); + + if (options->ordering_type == USER && + !ApplyUserOrdering(*problem_impl, + options->ordering, + transformed_program.get(), + error)) { + return NULL; + } + + if (options->ordering_type == SCHUR && options->num_eliminate_blocks != 0) { + *error = "Can't specify SCHUR ordering and num_eliminate_blocks " + "at the same time; SCHUR ordering determines " + "num_eliminate_blocks automatically."; + return NULL; + } + + if (options->ordering_type == SCHUR && options->ordering.size() != 0) { + *error = "Can't specify SCHUR ordering type and the ordering " + "vector at the same time; SCHUR ordering determines " + "a suitable parameter ordering automatically."; + return NULL; + } + + int num_eliminate_blocks = options->num_eliminate_blocks; + + if (!RemoveFixedBlocksFromProgram(transformed_program.get(), + &num_eliminate_blocks, + error)) { + return NULL; + } + + if (transformed_program->NumParameterBlocks() == 0) { + LOG(WARNING) << "No varying parameter blocks to optimize; " + << "bailing early."; + return transformed_program.release(); + } + + if (options->ordering_type == SCHUR) { + vector schur_ordering; + num_eliminate_blocks = ComputeSchurOrdering(*transformed_program, + &schur_ordering); + CHECK_EQ(schur_ordering.size(), transformed_program->NumParameterBlocks()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Replace the transformed program's ordering with the schur ordering. + swap(*transformed_program->mutable_parameter_blocks(), schur_ordering); + } + options->num_eliminate_blocks = num_eliminate_blocks; + CHECK_GE(options->num_eliminate_blocks, 0) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Since the transformed program is the "active" program, and it is mutated, + // update the parameter offsets and indices. + transformed_program->SetParameterOffsetsAndIndex(); + return transformed_program.release(); +} + +LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options, + string* error) { +#ifdef CERES_NO_SUITESPARSE + if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY because SuiteSparse was not " + "enabled when Ceres was built."; + return NULL; + } +#endif // CERES_NO_SUITESPARSE + + if (options->linear_solver_max_num_iterations <= 0) { + *error = "Solver::Options::linear_solver_max_num_iterations is 0."; + return NULL; + } + if (options->linear_solver_min_num_iterations <= 0) { + *error = "Solver::Options::linear_solver_min_num_iterations is 0."; + return NULL; + } + if (options->linear_solver_min_num_iterations > + options->linear_solver_max_num_iterations) { + *error = "Solver::Options::linear_solver_min_num_iterations > " + "Solver::Options::linear_solver_max_num_iterations."; + return NULL; + } + + LinearSolver::Options linear_solver_options; + linear_solver_options.constant_sparsity = true; + linear_solver_options.min_num_iterations = + options->linear_solver_min_num_iterations; + linear_solver_options.max_num_iterations = + options->linear_solver_max_num_iterations; + linear_solver_options.type = options->linear_solver_type; + linear_solver_options.preconditioner_type = options->preconditioner_type; + +#ifdef CERES_NO_SUITESPARSE + if (linear_solver_options.preconditioner_type == SCHUR_JACOBI) { + *error = "SCHUR_JACOBI preconditioner not suppored. Please build Ceres " + "with SuiteSparse support"; + return NULL; + } + + if (linear_solver_options.preconditioner_type == CLUSTER_JACOBI) { + *error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres " + "with SuiteSparse support"; + return NULL; + } + + if (linear_solver_options.preconditioner_type == CLUSTER_TRIDIAGONAL) { + *error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build " + "Ceres with SuiteSparse support"; + return NULL; + } +#endif + + linear_solver_options.num_threads = options->num_linear_solver_threads; + linear_solver_options.num_eliminate_blocks = + options->num_eliminate_blocks; + + if ((linear_solver_options.num_eliminate_blocks == 0) && + IsSchurType(linear_solver_options.type)) { +#ifndef CERES_NO_SUITESPARSE + LOG(INFO) << "No elimination block remaining " + << "switching to SPARSE_NORMAL_CHOLESKY."; + linear_solver_options.type = SPARSE_NORMAL_CHOLESKY; +#else + LOG(INFO) << "No elimination block remaining switching to DENSE_QR."; + linear_solver_options.type = DENSE_QR; +#endif // CERES_NO_SUITESPARSE + } + +#ifdef CERES_NO_SUITESPARSE + if (linear_solver_options.type == SPARSE_SCHUR) { + *error = "Can't use SPARSE_SCHUR because SuiteSparse was not " + "enabled when Ceres was built."; + return NULL; + } +#endif // CERES_NO_SUITESPARSE + + // The matrix used for storing the dense Schur complement has a + // single lock guarding the whole matrix. Running the + // SchurComplementSolver with multiple threads leads to maximum + // contention and slowdown. If the problem is large enough to + // benefit from a multithreaded schur eliminator, you should be + // using a SPARSE_SCHUR solver anyways. + if ((linear_solver_options.num_threads > 1) && + (linear_solver_options.type == DENSE_SCHUR)) { + LOG(WARNING) << "Warning: Solver::Options::num_linear_solver_threads = " + << options->num_linear_solver_threads + << " with DENSE_SCHUR will result in poor performance; " + << "switching to single-threaded."; + linear_solver_options.num_threads = 1; + } + + options->linear_solver_type = linear_solver_options.type; + options->num_linear_solver_threads = linear_solver_options.num_threads; + + return LinearSolver::Create(linear_solver_options); +} + +bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl, + vector& ordering, + Program* program, + string* error) { + if (ordering.size() != program->NumParameterBlocks()) { + *error = StringPrintf("User specified ordering does not have the same " + "number of parameters as the problem. The problem" + "has %d blocks while the ordering has %ld blocks.", + program->NumParameterBlocks(), + ordering.size()); + return false; + } + + // Ensure that there are no duplicates in the user's ordering. + { + vector ordering_copy(ordering); + sort(ordering_copy.begin(), ordering_copy.end()); + if (unique(ordering_copy.begin(), ordering_copy.end()) + != ordering_copy.end()) { + *error = "User specified ordering contains duplicates."; + return false; + } + } + + vector* parameter_blocks = + program->mutable_parameter_blocks(); + + fill(parameter_blocks->begin(), + parameter_blocks->end(), + static_cast(NULL)); + + const ProblemImpl::ParameterMap& parameter_map = problem_impl.parameter_map(); + for (int i = 0; i < ordering.size(); ++i) { + ProblemImpl::ParameterMap::const_iterator it = + parameter_map.find(ordering[i]); + if (it == parameter_map.end()) { + *error = StringPrintf("User specified ordering contains a pointer " + "to a double that is not a parameter block in the " + "problem. The invalid double is at position %d " + " in options.ordering.", i); + return false; + } + (*parameter_blocks)[i] = it->second; + } + return true; +} + +// Find the minimum index of any parameter block to the given residual. +// Parameter blocks that have indices greater than num_eliminate_blocks are +// considered to have an index equal to num_eliminate_blocks. +int MinParameterBlock(const ResidualBlock* residual_block, + int num_eliminate_blocks) { + int min_parameter_block_position = num_eliminate_blocks; + for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[i]; + DCHECK_NE(parameter_block->index(), -1) + << "Did you forget to call Program::SetParameterOffsetsAndIndex()?"; + min_parameter_block_position = std::min(parameter_block->index(), + min_parameter_block_position); + } + return min_parameter_block_position; +} + +// Reorder the residuals for program, if necessary, so that the residuals +// involving each E block occur together. This is a necessary condition for the +// Schur eliminator, which works on these "row blocks" in the jacobian. +bool SolverImpl::MaybeReorderResidualBlocks(const Solver::Options& options, + Program* program, + string* error) { + // Only Schur types require the lexicographic reordering. + if (!IsSchurType(options.linear_solver_type)) { + return true; + } + + CHECK_NE(0, options.num_eliminate_blocks) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Create a histogram of the number of residuals for each E block. There is an + // extra bucket at the end to catch all non-eliminated F blocks. + vector residual_blocks_per_e_block(options.num_eliminate_blocks + 1); + vector* residual_blocks = program->mutable_residual_blocks(); + vector min_position_per_residual(residual_blocks->size()); + for (int i = 0; i < residual_blocks->size(); ++i) { + ResidualBlock* residual_block = (*residual_blocks)[i]; + int position = MinParameterBlock(residual_block, + options.num_eliminate_blocks); + min_position_per_residual[i] = position; + DCHECK_LE(position, options.num_eliminate_blocks); + residual_blocks_per_e_block[position]++; + } + + // Run a cumulative sum on the histogram, to obtain offsets to the start of + // each histogram bucket (where each bucket is for the residuals for that + // E-block). + vector offsets(options.num_eliminate_blocks + 1); + std::partial_sum(residual_blocks_per_e_block.begin(), + residual_blocks_per_e_block.end(), + offsets.begin()); + CHECK_EQ(offsets.back(), residual_blocks->size()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + CHECK(find(residual_blocks_per_e_block.begin(), + residual_blocks_per_e_block.end() - 1, 0) != + residual_blocks_per_e_block.end()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Fill in each bucket with the residual blocks for its corresponding E block. + // Each bucket is individually filled from the back of the bucket to the front + // of the bucket. The filling order among the buckets is dictated by the + // residual blocks. This loop uses the offsets as counters; subtracting one + // from each offset as a residual block is placed in the bucket. When the + // filling is finished, the offset pointerts should have shifted down one + // entry (this is verified below). + vector reordered_residual_blocks( + (*residual_blocks).size(), static_cast(NULL)); + for (int i = 0; i < residual_blocks->size(); ++i) { + int bucket = min_position_per_residual[i]; + + // Decrement the cursor, which should now point at the next empty position. + offsets[bucket]--; + + // Sanity. + CHECK(reordered_residual_blocks[offsets[bucket]] == NULL) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + reordered_residual_blocks[offsets[bucket]] = (*residual_blocks)[i]; + } + + // Sanity check #1: The difference in bucket offsets should match the + // histogram sizes. + for (int i = 0; i < options.num_eliminate_blocks; ++i) { + CHECK_EQ(residual_blocks_per_e_block[i], offsets[i + 1] - offsets[i]) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + } + // Sanity check #2: No NULL's left behind. + for (int i = 0; i < reordered_residual_blocks.size(); ++i) { + CHECK(reordered_residual_blocks[i] != NULL) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + } + + // Now that the residuals are collected by E block, swap them in place. + swap(*program->mutable_residual_blocks(), reordered_residual_blocks); + return true; +} + +Evaluator* SolverImpl::CreateEvaluator(const Solver::Options& options, + Program* program, + string* error) { + Evaluator::Options evaluator_options; + evaluator_options.linear_solver_type = options.linear_solver_type; + evaluator_options.num_eliminate_blocks = options.num_eliminate_blocks; + evaluator_options.num_threads = options.num_threads; + return Evaluator::Create(evaluator_options, program, error); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h new file mode 100644 index 00000000000..957ebcc65df --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h @@ -0,0 +1,111 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_SOLVER_IMPL_H_ +#define CERES_INTERNAL_SOLVER_IMPL_H_ + +#include "ceres/solver.h" + +namespace ceres { +namespace internal { + +class Evaluator; +class LinearSolver; +class ProblemImpl; +class Program; + +class SolverImpl { + public: + // Mirrors the interface in solver.h, but exposes implementation + // details for testing internally. + static void Solve(const Solver::Options& options, + Problem* problem, + Solver::Summary* summary); + + // Create the transformed Program, which has all the fixed blocks + // and residuals eliminated, and in the case of automatic schur + // ordering, has the E blocks first in the resulting program, with + // options.num_eliminate_blocks set appropriately. + static Program* CreateReducedProgram(Solver::Options* options, + ProblemImpl* problem_impl, + string* error); + + // Create the appropriate linear solver, taking into account any + // config changes decided by CreateTransformedProgram(). The + // selected linear solver, which may be different from what the user + // selected; consider the case that the remaining elimininated + // blocks is zero after removing fixed blocks. + static LinearSolver* CreateLinearSolver(Solver::Options* options, + string* error); + + // Reorder the parameter blocks in program using the vector + // ordering. A return value of true indicates success and false + // indicates an error was encountered whose cause is logged to + // LOG(ERROR). + static bool ApplyUserOrdering(const ProblemImpl& problem_impl, + vector& ordering, + Program* program, + string* error); + + // Reorder the residuals for program, if necessary, so that the + // residuals involving each E block occur together. This is a + // necessary condition for the Schur eliminator, which works on + // these "row blocks" in the jacobian. + static bool MaybeReorderResidualBlocks(const Solver::Options& options, + Program* program, + string* error); + + // Create the appropriate evaluator for the transformed program. + static Evaluator* CreateEvaluator(const Solver::Options& options, + Program* program, + string* error); + + // Run the minimization for the given evaluator and configuration. + static void Minimize(const Solver::Options &options, + Program* program, + Evaluator* evaluator, + LinearSolver* linear_solver, + double* initial_parameters, + double* final_parameters, + Solver::Summary* summary); + + // Remove the fixed or unused parameter blocks and residuals + // depending only on fixed parameters from the problem. Also updates + // num_eliminate_blocks, since removed parameters changes the point + // at which the eliminated blocks is valid. + static bool RemoveFixedBlocksFromProgram(Program* program, + int* num_eliminate_blocks, + string* error); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SOLVER_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc new file mode 100644 index 00000000000..55336fd3130 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.cc @@ -0,0 +1,40 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/sparse_matrix.h" + +namespace ceres { +namespace internal { + +SparseMatrix::~SparseMatrix() { +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h new file mode 100644 index 00000000000..562210dfec8 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h @@ -0,0 +1,114 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Interface definition for sparse matrices. + +#ifndef CERES_INTERNAL_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_SPARSE_MATRIX_H_ + +#include +#include "ceres/linear_operator.h" +#include "ceres/internal/eigen.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; + +// This class defines the interface for storing and manipulating +// sparse matrices. The key property that differentiates different +// sparse matrices is how they are organized in memory and how the +// information about the sparsity structure of the matrix is +// stored. This has significant implications for linear solvers +// operating on these matrices. +// +// To deal with the different kinds of layouts, we will assume that a +// sparse matrix will have a two part representation. A values array +// that will be used to store the entries of the sparse matrix and +// some sort of a layout object that tells the user the sparsity +// structure and layout of the values array. For example in case of +// the TripletSparseMatrix, this information is carried in the rows +// and cols arrays and for the BlockSparseMatrix, this information is +// carried in the CompressedRowBlockStructure object. +// +// This interface deliberately does not contain any information about +// the structure of the sparse matrix as that seems to be highly +// matrix type dependent and we are at this stage unable to come up +// with an efficient high level interface that spans multiple sparse +// matrix types. +class SparseMatrix : public LinearOperator { + public: + virtual ~SparseMatrix(); + + // y += Ax; + virtual void RightMultiply(const double* x, double* y) const = 0; + // y += A'x; + virtual void LeftMultiply(const double* x, double* y) const = 0; + + // In MATLAB notation sum(A.*A, 1) + virtual void SquaredColumnNorm(double* x) const = 0; + // A = A * diag(scale) + virtual void ScaleColumns(const double* scale) = 0; + + // A = 0. A->num_nonzeros() == 0 is true after this call. The + // sparsity pattern is preserved. + virtual void SetZero() = 0; + + // Resize and populate dense_matrix with a dense version of the + // sparse matrix. + virtual void ToDenseMatrix(Matrix* dense_matrix) const = 0; + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + // Dump the sparse matrix to a proto. Destroys the contents of proto. + virtual void ToProto(SparseMatrixProto* proto) const = 0; +#endif + + // Write out the matrix as a sequence of (i,j,s) triplets. This + // format is useful for loading the matrix into MATLAB/octave as a + // sparse matrix. + virtual void ToTextFile(FILE* file) const = 0; + + // Accessors for the values array that stores the entries of the + // sparse matrix. The exact interpreptation of the values of this + // array depends on the particular kind of SparseMatrix being + // accessed. + virtual double* mutable_values() = 0; + virtual const double* values() const = 0; + + virtual int num_rows() const = 0; + virtual int num_cols() const = 0; + virtual int num_nonzeros() const = 0; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_SPARSE_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc new file mode 100644 index 00000000000..59222dc374d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc @@ -0,0 +1,129 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_NO_SUITESPARSE + +#include "ceres/sparse_normal_cholesky_solver.h" + +#include +#include +#include +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/linear_solver.h" +#include "ceres/suitesparse.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +SparseNormalCholeskySolver::SparseNormalCholeskySolver( + const LinearSolver::Options& options) + : options_(options), symbolic_factor_(NULL) {} + +SparseNormalCholeskySolver::~SparseNormalCholeskySolver() { + if (symbolic_factor_ != NULL) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } +} + +LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double * x) { + const time_t start_time = time(NULL); + const int num_cols = A->num_cols(); + + LinearSolver::Summary summary; + Vector Atb = Vector::Zero(num_cols); + A->LeftMultiply(b, Atb.data()); + + if (per_solve_options.D != NULL) { + // Temporarily append a diagonal block to the A matrix, but undo it before + // returning the matrix to the user. + CompressedRowSparseMatrix D(per_solve_options.D, num_cols); + A->AppendRows(D); + } + + VectorRef(x, num_cols).setZero(); + + scoped_ptr lhs(ss_.CreateSparseMatrixTransposeView(A)); + CHECK_NOTNULL(lhs.get()); + + cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols); + const time_t init_time = time(NULL); + + if (symbolic_factor_ == NULL) { + symbolic_factor_ = CHECK_NOTNULL(ss_.AnalyzeCholesky(lhs.get())); + } + + const time_t symbolic_time = time(NULL); + + cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), symbolic_factor_, rhs); + const time_t solve_time = time(NULL); + + ss_.Free(rhs); + rhs = NULL; + + if (per_solve_options.D != NULL) { + A->DeleteRows(num_cols); + } + + if (!options_.constant_sparsity) { + ss_.Free(symbolic_factor_); + symbolic_factor_ = NULL; + } + + summary.num_iterations = 1; + if (sol != NULL) { + memcpy(x, sol->x, num_cols * sizeof(*x)); + + ss_.Free(sol); + sol = NULL; + summary.termination_type = TOLERANCE; + } + + const time_t cleanup_time = time(NULL); + VLOG(2) << "time (sec) total: " << cleanup_time - start_time + << " init: " << init_time - start_time + << " symbolic: " << symbolic_time - init_time + << " solve: " << solve_time - symbolic_time + << " cleanup: " << cleanup_time - solve_time; + return summary; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h new file mode 100644 index 00000000000..ce1d6d285be --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h @@ -0,0 +1,77 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// A solver for sparse linear least squares problem based on solving +// the normal equations via a sparse cholesky factorization. + +#ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ +#define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ + +#ifndef CERES_NO_SUITESPARSE + +#include "cholmod.h" +#include "cholmod_core.h" +#include "ceres/linear_solver.h" +#include "ceres/suitesparse.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class CompressedRowSparseMatrix; + +// Solves the normal equations (A'A + D'D) x = A'b, using the CHOLMOD sparse +// cholesky solver. +class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { + public: + explicit SparseNormalCholeskySolver(const LinearSolver::Options& options); + virtual ~SparseNormalCholeskySolver(); + + private: + virtual LinearSolver::Summary SolveImpl( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& options, + double* x); + + const LinearSolver::Options options_; + SuiteSparse ss_; + + // Cached factorization + cholmod_factor* symbolic_factor_; + DISALLOW_COPY_AND_ASSIGN(SparseNormalCholeskySolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE + +#endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.cc b/extern/libmv/third_party/ceres/internal/ceres/split.cc new file mode 100644 index 00000000000..4fa1bd468b9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/split.cc @@ -0,0 +1,115 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#include +#include +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// If we know how much to allocate for a vector of strings, we can allocate the +// vector only once and directly to the right size. This saves in +// between 33-66 % of memory space needed for the result, and runs faster in the +// microbenchmarks. +// +// The reserve is only implemented for the single character delim. +// +// The implementation for counting is cut-and-pasted from +// SplitStringToIteratorUsing. I could have written my own counting iterator, +// and use the existing template function, but probably this is more clear and +// more sure to get optimized to reasonable code. +static int CalculateReserveForVector(const string& full, const char* delim) { + int count = 0; + if (delim[0] != '\0' && delim[1] == '\0') { + // Optimize the common case where delim is a single character. + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { // This could be optimized with hasless(v,1) trick. + ++p; + } else { + while (++p != end && *p != c) { + // Skip to the next occurence of the delimiter. + } + ++count; + } + } + } + return count; +} + +template +static inline +void SplitStringToIteratorUsing(const StringType& full, + const char* delim, + ITR& result) { + // Optimize the common case where delim is a single character. + if (delim[0] != '\0' && delim[1] == '\0') { + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != c) { + // Skip to the next occurence of the delimiter. + } + *result++ = StringType(start, p - start); + } + } + return; + } + + string::size_type begin_index, end_index; + begin_index = full.find_first_not_of(delim); + while (begin_index != string::npos) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = full.find_first_not_of(delim, end_index); + } +} + +void SplitStringUsing(const string& full, + const char* delim, + vector* result) { + result->reserve(result->size() + CalculateReserveForVector(full, delim)); + back_insert_iterator< vector > it(*result); + SplitStringToIteratorUsing(full, delim, it); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/stl_util.h b/extern/libmv/third_party/ceres/internal/ceres/stl_util.h new file mode 100644 index 00000000000..a1a19e8b3ce --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/stl_util.h @@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_STL_UTIL_H_ +#define CERES_INTERNAL_STL_UTIL_H_ + +namespace ceres { + +// STLDeleteContainerPointers() +// For a range within a container of pointers, calls delete +// (non-array version) on these pointers. +// NOTE: for these three functions, we could just implement a DeleteObject +// functor and then call for_each() on the range and functor, but this +// requires us to pull in all of algorithm.h, which seems expensive. +// For hash_[multi]set, it is important that this deletes behind the iterator +// because the hash_set may call the hash function on the iterator when it is +// advanced, which could result in the hash function trying to deference a +// stale pointer. +template +void STLDeleteContainerPointers(ForwardIterator begin, + ForwardIterator end) { + while (begin != end) { + ForwardIterator temp = begin; + ++begin; + delete *temp; + } +} + +// STLDeleteElements() deletes all the elements in an STL container and clears +// the container. This function is suitable for use with a vector, set, +// hash_set, or any other STL container which defines sensible begin(), end(), +// and clear() methods. +// +// If container is NULL, this function is a no-op. +// +// As an alternative to calling STLDeleteElements() directly, consider +// ElementDeleter (defined below), which ensures that your container's elements +// are deleted when the ElementDeleter goes out of scope. +template +void STLDeleteElements(T *container) { + if (!container) return; + STLDeleteContainerPointers(container->begin(), container->end()); + container->clear(); +} + +} // namespace ceres + +#endif // CERES_INTERNAL_STL_UTIL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc new file mode 100644 index 00000000000..c0f35225bc3 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc @@ -0,0 +1,126 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat + +#include +#include // For va_list and related operations +#include // MSVC requires this for _vsnprintf +#include +#include + +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +#ifdef _MSC_VER +enum { IS_COMPILER_MSVC = 1 }; +#define va_copy(d,s) ((d) = (s)) +#else +enum { IS_COMPILER_MSVC = 0 }; +#endif + +void StringAppendV(string* dst, const char* format, va_list ap) { + // First try with a small fixed size buffer + char space[1024]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, sizeof(space), format, backup_ap); + va_end(backup_ap); + + if (result < sizeof(space)) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + + if (IS_COMPILER_MSVC) { + // Error or MSVC running out of space. MSVC 8.0 and higher + // can be asked about space needed with the special idiom below: + va_copy(backup_ap, ap); + result = vsnprintf(NULL, 0, format, backup_ap); + va_end(backup_ap); + } + + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result+1; + char* buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + + +string StringPrintf(const char* format, ...) { + va_list ap; + va_start(ap, format); + string result; + StringAppendV(&result, format, ap); + va_end(ap); + return result; +} + +const string& SStringPrintf(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + dst->clear(); + StringAppendV(dst, format, ap); + va_end(ap); + return *dst; +} + +void StringAppendF(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + StringAppendV(dst, format, ap); + va_end(ap); +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h new file mode 100644 index 00000000000..30b974e7ae5 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h @@ -0,0 +1,89 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: Sanjay Ghemawat +// +// Printf variants that place their output in a C++ string. +// +// Usage: +// string result = StringPrintf("%d %s\n", 10, "hello"); +// SStringPrintf(&result, "%d %s\n", 10, "hello"); +// StringAppendF(&result, "%d %s\n", 20, "there"); + +#ifndef CERES_INTERNAL_STRINGPRINTF_H_ +#define CERES_INTERNAL_STRINGPRINTF_H_ + +#include +#include + +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +#if (defined(__GNUC__) || defined(__clang__)) +// Tell the compiler to do printf format string checking if the compiler +// supports it; see the 'format' attribute in +// . +// +// N.B.: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#define PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__ (__printf__, string_index, first_to_check))) +#define SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__ (__scanf__, string_index, first_to_check))) +#else +#define PRINTF_ATTRIBUTE(string_index, first_to_check) +#endif + +// Return a C++ string. +extern string StringPrintf(const char* format, ...) + // Tell the compiler to do printf format string checking. + PRINTF_ATTRIBUTE(1,2); + +// Store result into a supplied string and return it. +extern const string& SStringPrintf(string* dst, const char* format, ...) + // Tell the compiler to do printf format string checking. + PRINTF_ATTRIBUTE(2,3); + +// Append result to a supplied string. +extern void StringAppendF(string* dst, const char* format, ...) + // Tell the compiler to do printf format string checking. + PRINTF_ATTRIBUTE(2,3); + +// Lower-level routine that takes a va_list and appends to a specified string. +// All other routines are just convenience wrappers around it. +extern void StringAppendV(string* dst, const char* format, va_list ap); + +#undef PRINTF_ATTRIBUTE + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_STRINGPRINTF_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc new file mode 100644 index 00000000000..1cf6a7496a7 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc @@ -0,0 +1,193 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_NO_SUITESPARSE + +#include "ceres/suitesparse.h" + +#include "cholmod.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +namespace ceres { +namespace internal { + +cholmod_sparse* SuiteSparse::CreateSparseMatrix(TripletSparseMatrix* A) { + cholmod_triplet triplet; + + triplet.nrow = A->num_rows(); + triplet.ncol = A->num_cols(); + triplet.nzmax = A->max_num_nonzeros(); + triplet.nnz = A->num_nonzeros(); + triplet.i = reinterpret_cast(A->mutable_rows()); + triplet.j = reinterpret_cast(A->mutable_cols()); + triplet.x = reinterpret_cast(A->mutable_values()); + triplet.stype = 0; // Matrix is not symmetric. + triplet.itype = CHOLMOD_INT; + triplet.xtype = CHOLMOD_REAL; + triplet.dtype = CHOLMOD_DOUBLE; + + return cholmod_triplet_to_sparse(&triplet, triplet.nnz, &cc_); +} + + +cholmod_sparse* SuiteSparse::CreateSparseMatrixTranspose( + TripletSparseMatrix* A) { + cholmod_triplet triplet; + + triplet.ncol = A->num_rows(); // swap row and columns + triplet.nrow = A->num_cols(); + triplet.nzmax = A->max_num_nonzeros(); + triplet.nnz = A->num_nonzeros(); + + // swap rows and columns + triplet.j = reinterpret_cast(A->mutable_rows()); + triplet.i = reinterpret_cast(A->mutable_cols()); + triplet.x = reinterpret_cast(A->mutable_values()); + triplet.stype = 0; // Matrix is not symmetric. + triplet.itype = CHOLMOD_INT; + triplet.xtype = CHOLMOD_REAL; + triplet.dtype = CHOLMOD_DOUBLE; + + return cholmod_triplet_to_sparse(&triplet, triplet.nnz, &cc_); +} + +cholmod_sparse* SuiteSparse::CreateSparseMatrixTransposeView( + CompressedRowSparseMatrix* A) { + cholmod_sparse* m = new cholmod_sparse_struct; + m->nrow = A->num_cols(); + m->ncol = A->num_rows(); + m->nzmax = A->num_nonzeros(); + + m->p = reinterpret_cast(A->mutable_rows()); + m->i = reinterpret_cast(A->mutable_cols()); + m->x = reinterpret_cast(A->mutable_values()); + + m->stype = 0; // Matrix is not symmetric. + m->itype = CHOLMOD_INT; + m->xtype = CHOLMOD_REAL; + m->dtype = CHOLMOD_DOUBLE; + m->sorted = 1; + m->packed = 1; + + return m; +} + +cholmod_dense* SuiteSparse::CreateDenseVector(const double* x, + int in_size, + int out_size) { + CHECK_LE(in_size, out_size); + cholmod_dense* v = cholmod_zeros(out_size, 1, CHOLMOD_REAL, &cc_); + if (x != NULL) { + memcpy(v->x, x, in_size*sizeof(*x)); + } + return v; +} + +cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) { + cholmod_factor* factor = cholmod_analyze(A, &cc_); + CHECK_EQ(cc_.status, CHOLMOD_OK) + << "Cholmod symbolic analysis failed " << cc_.status; + CHECK_NOTNULL(factor); + return factor; +} + +bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(L); + + cc_.quick_return_if_not_posdef = 1; + int status = cholmod_factorize(A, L, &cc_); + switch (cc_.status) { + case CHOLMOD_NOT_INSTALLED: + LOG(WARNING) << "Cholmod failure: method not installed."; + return false; + case CHOLMOD_OUT_OF_MEMORY: + LOG(WARNING) << "Cholmod failure: out of memory."; + return false; + case CHOLMOD_TOO_LARGE: + LOG(WARNING) << "Cholmod failure: integer overflow occured."; + return false; + case CHOLMOD_INVALID: + LOG(WARNING) << "Cholmod failure: invalid input."; + return false; + case CHOLMOD_NOT_POSDEF: + // TODO(sameeragarwal): These two warnings require more + // sophisticated handling going forward. For now we will be + // strict and treat them as failures. + LOG(WARNING) << "Cholmod warning: matrix not positive definite."; + return false; + case CHOLMOD_DSMALL: + LOG(WARNING) << "Cholmod warning: D for LDL' or diag(L) or " + << "LL' has tiny absolute value."; + return false; + case CHOLMOD_OK: + if (status != 0) { + return true; + } + LOG(WARNING) << "Cholmod failure: cholmod_factorize returned zero " + << "but cholmod_common::status is CHOLMOD_OK." + << "Please report this to ceres-solver@googlegroups.com."; + return false; + default: + LOG(WARNING) << "Unknown cholmod return code. " + << "Please report this to ceres-solver@googlegroups.com."; + return false; + } + return false; +} + +cholmod_dense* SuiteSparse::Solve(cholmod_factor* L, + cholmod_dense* b) { + if (cc_.status != CHOLMOD_OK) { + LOG(WARNING) << "CHOLMOD status NOT OK"; + return NULL; + } + + return cholmod_solve(CHOLMOD_A, L, b, &cc_); +} + +cholmod_dense* SuiteSparse::SolveCholesky(cholmod_sparse* A, + cholmod_factor* L, + cholmod_dense* b) { + CHECK_NOTNULL(A); + CHECK_NOTNULL(L); + CHECK_NOTNULL(b); + + if (Cholesky(A, L)) { + return Solve(L, b); + } + + return NULL; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h new file mode 100644 index 00000000000..091e67a69a9 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h @@ -0,0 +1,159 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// A simple C++ interface to the SuiteSparse and CHOLMOD libraries. + +#ifndef CERES_INTERNAL_SUITESPARSE_H_ +#define CERES_INTERNAL_SUITESPARSE_H_ + +#ifndef CERES_NO_SUITESPARSE + +#include +#include + +#include +#include "cholmod.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class CompressedRowSparseMatrix; +class TripletSparseMatrix; + +// The raw CHOLMOD and SuiteSparseQR libraries have a slightly +// cumbersome c like calling format. This object abstracts it away and +// provides the user with a simpler interface. The methods here cannot +// be static as a cholmod_common object serves as a global variable +// for all cholmod function calls. +class SuiteSparse { + public: + SuiteSparse() { cholmod_start(&cc_); } + ~SuiteSparse() { cholmod_finish(&cc_); } + + // Functions for building cholmod_sparse objects from sparse + // matrices stored in triplet form. The matrix A is not + // modifed. Called owns the result. + cholmod_sparse* CreateSparseMatrix(TripletSparseMatrix* A); + + // This function works like CreateSparseMatrix, except that the + // return value corresponds to A' rather than A. + cholmod_sparse* CreateSparseMatrixTranspose(TripletSparseMatrix* A); + + // Create a cholmod_sparse wrapper around the contents of A. This is + // a shallow object, which refers to the contents of A and does not + // use the SuiteSparse machinery to allocate memory, this object + // should be disposed off with a delete and not a call to Free as is + // the case for objects returned by CreateSparseMatrixTranspose. + cholmod_sparse* CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A); + + // Given a vector x, build a cholmod_dense vector of size out_size + // with the first in_size entries copied from x. If x is NULL, then + // an all zeros vector is returned. Caller owns the result. + cholmod_dense* CreateDenseVector(const double* x, int in_size, int out_size); + + // The matrix A is scaled using the matrix whose diagonal is the + // vector scale. mode describes how scaling is applied. Possible + // values are CHOLMOD_ROW for row scaling - diag(scale) * A, + // CHOLMOD_COL for column scaling - A * diag(scale) and CHOLMOD_SYM + // for symmetric scaling which scales both the rows and the columns + // - diag(scale) * A * diag(scale). + void Scale(cholmod_dense* scale, int mode, cholmod_sparse* A) { + cholmod_scale(scale, mode, A, &cc_); + } + + // Create and return a matrix m = A * A'. Caller owns the + // result. The matrix A is not modified. + cholmod_sparse* AATranspose(cholmod_sparse* A) { + cholmod_sparse*m = cholmod_aat(A, NULL, A->nrow, 1, &cc_); + m->stype = 1; // Pay attention to the upper triangular part. + return m; + } + + // y = alpha * A * x + beta * y. Only y is modified. + void SparseDenseMultiply(cholmod_sparse* A, double alpha, double beta, + cholmod_dense* x, cholmod_dense* y) { + double alpha_[2] = {alpha, 0}; + double beta_[2] = {beta, 0}; + cholmod_sdmult(A, 0, alpha_, beta_, x, y, &cc_); + } + + // Analyze the sparsity structure of the matrix A compute the + // symbolic factorization of A. A is not modified, only the pattern + // of non-zeros of A is used, the actual numerical values in A are + // of no consequence. Caller owns the result. + cholmod_factor* AnalyzeCholesky(cholmod_sparse* A); + + // Use the symbolic factorization in L, to find the numerical + // factorization for the matrix A or AA^T. Return true if + // successful, false otherwise. L contains the numeric factorization + // on return. + bool Cholesky(cholmod_sparse* A, cholmod_factor* L); + + // Given a Cholesky factorization of a matrix A = LL^T, solve the + // linear system Ax = b, and return the result. If the Solve fails + // NULL is returned. Caller owns the result. + cholmod_dense* Solve(cholmod_factor* L, cholmod_dense* b); + + // Combine the calls to Cholesky and Solve into a single call. If + // the cholesky factorization or the solve fails, return + // NULL. Caller owns the result. + cholmod_dense* SolveCholesky(cholmod_sparse* A, + cholmod_factor* L, + cholmod_dense* b); + + void Free(cholmod_sparse* m) { cholmod_free_sparse(&m, &cc_); } + void Free(cholmod_dense* m) { cholmod_free_dense(&m, &cc_); } + void Free(cholmod_factor* m) { cholmod_free_factor(&m, &cc_); } + + void Print(cholmod_sparse* m, const string& name) { + cholmod_print_sparse(m, const_cast(name.c_str()), &cc_); + } + + void Print(cholmod_dense* m, const string& name) { + cholmod_print_dense(m, const_cast(name.c_str()), &cc_); + } + + void Print(cholmod_triplet* m, const string& name) { + cholmod_print_triplet(m, const_cast(name.c_str()), &cc_); + } + + cholmod_common* mutable_cc() { return &cc_; } + + private: + cholmod_common cc_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_SUITESPARSE + +#endif // CERES_INTERNAL_SUITESPARSE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc new file mode 100644 index 00000000000..247ab2e697b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc @@ -0,0 +1,306 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/triplet_sparse_matrix.h" + +#include +#include +#include +#include "ceres/matrix_proto.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +TripletSparseMatrix::TripletSparseMatrix() + : num_rows_(0), + num_cols_(0), + max_num_nonzeros_(0), + num_nonzeros_(0), + rows_(NULL), + cols_(NULL), + values_(NULL) {} + +TripletSparseMatrix::~TripletSparseMatrix() {} + +TripletSparseMatrix::TripletSparseMatrix(int num_rows, + int num_cols, + int max_num_nonzeros) + : num_rows_(num_rows), + num_cols_(num_cols), + max_num_nonzeros_(max_num_nonzeros), + num_nonzeros_(0), + rows_(NULL), + cols_(NULL), + values_(NULL) { + // All the sizes should at least be zero + CHECK_GE(num_rows, 0); + CHECK_GE(num_cols, 0); + CHECK_GE(max_num_nonzeros, 0); + AllocateMemory(); +} + +TripletSparseMatrix::TripletSparseMatrix(const TripletSparseMatrix& orig) + : num_rows_(orig.num_rows_), + num_cols_(orig.num_cols_), + max_num_nonzeros_(orig.max_num_nonzeros_), + num_nonzeros_(orig.num_nonzeros_), + rows_(NULL), + cols_(NULL), + values_(NULL) { + AllocateMemory(); + CopyData(orig); +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +TripletSparseMatrix::TripletSparseMatrix(const SparseMatrixProto& outer_proto) { + CHECK(outer_proto.has_triplet_matrix()); + + const TripletSparseMatrixProto& proto = outer_proto.triplet_matrix(); + CHECK(proto.has_num_rows()); + CHECK(proto.has_num_cols()); + CHECK_EQ(proto.rows_size(), proto.cols_size()); + CHECK_EQ(proto.cols_size(), proto.values_size()); + + // Initialize the matrix with the appropriate size and capacity. + max_num_nonzeros_ = 0; + set_num_nonzeros(0); + Reserve(proto.num_nonzeros()); + Resize(proto.num_rows(), proto.num_cols()); + set_num_nonzeros(proto.num_nonzeros()); + + // Copy the entries in. + for (int i = 0; i < proto.num_nonzeros(); ++i) { + rows_[i] = proto.rows(i); + cols_[i] = proto.cols(i); + values_[i] = proto.values(i); + } +} +#endif + +TripletSparseMatrix& TripletSparseMatrix::operator=( + const TripletSparseMatrix& rhs) { + num_rows_ = rhs.num_rows_; + num_cols_ = rhs.num_cols_; + num_nonzeros_ = rhs.num_nonzeros_; + max_num_nonzeros_ = rhs.max_num_nonzeros_; + AllocateMemory(); + CopyData(rhs); + return *this; +} + +bool TripletSparseMatrix::AllTripletsWithinBounds() const { + for (int i = 0; i < num_nonzeros_; ++i) { + if ((rows_[i] < 0) || (rows_[i] >= num_rows_) || + (cols_[i] < 0) || (cols_[i] >= num_cols_)) + return false; + } + return true; +} + +void TripletSparseMatrix::Reserve(int new_max_num_nonzeros) { + CHECK_LE(num_nonzeros_, new_max_num_nonzeros) + << "Reallocation will cause data loss"; + + // Nothing to do if we have enough space already. + if (new_max_num_nonzeros <= max_num_nonzeros_) + return; + + int* new_rows = new int[new_max_num_nonzeros]; + int* new_cols = new int[new_max_num_nonzeros]; + double* new_values = new double[new_max_num_nonzeros]; + + for (int i = 0; i < num_nonzeros_; ++i) { + new_rows[i] = rows_[i]; + new_cols[i] = cols_[i]; + new_values[i] = values_[i]; + } + + rows_.reset(new_rows); + cols_.reset(new_cols); + values_.reset(new_values); + + max_num_nonzeros_ = new_max_num_nonzeros; +} + +void TripletSparseMatrix::SetZero() { + fill(values_.get(), values_.get() + max_num_nonzeros_, 0.0); + num_nonzeros_ = 0; +} + +void TripletSparseMatrix::set_num_nonzeros(int num_nonzeros) { + CHECK_GE(num_nonzeros, 0); + CHECK_LE(num_nonzeros, max_num_nonzeros_); + num_nonzeros_ = num_nonzeros; +}; + +void TripletSparseMatrix::AllocateMemory() { + rows_.reset(new int[max_num_nonzeros_]); + cols_.reset(new int[max_num_nonzeros_]); + values_.reset(new double[max_num_nonzeros_]); +} + +void TripletSparseMatrix::CopyData(const TripletSparseMatrix& orig) { + for (int i = 0; i < num_nonzeros_; ++i) { + rows_[i] = orig.rows_[i]; + cols_[i] = orig.cols_[i]; + values_[i] = orig.values_[i]; + } +} + +void TripletSparseMatrix::RightMultiply(const double* x, double* y) const { + for (int i = 0; i < num_nonzeros_; ++i) { + y[rows_[i]] += values_[i]*x[cols_[i]]; + } +} + +void TripletSparseMatrix::LeftMultiply(const double* x, double* y) const { + for (int i = 0; i < num_nonzeros_; ++i) { + y[cols_[i]] += values_[i]*x[rows_[i]]; + } +} + +void TripletSparseMatrix::SquaredColumnNorm(double* x) const { + CHECK_NOTNULL(x); + VectorRef(x, num_cols_).setZero(); + for (int i = 0; i < num_nonzeros_; ++i) { + x[cols_[i]] += values_[i] * values_[i]; + } +} + +void TripletSparseMatrix::ScaleColumns(const double* scale) { + CHECK_NOTNULL(scale); + for (int i = 0; i < num_nonzeros_; ++i) { + values_[i] = values_[i] * scale[cols_[i]]; + } +} + +void TripletSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { + dense_matrix->resize(num_rows_, num_cols_); + dense_matrix->setZero(); + Matrix& m = *dense_matrix; + for (int i = 0; i < num_nonzeros_; ++i) { + m(rows_[i], cols_[i]) += values_[i]; + } +} + +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +void TripletSparseMatrix::ToProto(SparseMatrixProto *proto) const { + proto->Clear(); + + TripletSparseMatrixProto* tsm_proto = proto->mutable_triplet_matrix(); + tsm_proto->set_num_rows(num_rows_); + tsm_proto->set_num_cols(num_cols_); + tsm_proto->set_num_nonzeros(num_nonzeros_); + for (int i = 0; i < num_nonzeros_; ++i) { + tsm_proto->add_rows(rows_[i]); + tsm_proto->add_cols(cols_[i]); + tsm_proto->add_values(values_[i]); + } +} +#endif + +void TripletSparseMatrix::AppendRows(const TripletSparseMatrix& B) { + CHECK_EQ(B.num_cols(), num_cols_); + Reserve(num_nonzeros_ + B.num_nonzeros_); + for (int i = 0; i < B.num_nonzeros_; ++i) { + rows_.get()[num_nonzeros_] = B.rows()[i] + num_rows_; + cols_.get()[num_nonzeros_] = B.cols()[i]; + values_.get()[num_nonzeros_++] = B.values()[i]; + } + num_rows_ = num_rows_ + B.num_rows(); +} + +void TripletSparseMatrix::AppendCols(const TripletSparseMatrix& B) { + CHECK_EQ(B.num_rows(), num_rows_); + Reserve(num_nonzeros_ + B.num_nonzeros_); + for (int i = 0; i < B.num_nonzeros_; ++i, ++num_nonzeros_) { + rows_.get()[num_nonzeros_] = B.rows()[i]; + cols_.get()[num_nonzeros_] = B.cols()[i] + num_cols_; + values_.get()[num_nonzeros_] = B.values()[i]; + } + num_cols_ = num_cols_ + B.num_cols(); +} + + +void TripletSparseMatrix::Resize(int new_num_rows, int new_num_cols) { + if ((new_num_rows >= num_rows_) && (new_num_cols >= num_cols_)) { + num_rows_ = new_num_rows; + num_cols_ = new_num_cols; + return; + } + + num_rows_ = new_num_rows; + num_cols_ = new_num_cols; + + int* r_ptr = rows_.get(); + int* c_ptr = cols_.get(); + double* v_ptr = values_.get(); + + int dropped_terms = 0; + for (int i = 0; i < num_nonzeros_; ++i) { + if ((r_ptr[i] < num_rows_) && (c_ptr[i] < num_cols_)) { + if (dropped_terms) { + r_ptr[i-dropped_terms] = r_ptr[i]; + c_ptr[i-dropped_terms] = c_ptr[i]; + v_ptr[i-dropped_terms] = v_ptr[i]; + } + } else { + ++dropped_terms; + } + } + num_nonzeros_ -= dropped_terms; +} + +TripletSparseMatrix* TripletSparseMatrix::CreateSparseDiagonalMatrix( + const double* values, int num_rows) { + TripletSparseMatrix* m = + new TripletSparseMatrix(num_rows, num_rows, num_rows); + for (int i = 0; i < num_rows; ++i) { + m->mutable_rows()[i] = i; + m->mutable_cols()[i] = i; + m->mutable_values()[i] = values[i]; + } + m->set_num_nonzeros(num_rows); + return m; +} + +void TripletSparseMatrix::ToTextFile(FILE* file) const { + CHECK_NOTNULL(file); + for (int i = 0; i < num_nonzeros_; ++i) { + fprintf(file, "% 10d % 10d %17f\n", rows_[i], cols_[i], values_[i]); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h new file mode 100644 index 00000000000..300e74d0bbc --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h @@ -0,0 +1,137 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H_ +#define CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H_ + +#include "ceres/sparse_matrix.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class SparseMatrixProto; + +// An implementation of the SparseMatrix interface to store and +// manipulate sparse matrices in triplet (i,j,s) form. This object is +// inspired by the design of the cholmod_triplet struct used in the +// SuiteSparse package and is memory layout compatible with it. +class TripletSparseMatrix : public SparseMatrix { + public: + TripletSparseMatrix(); + TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros); + explicit TripletSparseMatrix(const TripletSparseMatrix& orig); +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + explicit TripletSparseMatrix(const SparseMatrixProto& proto); +#endif + + TripletSparseMatrix& operator=(const TripletSparseMatrix& rhs); + + ~TripletSparseMatrix(); + + // Implementation of the SparseMatrix interface. + virtual void SetZero(); + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const; + virtual void SquaredColumnNorm(double* x) const; + virtual void ScaleColumns(const double* scale); + virtual void ToDenseMatrix(Matrix* dense_matrix) const; +#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS + virtual void ToProto(SparseMatrixProto *proto) const; +#endif + virtual void ToTextFile(FILE* file) const; + virtual int num_rows() const { return num_rows_; } + virtual int num_cols() const { return num_cols_; } + virtual int num_nonzeros() const { return num_nonzeros_; } + virtual const double* values() const { return values_.get(); } + virtual double* mutable_values() { return values_.get(); } + virtual void set_num_nonzeros(int num_nonzeros); + + // Increase max_num_nonzeros and correspondingly increase the size + // of rows_, cols_ and values_. If new_max_num_nonzeros is smaller + // than max_num_nonzeros_, then num_non_zeros should be less than or + // equal to new_max_num_nonzeros, otherwise data loss is possible + // and the method crashes. + void Reserve(int new_max_num_nonzeros); + + // Append the matrix B at the bottom of this matrix. B should have + // the same number of columns as num_cols_. + void AppendRows(const TripletSparseMatrix& B); + + // Append the matrix B at the right of this matrix. B should have + // the same number of rows as num_rows_; + void AppendCols(const TripletSparseMatrix& B); + + // Resize the matrix. Entries which fall outside the new matrix + // bounds are dropped and the num_non_zeros changed accordingly. + void Resize(int new_num_rows, int new_num_cols); + + int max_num_nonzeros() const { return max_num_nonzeros_; } + const int* rows() const { return rows_.get(); } + const int* cols() const { return cols_.get(); } + int* mutable_rows() { return rows_.get(); } + int* mutable_cols() { return cols_.get(); } + + // Returns true if the entries of the matrix obey the row, column, + // and column size bounds and false otherwise. + bool AllTripletsWithinBounds() const; + + bool IsValid() const { return AllTripletsWithinBounds(); } + + // Build a sparse diagonal matrix of size num_rows x num_rows from + // the array values. Entries of the values array are copied into the + // sparse matrix. + static TripletSparseMatrix* CreateSparseDiagonalMatrix(const double* values, + int num_rows); + + private: + void AllocateMemory(); + void CopyData(const TripletSparseMatrix& orig); + + int num_rows_; + int num_cols_; + int max_num_nonzeros_; + int num_nonzeros_; + + // The data is stored as three arrays. For each i, values_[i] is + // stored at the location (rows_[i], cols_[i]). If the there are + // multiple entries with the same (rows_[i], cols_[i]), the values_ + // entries corresponding to them are summed up. + scoped_array rows_; + scoped_array cols_; + scoped_array values_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H__ diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc new file mode 100644 index 00000000000..860f8a43f37 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc @@ -0,0 +1,98 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include +#include "ceres/types.h" + +namespace ceres { + +#define CASESTR(x) case x: return #x + +const char* LinearSolverTypeToString(LinearSolverType solver_type) { + switch (solver_type) { + CASESTR(SPARSE_NORMAL_CHOLESKY); + CASESTR(DENSE_QR); + CASESTR(DENSE_SCHUR); + CASESTR(SPARSE_SCHUR); + CASESTR(ITERATIVE_SCHUR); + CASESTR(CGNR); + default: + return "UNKNOWN"; + } +} + +const char* PreconditionerTypeToString( + PreconditionerType preconditioner_type) { + switch (preconditioner_type) { + CASESTR(IDENTITY); + CASESTR(JACOBI); + CASESTR(SCHUR_JACOBI); + CASESTR(CLUSTER_JACOBI); + CASESTR(CLUSTER_TRIDIAGONAL); + default: + return "UNKNOWN"; + } +} + +const char* OrderingTypeToString(OrderingType ordering_type) { + switch (ordering_type) { + CASESTR(NATURAL); + CASESTR(USER); + CASESTR(SCHUR); + default: + return "UNKNOWN"; + } +} + +const char* SolverTerminationTypeToString( + SolverTerminationType termination_type) { + switch (termination_type) { + CASESTR(NO_CONVERGENCE); + CASESTR(FUNCTION_TOLERANCE); + CASESTR(GRADIENT_TOLERANCE); + CASESTR(PARAMETER_TOLERANCE); + CASESTR(NUMERICAL_FAILURE); + CASESTR(USER_ABORT); + CASESTR(USER_SUCCESS); + CASESTR(DID_NOT_RUN); + default: + return "UNKNOWN"; + } +} + +#undef CASESTR + +bool IsSchurType(LinearSolverType type) { + return ((type == SPARSE_SCHUR) || + (type == DENSE_SCHUR) || + (type == ITERATIVE_SCHUR)); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc new file mode 100644 index 00000000000..fd41648a7af --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc @@ -0,0 +1,150 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: kushalav@google.com (Avanish Kushal) + +#include +#include +#include +#include +#include +#include + +#include +#include "ceres/block_structure.h" +#include "ceres/collections_port.h" +#include "ceres/graph.h" + +namespace ceres { +namespace internal { + +void ComputeVisibility(const CompressedRowBlockStructure& block_structure, + const int num_eliminate_blocks, + vector< set >* visibility) { + CHECK_NOTNULL(visibility); + + // Clear the visibility vector and resize it to hold a + // vector for each camera. + visibility->resize(0); + visibility->resize(block_structure.cols.size() - num_eliminate_blocks); + + for (int i = 0; i < block_structure.rows.size(); ++i) { + const vector& cells = block_structure.rows[i].cells; + int block_id = cells[0].block_id; + // If the first block is not an e_block, then skip this row block. + if (block_id >= num_eliminate_blocks) { + continue; + } + + for (int j = 1; j < cells.size(); ++j) { + int camera_block_id = cells[j].block_id - num_eliminate_blocks; + DCHECK_GE(camera_block_id, 0); + DCHECK_LT(camera_block_id, visibility->size()); + (*visibility)[camera_block_id].insert(block_id); + } + } +} + +Graph* CreateSchurComplementGraph(const vector >& visibility) { + const time_t start_time = time(NULL); + // Compute the number of e_blocks/point blocks. Since the visibility + // set for each e_block/camera contains the set of e_blocks/points + // visible to it, we find the maximum across all visibility sets. + int num_points = 0; + for (int i = 0; i < visibility.size(); i++) { + if (visibility[i].size() > 0) { + num_points = max(num_points, (*visibility[i].rbegin()) + 1); + } + } + + // Invert the visibility. The input is a camera->point mapping, + // which tells us which points are visible in which + // cameras. However, to compute the sparsity structure of the Schur + // Complement efficiently, its better to have the point->camera + // mapping. + vector > inverse_visibility(num_points); + for (int i = 0; i < visibility.size(); i++) { + const set& visibility_set = visibility[i]; + for (set::const_iterator it = visibility_set.begin(); + it != visibility_set.end(); + ++it) { + inverse_visibility[*it].insert(i); + } + } + + // Map from camera pairs to number of points visible to both cameras + // in the pair. + HashMap, int > camera_pairs; + + // Count the number of points visible to each camera/f_block pair. + for (vector >::const_iterator it = inverse_visibility.begin(); + it != inverse_visibility.end(); + ++it) { + const set& inverse_visibility_set = *it; + for (set::const_iterator camera1 = inverse_visibility_set.begin(); + camera1 != inverse_visibility_set.end(); + ++camera1) { + set::const_iterator camera2 = camera1; + for (++camera2; camera2 != inverse_visibility_set.end(); ++camera2) { + ++(camera_pairs[make_pair(*camera1, *camera2)]); + } + } + } + + Graph* graph = new Graph(); + + // Add vertices and initialize the pairs for self edges so that self + // edges are guaranteed. This is needed for the Canonical views + // algorithm to work correctly. + static const double kSelfEdgeWeight = 1.0; + for (int i = 0; i < visibility.size(); ++i) { + graph->AddVertex(i); + graph->AddEdge(i, i, kSelfEdgeWeight); + } + + // Add an edge for each camera pair. + for (HashMap, int>::const_iterator it = camera_pairs.begin(); + it != camera_pairs.end(); + ++it) { + const int camera1 = it->first.first; + const int camera2 = it->first.second; + CHECK_NE(camera1, camera2); + + const int count = it->second; + // Static cast necessary for Windows. + const double weight = static_cast(count) / + (sqrt(static_cast(visibility[camera1].size() * visibility[camera2].size()))); + graph->AddEdge(camera1, camera2, weight); + } + + VLOG(2) << "Schur complement graph time: " << (time(NULL) - start_time); + return graph; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.h b/extern/libmv/third_party/ceres/internal/ceres/visibility.h new file mode 100644 index 00000000000..692dd87201e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.h @@ -0,0 +1,77 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: kushalav@google.com (Avanish Kushal) +// sameeragarwal@google.com (Sameer Agarwal) +// +// Functions to manipulate visibility information from the block +// structure of sparse matrices. + +#ifndef CERES_INTERNAL_VISIBILITY_H_ +#define CERES_INTERNAL_VISIBILITY_H_ + +#include +#include +#include "ceres/graph.h" + +namespace ceres { +namespace internal { + +class CompressedRowBlockStructure; + +// Given a compressed row block structure, computes the set of +// e_blocks "visible" to each f_block. If an e_block co-occurs with an +// f_block in a residual block, it is visible to the f_block. The +// first num_eliminate_blocks columns blocks are e_blocks and the rest +// f_blocks. +// +// In a structure from motion problem, e_blocks correspond to 3D +// points and f_blocks correspond to cameras. +void ComputeVisibility(const CompressedRowBlockStructure& block_structure, + int num_eliminate_blocks, + vector >* visibility); + +// Given f_block visibility as computed by the ComputeVisibility +// function above, construct and return a graph whose vertices are +// f_blocks and an edge connects two vertices if they have atleast one +// e_block in common. The weight of this edge is normalized dot +// product between the visibility vectors of the two +// vertices/f_blocks. +// +// This graph reflects the sparsity structure of reduced camera +// matrix/Schur complement matrix obtained by eliminating the e_blocks +// from the normal equations. +// +// Caller acquires ownership of the returned Graph pointer +// (heap-allocated). +Graph* CreateSchurComplementGraph(const vector >& visibility); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_VISIBILITY_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc new file mode 100644 index 00000000000..aca77528215 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc @@ -0,0 +1,611 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/visibility_based_preconditioner.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Eigen/Dense" +#include "ceres/block_random_access_sparse_matrix.h" +#include "ceres/block_sparse_matrix.h" +#include "ceres/canonical_views_clustering.h" +#include "ceres/collections_port.h" +#include "ceres/detect_structure.h" +#include "ceres/graph.h" +#include "ceres/graph_algorithms.h" +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/visibility.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +// TODO(sameeragarwal): Currently these are magic weights for the +// preconditioner construction. Move these higher up into the Options +// struct and provide some guidelines for choosing them. +// +// This will require some more work on the clustering algorithm and +// possibly some more refactoring of the code. +static const double kSizePenaltyWeight = 3.0; +static const double kSimilarityPenaltyWeight = 0.0; + +#ifndef CERES_NO_SUITESPARSE +VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( + const CompressedRowBlockStructure& bs, + const LinearSolver::Options& options) + : options_(options), + num_blocks_(0), + num_clusters_(0), + factor_(NULL) { + CHECK_GT(options_.num_eliminate_blocks, 0); + CHECK(options_.preconditioner_type == SCHUR_JACOBI || + options_.preconditioner_type == CLUSTER_JACOBI || + options_.preconditioner_type == CLUSTER_TRIDIAGONAL) + << "Unknown preconditioner type: " << options_.preconditioner_type; + num_blocks_ = bs.cols.size() - options_.num_eliminate_blocks; + CHECK_GT(num_blocks_, 0) + << "Jacobian should have atleast 1 f_block for " + << "visibility based preconditioning."; + + // Vector of camera block sizes + block_size_.resize(num_blocks_); + for (int i = 0; i < num_blocks_; ++i) { + block_size_[i] = bs.cols[i + options_.num_eliminate_blocks].size; + } + + const time_t start_time = time(NULL); + switch (options_.preconditioner_type) { + case SCHUR_JACOBI: + ComputeSchurJacobiSparsity(bs); + break; + case CLUSTER_JACOBI: + ComputeClusterJacobiSparsity(bs); + break; + case CLUSTER_TRIDIAGONAL: + ComputeClusterTridiagonalSparsity(bs); + break; + default: + LOG(FATAL) << "Unknown preconditioner type"; + } + const time_t structure_time = time(NULL); + InitStorage(bs); + const time_t storage_time = time(NULL); + InitEliminator(bs); + const time_t eliminator_time = time(NULL); + + // Allocate temporary storage for a vector used during + // RightMultiply. + tmp_rhs_ = CHECK_NOTNULL(ss_.CreateDenseVector(NULL, + m_->num_rows(), + m_->num_rows())); + const time_t init_time = time(NULL); + VLOG(2) << "init time: " + << init_time - start_time + << " structure time: " << structure_time - start_time + << " storage time:" << storage_time - structure_time + << " eliminator time: " << eliminator_time - storage_time; +} + +VisibilityBasedPreconditioner::~VisibilityBasedPreconditioner() { + if (factor_ != NULL) { + ss_.Free(factor_); + factor_ = NULL; + } + if (tmp_rhs_ != NULL) { + ss_.Free(tmp_rhs_); + tmp_rhs_ = NULL; + } +} + +// Determine the sparsity structure of the SCHUR_JACOBI +// preconditioner. SCHUR_JACOBI is an extreme case of a visibility +// based preconditioner where each camera block corresponds to a +// cluster and there is no interaction between clusters. +void VisibilityBasedPreconditioner::ComputeSchurJacobiSparsity( + const CompressedRowBlockStructure& bs) { + num_clusters_ = num_blocks_; + cluster_membership_.resize(num_blocks_); + cluster_pairs_.clear(); + + // Each camea block is a member of its own cluster and the only + // cluster pairs are the self edges (i,i). + for (int i = 0; i < num_clusters_; ++i) { + cluster_membership_[i] = i; + cluster_pairs_.insert(make_pair(i, i)); + } +} + +// Determine the sparsity structure of the CLUSTER_JACOBI +// preconditioner. It clusters cameras using their scene +// visibility. The clusters form the diagonal blocks of the +// preconditioner matrix. +void VisibilityBasedPreconditioner::ComputeClusterJacobiSparsity( + const CompressedRowBlockStructure& bs) { + vector > visibility; + ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility); + CHECK_EQ(num_blocks_, visibility.size()); + ClusterCameras(visibility); + cluster_pairs_.clear(); + for (int i = 0; i < num_clusters_; ++i) { + cluster_pairs_.insert(make_pair(i, i)); + } +} + +// Determine the sparsity structure of the CLUSTER_TRIDIAGONAL +// preconditioner. It clusters cameras using using the scene +// visibility and then finds the strongly interacting pairs of +// clusters by constructing another graph with the clusters as +// vertices and approximating it with a degree-2 maximum spanning +// forest. The set of edges in this forest are the cluster pairs. +void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity( + const CompressedRowBlockStructure& bs) { + vector > visibility; + ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility); + CHECK_EQ(num_blocks_, visibility.size()); + ClusterCameras(visibility); + + // Construct a weighted graph on the set of clusters, where the + // edges are the number of 3D points/e_blocks visible in both the + // clusters at the ends of the edge. Return an approximate degree-2 + // maximum spanning forest of this graph. + vector > cluster_visibility; + ComputeClusterVisibility(visibility, &cluster_visibility); + scoped_ptr > cluster_graph( + CHECK_NOTNULL(CreateClusterGraph(cluster_visibility))); + scoped_ptr > forest( + CHECK_NOTNULL(Degree2MaximumSpanningForest(*cluster_graph))); + ForestToClusterPairs(*forest, &cluster_pairs_); +} + +// Allocate storage for the preconditioner matrix. +void VisibilityBasedPreconditioner::InitStorage( + const CompressedRowBlockStructure& bs) { + ComputeBlockPairsInPreconditioner(bs); + m_.reset(new BlockRandomAccessSparseMatrix(block_size_, block_pairs_)); +} + +// Call the canonical views algorithm and cluster the cameras based on +// their visibility sets. The visibility set of a camera is the set of +// e_blocks/3D points in the scene that are seen by it. +// +// The cluster_membership_ vector is updated to indicate cluster +// memberships for each camera block. +void VisibilityBasedPreconditioner::ClusterCameras( + const vector >& visibility) { + scoped_ptr > schur_complement_graph( + CHECK_NOTNULL(CreateSchurComplementGraph(visibility))); + + CanonicalViewsClusteringOptions options; + options.size_penalty_weight = kSizePenaltyWeight; + options.similarity_penalty_weight = kSimilarityPenaltyWeight; + + vector centers; + HashMap membership; + ComputeCanonicalViewsClustering(*schur_complement_graph, + options, + ¢ers, + &membership); + num_clusters_ = centers.size(); + CHECK_GT(num_clusters_, 0); + VLOG(2) << "num_clusters: " << num_clusters_; + FlattenMembershipMap(membership, &cluster_membership_); +} + +// Compute the block sparsity structure of the Schur complement +// matrix. For each pair of cameras contributing a non-zero cell to +// the schur complement, determine if that cell is present in the +// preconditioner or not. +// +// A pair of cameras contribute a cell to the preconditioner if they +// are part of the same cluster or if the the two clusters that they +// belong have an edge connecting them in the degree-2 maximum +// spanning forest. +// +// For example, a camera pair (i,j) where i belonges to cluster1 and +// j belongs to cluster2 (assume that cluster1 < cluster2). +// +// The cell corresponding to (i,j) is present in the preconditioner +// if cluster1 == cluster2 or the pair (cluster1, cluster2) were +// connected by an edge in the degree-2 maximum spanning forest. +// +// Since we have already expanded the forest into a set of camera +// pairs/edges, including self edges, the check can be reduced to +// checking membership of (cluster1, cluster2) in cluster_pairs_. +void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( + const CompressedRowBlockStructure& bs) { + block_pairs_.clear(); + for (int i = 0; i < num_blocks_; ++i) { + block_pairs_.insert(make_pair(i, i)); + } + + int r = 0; + set > skipped_pairs; + const int num_row_blocks = bs.rows.size(); + const int num_eliminate_blocks = options_.num_eliminate_blocks; + + // Iterate over each row of the matrix. The block structure of the + // matrix is assumed to be sorted in order of the e_blocks/point + // blocks. Thus all row blocks containing an e_block/point occur + // contiguously. Further, if present, an e_block is always the first + // parameter block in each row block. These structural assumptions + // are common to all Schur complement based solvers in Ceres. + // + // For each e_block/point block we identify the set of cameras + // seeing it. The cross product of this set with itself is the set + // of non-zero cells contibuted by this e_block. + // + // The time complexity of this is O(nm^2) where, n is the number of + // 3d points and m is the maximum number of cameras seeing any + // point, which for most scenes is a fairly small number. + while (r < num_row_blocks) { + int e_block_id = bs.rows[r].cells.front().block_id; + if (e_block_id >= num_eliminate_blocks) { + // Skip the rows whose first block is an f_block. + break; + } + + set f_blocks; + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs.rows[r]; + if (row.cells.front().block_id != e_block_id) { + break; + } + + // Iterate over the blocks in the row, ignoring the first block + // since it is the one to be eliminated and adding the rest to + // the list of f_blocks associated with this e_block. + for (int c = 1; c < row.cells.size(); ++c) { + const Cell& cell = row.cells[c]; + const int f_block_id = cell.block_id - num_eliminate_blocks; + CHECK_GE(f_block_id, 0); + f_blocks.insert(f_block_id); + } + } + + for (set::const_iterator block1 = f_blocks.begin(); + block1 != f_blocks.end(); + ++block1) { + set::const_iterator block2 = block1; + ++block2; + for (; block2 != f_blocks.end(); ++block2) { + if (IsBlockPairInPreconditioner(*block1, *block2)) { + block_pairs_.insert(make_pair(*block1, *block2)); + } else { + skipped_pairs.insert(make_pair(*block1, *block2)); + } + } + } + } + + // The remaining rows which do not contain any e_blocks. + for (; r < num_row_blocks; ++r) { + const CompressedRow& row = bs.rows[r]; + CHECK_GE(row.cells.front().block_id, num_eliminate_blocks); + for (int i = 0; i < row.cells.size(); ++i) { + const int block1 = row.cells[i].block_id - num_eliminate_blocks; + for (int j = 0; j < row.cells.size(); ++j) { + const int block2 = row.cells[j].block_id - num_eliminate_blocks; + if (block1 <= block2) { + if (IsBlockPairInPreconditioner(block1, block2)) { + block_pairs_.insert(make_pair(block1, block2)); + } else { + skipped_pairs.insert(make_pair(block1, block2)); + } + } + } + } + } + + VLOG(1) << "Block pair stats: " + << block_pairs_.size() << " included " + << skipped_pairs.size() << " excluded"; +} + +// Initialize the SchurEliminator. +void VisibilityBasedPreconditioner::InitEliminator( + const CompressedRowBlockStructure& bs) { + LinearSolver::Options eliminator_options; + eliminator_options.num_eliminate_blocks = options_.num_eliminate_blocks; + eliminator_options.num_threads = options_.num_threads; + eliminator_options.constant_sparsity = true; + + DetectStructure(bs, options_.num_eliminate_blocks, + &eliminator_options.row_block_size, + &eliminator_options.e_block_size, + &eliminator_options.f_block_size); + + eliminator_.reset(SchurEliminatorBase::Create(eliminator_options)); + eliminator_->Init(options_.num_eliminate_blocks, &bs); +} + +// Compute the values of the preconditioner matrix and factorize it. +bool VisibilityBasedPreconditioner::Compute(const BlockSparseMatrixBase& A, + const double* D) { + const time_t start_time = time(NULL); + const int num_rows = m_->num_rows(); + CHECK_GT(num_rows, 0); + + // We need a dummy rhs vector and a dummy b vector since the Schur + // eliminator combines the computation of the reduced camera matrix + // with the computation of the right hand side of that linear + // system. + // + // TODO(sameeragarwal): Perhaps its worth refactoring the + // SchurEliminator::Eliminate function to allow NULL for the rhs. As + // of now it does not seem to be worth the effort. + Vector rhs = Vector::Zero(m_->num_rows()); + Vector b = Vector::Zero(A.num_rows()); + + // Compute a subset of the entries of the Schur complement. + eliminator_->Eliminate(&A, b.data(), D, m_.get(), rhs.data()); + + // Try factorizing the matrix. For SCHUR_JACOBI and CLUSTER_JACOBI, + // this should always succeed modulo some numerical/conditioning + // problems. For CLUSTER_TRIDIAGONAL, in general the preconditioner + // matrix as constructed is not positive definite. However, we will + // go ahead and try factorizing it. If it works, great, otherwise we + // scale all the cells in the preconditioner corresponding to the + // edges in the degree-2 forest and that guarantees positive + // definiteness. The proof of this fact can be found in Lemma 1 in + // "Visibility Based Preconditioning for Bundle Adjustment". + // + // Doing the factorization like this saves us matrix mass when + // scaling is not needed, which is quite often in our experience. + bool status = Factorize(); + + // The scaling only affects the tri-diagonal case, since + // ScaleOffDiagonalBlocks only pays attenion to the cells that + // belong to the edges of the degree-2 forest. In the SCHUR_JACOBI + // and the CLUSTER_JACOBI cases, the preconditioner is guaranteed to + // be positive semidefinite. + if (!status && options_.preconditioner_type == CLUSTER_TRIDIAGONAL) { + VLOG(1) << "Unscaled factorization failed. Retrying with off-diagonal " + << "scaling"; + ScaleOffDiagonalCells(); + status = Factorize(); + } + + VLOG(2) << "Compute time: " << time(NULL) - start_time; + return status; +} + +// Consider the preconditioner matrix as meta-block matrix, whose +// blocks correspond to the clusters. Then cluster pairs corresponding +// to edges in the degree-2 forest are off diagonal entries of this +// matrix. Scaling these off-diagonal entries by 1/2 forces this +// matrix to be positive definite. +void VisibilityBasedPreconditioner::ScaleOffDiagonalCells() { + for (set< pair >::const_iterator it = block_pairs_.begin(); + it != block_pairs_.end(); + ++it) { + const int block1 = it->first; + const int block2 = it->second; + if (!IsBlockPairOffDiagonal(block1, block2)) { + continue; + } + + int r, c, row_stride, col_stride; + CellInfo* cell_info = m_->GetCell(block1, block2, + &r, &c, + &row_stride, &col_stride); + CHECK(cell_info != NULL) + << "Cell missing for block pair (" << block1 << "," << block2 << ")" + << " cluster pair (" << cluster_membership_[block1] + << " " << cluster_membership_[block2] << ")"; + + // Ah the magic of tri-diagonal matrices and diagonal + // dominance. See Lemma 1 in "Visibility Based Preconditioning + // For Bundle Adjustment". + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block_size_[block1], block_size_[block2]) *= 0.5; + } +} + +// Compute the sparse Cholesky factorization of the preconditioner +// matrix. +bool VisibilityBasedPreconditioner::Factorize() { + // Extract the TripletSparseMatrix that is used for actually storing + // S and convert it into a cholmod_sparse object. + cholmod_sparse* lhs = ss_.CreateSparseMatrix( + down_cast( + m_.get())->mutable_matrix()); + + // The matrix is symmetric, and the upper triangular part of the + // matrix contains the values. + lhs->stype = 1; + + // Symbolic factorization is computed if we don't already have one + // handy. + if (factor_ == NULL) { + factor_ = ss_.AnalyzeCholesky(lhs); + } + + bool status = ss_.Cholesky(lhs, factor_); + ss_.Free(lhs); + return status; +} + +void VisibilityBasedPreconditioner::RightMultiply(const double* x, + double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + SuiteSparse* ss = const_cast(&ss_); + + const int num_rows = m_->num_rows(); + memcpy(CHECK_NOTNULL(tmp_rhs_)->x, x, m_->num_rows() * sizeof(*x)); + cholmod_dense* solution = CHECK_NOTNULL(ss->Solve(factor_, tmp_rhs_)); + memcpy(y, solution->x, sizeof(*y) * num_rows); + ss->Free(solution); +} + +int VisibilityBasedPreconditioner::num_rows() const { + return m_->num_rows(); +} + +// Classify camera/f_block pairs as in and out of the preconditioner, +// based on whether the cluster pair that they belong to is in the +// preconditioner or not. +bool VisibilityBasedPreconditioner::IsBlockPairInPreconditioner( + const int block1, + const int block2) const { + int cluster1 = cluster_membership_[block1]; + int cluster2 = cluster_membership_[block2]; + if (cluster1 > cluster2) { + std::swap(cluster1, cluster2); + } + return (cluster_pairs_.count(make_pair(cluster1, cluster2)) > 0); +} + +bool VisibilityBasedPreconditioner::IsBlockPairOffDiagonal( + const int block1, + const int block2) const { + return (cluster_membership_[block1] != cluster_membership_[block2]); +} + +// Convert a graph into a list of edges that includes self edges for +// each vertex. +void VisibilityBasedPreconditioner::ForestToClusterPairs( + const Graph& forest, + HashSet >* cluster_pairs) const { + CHECK_NOTNULL(cluster_pairs)->clear(); + const HashSet& vertices = forest.vertices(); + CHECK_EQ(vertices.size(), num_clusters_); + + // Add all the cluster pairs corresponding to the edges in the + // forest. + for (HashSet::const_iterator it1 = vertices.begin(); + it1 != vertices.end(); + ++it1) { + const int cluster1 = *it1; + cluster_pairs->insert(make_pair(cluster1, cluster1)); + const HashSet& neighbors = forest.Neighbors(cluster1); + for (HashSet::const_iterator it2 = neighbors.begin(); + it2 != neighbors.end(); + ++it2) { + const int cluster2 = *it2; + if (cluster1 < cluster2) { + cluster_pairs->insert(make_pair(cluster1, cluster2)); + } + } + } +} + +// The visibilty set of a cluster is the union of the visibilty sets +// of all its cameras. In other words, the set of points visible to +// any camera in the cluster. +void VisibilityBasedPreconditioner::ComputeClusterVisibility( + const vector >& visibility, + vector >* cluster_visibility) const { + CHECK_NOTNULL(cluster_visibility)->resize(0); + cluster_visibility->resize(num_clusters_); + for (int i = 0; i < num_blocks_; ++i) { + const int cluster_id = cluster_membership_[i]; + (*cluster_visibility)[cluster_id].insert(visibility[i].begin(), + visibility[i].end()); + } +} + +// Construct a graph whose vertices are the clusters, and the edge +// weights are the number of 3D points visible to cameras in both the +// vertices. +Graph* VisibilityBasedPreconditioner::CreateClusterGraph( + const vector >& cluster_visibility) const { + Graph* cluster_graph = new Graph; + + for (int i = 0; i < num_clusters_; ++i) { + cluster_graph->AddVertex(i); + } + + for (int i = 0; i < num_clusters_; ++i) { + const set& cluster_i = cluster_visibility[i]; + for (int j = i+1; j < num_clusters_; ++j) { + vector intersection; + const set& cluster_j = cluster_visibility[j]; + set_intersection(cluster_i.begin(), cluster_i.end(), + cluster_j.begin(), cluster_j.end(), + back_inserter(intersection)); + + if (intersection.size() > 0) { + // Clusters interact strongly when they share a large number + // of 3D points. The degree-2 maximum spanning forest + // alorithm, iterates on the edges in decreasing order of + // their weight, which is the number of points shared by the + // two cameras that it connects. + cluster_graph->AddEdge(i, j, intersection.size()); + } + } + } + return cluster_graph; +} + +// Canonical views clustering returns a HashMap from vertices to +// cluster ids. Convert this into a flat array for quick lookup. It is +// possible that some of the vertices may not be associated with any +// cluster. In that case, randomly assign them to one of the clusters. +void VisibilityBasedPreconditioner::FlattenMembershipMap( + const HashMap& membership_map, + vector* membership_vector) const { + CHECK_NOTNULL(membership_vector)->resize(0); + membership_vector->resize(num_blocks_, -1); + // Iterate over the cluster membership map and update the + // cluster_membership_ vector assigning arbitrary cluster ids to + // the few cameras that have not been clustered. + for (HashMap::const_iterator it = membership_map.begin(); + it != membership_map.end(); + ++it) { + const int camera_id = it->first; + int cluster_id = it->second; + + // If the view was not clustered, randomly assign it to one of the + // clusters. This preserves the mathematical correctness of the + // preconditioner. If there are too many views which are not + // clustered, it may lead to some quality degradation though. + // + // TODO(sameeragarwal): Check if a large number of views have not + // been clustered and deal with it? + if (cluster_id == -1) { + cluster_id = camera_id % num_clusters_; + } + + membership_vector->at(camera_id) = cluster_id; + } +} + +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h new file mode 100644 index 00000000000..fa095ca1dd8 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h @@ -0,0 +1,273 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Preconditioners for linear systems that arise in Structure from +// Motion problems. VisibilityBasedPreconditioner implements three +// preconditioners: +// +// SCHUR_JACOBI +// CLUSTER_JACOBI +// CLUSTER_TRIDIAGONAL +// +// Detailed descriptions of these preconditions beyond what is +// documented here can be found in +// +// Bundle Adjustment in the Large +// S. Agarwal, N. Snavely, S. Seitz & R. Szeliski, ECCV 2010 +// http://www.cs.washington.edu/homes/sagarwal/bal.pdf +// +// Visibility Based Preconditioning for Bundle Adjustment +// A. Kushal & S. Agarwal, submitted to CVPR 2012 +// http://www.cs.washington.edu/homes/sagarwal/vbp.pdf +// +// The three preconditioners share enough code that its most efficient +// to implement them as part of the same code base. + +#ifndef CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ +#define CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ + +#include +#include +#include +#include "ceres/collections_port.h" +#include "ceres/graph.h" +#include "ceres/linear_solver.h" +#include "ceres/linear_operator.h" +#include "ceres/suitesparse.h" +#include "ceres/internal/macros.h" +#include "ceres/internal/scoped_ptr.h" + +namespace ceres { +namespace internal { + +class BlockRandomAccessSparseMatrix; +class BlockSparseMatrixBase; +class CompressedRowBlockStructure; +class SchurEliminatorBase; + +// This class implements three preconditioners for Structure from +// Motion/Bundle Adjustment problems. The name +// VisibilityBasedPreconditioner comes from the fact that the sparsity +// structure of the preconditioner matrix is determined by analyzing +// the visibility structure of the scene, i.e. which cameras see which +// points. +// +// Strictly speaking, SCHUR_JACOBI is not a visibility based +// preconditioner but it is an extreme case of CLUSTER_JACOBI, where +// every cluster contains exactly one camera block. Treating it as a +// special case of CLUSTER_JACOBI makes it easy to implement as part +// of the same code base with no significant loss of performance. +// +// In the following, we will only discuss CLUSTER_JACOBI and +// CLUSTER_TRIDIAGONAL. +// +// The key idea of visibility based preconditioning is to identify +// cameras that we expect have strong interactions, and then using the +// entries in the Schur complement matrix corresponding to these +// camera pairs as an approximation to the full Schur complement. +// +// CLUSTER_JACOBI identifies these camera pairs by clustering cameras, +// and considering all non-zero camera pairs within each cluster. The +// clustering in the current implementation is done using the +// Canonical Views algorithm of Simon et al. (see +// canonical_views_clustering.h). For the purposes of clustering, the +// similarity or the degree of interaction between a pair of cameras +// is measured by counting the number of points visible in both the +// cameras. Thus the name VisibilityBasedPreconditioner. Further, if we +// were to permute the parameter blocks such that all the cameras in +// the same cluster occur contiguously, the preconditioner matrix will +// be a block diagonal matrix with blocks corresponding to the +// clusters. Thus in analogy with the Jacobi preconditioner we refer +// to this as the CLUSTER_JACOBI preconditioner. +// +// CLUSTER_TRIDIAGONAL adds more mass to the CLUSTER_JACOBI +// preconditioner by considering the interaction between clusters and +// identifying strong interactions between cluster pairs. This is done +// by constructing a weighted graph on the clusters, with the weight +// on the edges connecting two clusters proportional to the number of +// 3D points visible to cameras in both the clusters. A degree-2 +// maximum spanning forest is identified in this graph and the camera +// pairs contained in the edges of this forest are added to the +// preconditioner. The detailed reasoning for this construction is +// explained in the paper mentioned above. +// +// Degree-2 spanning trees and forests have the property that they +// correspond to tri-diagonal matrices. Thus there exist a permutation +// of the camera blocks under which the CLUSTER_TRIDIAGONAL +// preconditioner matrix is a block tridiagonal matrix, and thus the +// name for the preconditioner. +// +// Thread Safety: This class is NOT thread safe. +// +// Example usage: +// +// LinearSolver::Options options; +// options.preconditioner_type = CLUSTER_JACOBI; +// options.num_eliminate_blocks = num_points; +// VisibilityBasedPreconditioner preconditioner( +// *A.block_structure(), options); +// preconditioner.Compute(A, NULL); +// preconditioner.RightMultiply(x, y); +// + +#ifndef CERES_NO_SUITESPARSE +class VisibilityBasedPreconditioner : public LinearOperator { + public: + // Initialize the symbolic structure of the preconditioner. bs is + // the block structure of the linear system to be solved. It is used + // to determine the sparsity structure of the preconditioner matrix. + // + // It has the same structural requirement as other Schur complement + // based solvers. Please see schur_eliminator.h for more details. + // + // LinearSolver::Options::num_eliminate_blocks should be set to the + // number of e_blocks in the block structure. + // + // TODO(sameeragarwal): The use of LinearSolver::Options should + // ultimately be replaced with Preconditioner::Options and some sort + // of preconditioner factory along the lines of + // LinearSolver::CreateLinearSolver. I will wait to do this till I + // create a general purpose block Jacobi preconditioner for general + // sparse problems along with a CGLS solver. + VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs, + const LinearSolver::Options& options); + virtual ~VisibilityBasedPreconditioner(); + + // Compute the numerical value of the preconditioner for the linear + // system: + // + // | A | x = |b| + // |diag(D)| |0| + // + // for some vector b. It is important that the matrix A have the + // same block structure as the one used to construct this object. + // + // D can be NULL, in which case its interpreted as a diagonal matrix + // of size zero. + bool Compute(const BlockSparseMatrixBase& A, + const double* D); + + // LinearOperator interface. Since the operator is symmetric, + // LeftMultiply and num_cols are just calls to RightMultiply and + // num_rows respectively. Compute() must be called before + // RightMultiply can be called. + virtual void RightMultiply(const double* x, double* y) const; + virtual void LeftMultiply(const double* x, double* y) const { + RightMultiply(x, y); + } + virtual int num_rows() const; + virtual int num_cols() const { return num_rows(); } + + friend class VisibilityBasedPreconditionerTest; + private: + void ComputeSchurJacobiSparsity(const CompressedRowBlockStructure& bs); + void ComputeClusterJacobiSparsity(const CompressedRowBlockStructure& bs); + void ComputeClusterTridiagonalSparsity(const CompressedRowBlockStructure& bs); + void InitStorage(const CompressedRowBlockStructure& bs); + void InitEliminator(const CompressedRowBlockStructure& bs); + bool Factorize(); + void ScaleOffDiagonalCells(); + + void ClusterCameras(const vector< set >& visibility); + void FlattenMembershipMap(const HashMap& membership_map, + vector* membership_vector) const; + void ComputeClusterVisibility(const vector >& visibility, + vector >* cluster_visibility) const; + Graph* CreateClusterGraph(const vector >& visibility) const; + void ForestToClusterPairs(const Graph& forest, + HashSet >* cluster_pairs) const; + void ComputeBlockPairsInPreconditioner(const CompressedRowBlockStructure& bs); + bool IsBlockPairInPreconditioner(int block1, int block2) const; + bool IsBlockPairOffDiagonal(int block1, int block2) const; + + LinearSolver::Options options_; + + // Number of parameter blocks in the schur complement. + int num_blocks_; + int num_clusters_; + + // Sizes of the blocks in the schur complement. + vector block_size_; + + // Mapping from cameras to clusters. + vector cluster_membership_; + + // Non-zero camera pairs from the schur complement matrix that are + // present in the preconditioner, sorted by row (first element of + // each pair), then column (second). + set > block_pairs_; + + // Set of cluster pairs (including self pairs (i,i)) in the + // preconditioner. + HashSet > cluster_pairs_; + scoped_ptr eliminator_; + + // Preconditioner matrix. + scoped_ptr m_; + + // RightMultiply is a const method for LinearOperators. It is + // implemented using CHOLMOD's sparse triangular matrix solve + // function. This however requires non-const access to the + // SuiteSparse context object, even though it does not result in any + // of the state of the preconditioner being modified. + SuiteSparse ss_; + + // Symbolic and numeric factorization of the preconditioner. + cholmod_factor* factor_; + + // Temporary vector used by RightMultiply. + cholmod_dense* tmp_rhs_; + DISALLOW_COPY_AND_ASSIGN(VisibilityBasedPreconditioner); +}; +#else // SuiteSparse +// If SuiteSparse is not compiled in, the preconditioner is not +// available. +class VisibilityBasedPreconditioner : public LinearOperator { + public: + VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs, + const LinearSolver::Options& options) { + LOG(FATAL) << "Visibility based preconditioning is not available. Please " + "build Ceres with SuiteSparse."; + } + virtual ~VisibilityBasedPreconditioner() {} + virtual void RightMultiply(const double* x, double* y) const {} + virtual void LeftMultiply(const double* x, double* y) const {} + virtual int num_rows() const { return -1; } + virtual int num_cols() const { return -1; } + bool Compute(const BlockSparseMatrixBase& A, const double* D) { + return false; + } +}; +#endif // CERES_NO_SUITESPARSE + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_ diff --git a/extern/libmv/third_party/ceres/mkfiles.sh b/extern/libmv/third_party/ceres/mkfiles.sh new file mode 100644 index 00000000000..d335829aa2c --- /dev/null +++ b/extern/libmv/third_party/ceres/mkfiles.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +find ./include/ -type f | sed -r 's/^\.\///' | sort > files.txt +find ./internal/ -type f | sed -r 's/^\.\///' | sort >> files.txt diff --git a/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch b/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch new file mode 100644 index 00000000000..c3129d8e02b --- /dev/null +++ b/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch @@ -0,0 +1,15 @@ +diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc +index ed3499b..28e0313 100644 +--- a/internal/ceres/residual_block_utils.cc ++++ b/internal/ceres/residual_block_utils.cc +@@ -40,6 +40,10 @@ + #include "ceres/internal/eigen.h" + #include "ceres/internal/port.h" + ++#ifdef _MSC_VER ++# define isfinite _finite ++#endif ++ + namespace ceres { + namespace internal { + diff --git a/extern/libmv/third_party/ceres/patches/series b/extern/libmv/third_party/ceres/patches/series new file mode 100644 index 00000000000..dbe955ae61e --- /dev/null +++ b/extern/libmv/third_party/ceres/patches/series @@ -0,0 +1 @@ +msvc_isfinite.patch diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 2c2b3f6df8a..99db5576fa0 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -163,6 +163,7 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) + list(APPEND BLENDER_SORTED_LIBS extern_ceres) endif() list(APPEND BLENDER_SORTED_LIBS extern_colamd) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index ac52acc3043..0e1a597386f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -900,6 +900,7 @@ endif() if(WITH_LIBMV) list(APPEND BLENDER_SORTED_LIBS extern_libmv) + list(APPEND BLENDER_SORTED_LIBS extern_ceres) endif() if(WITH_MOD_CLOTH_ELTOPO) -- cgit v1.2.3 From 25bb441301a52b10ce12efa2adb99f7ce5abddb6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 15:28:19 +0000 Subject: Planar tracking support for motion tracking =========================================== Major list of changes done in tomato branch: - Add a planar tracking implementation to libmv This adds a new planar tracking implementation to libmv. The tracker is based on Ceres[1], the new nonlinear minimizer that myself and Sameer released from Google as open source. Since the motion model is more involved, the interface is different than the RegionTracker interface used previously in Blender. The start of a C API in libmv-capi.{cpp,h} is also included. - Migrate from pat_{min,max} for markers to 4 corners representation Convert markers in the movie clip editor / 2D tracker from using pat_min and pat_max notation to using the a more general, 4-corner representation. There is still considerable porting work to do; in particular sliding from preview widget does not work correct for rotated markers. All other areas should be ported to new representation: * Added support of sliding individual corners. LMB slide + Ctrl would scale the whole pattern * S would scale the whole marker, S-S would scale pattern only * Added support of marker's rotation which is currently rotates only patterns around their centers or all markers around median, Rotation or other non-translation/scaling transformation of search area doesn't make sense. * Track Preview widget would display transformed pattern which libmv actually operates with. - "Efficient Second-order Minimization" for the planar tracker This implements the "Efficient Second-order Minimization" scheme, as supported by the existing translation tracker. This increases the amount of per-iteration work, but decreases the number of iterations required to converge and also increases the size of the basin of attraction for the optimization. - Remove the use of the legacy RegionTracker API from Blender, and replaces it with the new TrackRegion API. This also adds several features to the planar tracker in libmv: * Do a brute-force initialization of tracking similar to "Hybrid" mode in the stable release, but using all floats. This is slower but more accurate. It is still necessary to evaluate if the performance loss is worth it. In particular, this change is necessary to support high bit depth imagery. * Add support for masks over the search window. This is a step towards supporting user-defined tracker masks. The tracker masks will make it easy for users to make a mask for e.g. a ball. Not exposed into interface yet/ * Add Pearson product moment correlation coefficient checking (aka "Correlation" in the UI. This causes tracking failure if the tracked patch is not linearly related to the template. * Add support for warping a few points in addition to the supplied points. This is useful because the tracking code deliberately does not expose the underlying warp representation. Instead, warps are specified in an aparametric way via the correspondences. - Replace the old style tracker configuration panel with the new planar tracking panel. From a users perspective, this means: * The old "tracking algorithm" picker is gone. There is only 1 algorithm now. We may revisit this later, but I would much prefer to have only 1 algorithm. So far no optimization work has been done so the speed is not there yet. * There is now a dropdown to select the motion model. Choices: * Translation * Translation, rotation * Translation, scale * Translation, rotation, scale * Affine * Perspective * The old "Hybrid" mode is gone; instead there is a toggle to enable or disable translation-only tracker initialization. This is the equivalent of the hyrbid mode before, but rewritten to work with the new planar tracking modes. * The pyramid levels setting is gone. At a future date, the planar tracker will decide to use pyramids or not automatically. The pyramid setting was ultimately a mistake; with the brute force initialization it is unnecessary. - Add light-normalized tracking Added the ability to normalize patterns by their average value while tracking, to make them invariant to global illumination changes. Additional details could be found at wiki page [2] [1] http://code.google.com/p/ceres-solver [2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker --- extern/libmv/CMakeLists.txt | 2 + extern/libmv/libmv-capi.cpp | 149 ++- extern/libmv/libmv-capi.h | 26 + extern/libmv/libmv/image/sample.h | 64 +- extern/libmv/libmv/multiview/homography.cc | 267 ++++ extern/libmv/libmv/multiview/homography.h | 84 ++ .../libmv/multiview/homography_parameterization.h | 91 ++ extern/libmv/libmv/tracking/esm_region_tracker.cc | 39 + extern/libmv/libmv/tracking/track_region.cc | 1391 ++++++++++++++++++++ extern/libmv/libmv/tracking/track_region.h | 146 ++ release/scripts/startup/bl_ui/space_clip.py | 14 +- source/blender/blenkernel/BKE_tracking.h | 15 +- source/blender/blenkernel/intern/movieclip.c | 38 +- source/blender/blenkernel/intern/tracking.c | 730 ++++++---- source/blender/blenloader/intern/readfile.c | 54 +- source/blender/editors/interface/interface_draw.c | 85 +- source/blender/editors/space_clip/clip_buttons.c | 91 +- source/blender/editors/space_clip/clip_draw.c | 260 ++-- source/blender/editors/space_clip/space_clip.c | 4 + source/blender/editors/space_clip/tracking_ops.c | 301 ++++- source/blender/editors/transform/transform.c | 15 + .../editors/transform/transform_conversions.c | 131 +- .../blender/editors/transform/transform_generics.c | 15 +- source/blender/editors/transform/transform_ops.c | 1 + source/blender/makesdna/DNA_movieclip_types.h | 3 + source/blender/makesdna/DNA_tracking_types.h | 83 +- source/blender/makesrna/RNA_access.h | 2 + source/blender/makesrna/intern/rna_tracking.c | 242 ++-- 28 files changed, 3530 insertions(+), 813 deletions(-) create mode 100644 extern/libmv/libmv/multiview/homography.cc create mode 100644 extern/libmv/libmv/multiview/homography.h create mode 100644 extern/libmv/libmv/multiview/homography_parameterization.h create mode 100644 extern/libmv/libmv/tracking/track_region.cc create mode 100644 extern/libmv/libmv/tracking/track_region.h diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index cf0ad1102e0..60cd84d89d4 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC libmv/multiview/fundamental.cc libmv/multiview/projection.cc libmv/multiview/triangulation.cc + libmv/multiview/homography.cc libmv/numeric/numeric.cc libmv/numeric/poly.cc libmv/simple_pipeline/bundle.cc @@ -84,6 +85,7 @@ set(SRC libmv/tracking/pyramid_region_tracker.cc libmv/tracking/retrack_region_tracker.cc libmv/tracking/trklt_region_tracker.cc + libmv/tracking/track_region.cc third_party/fast/fast_10.c third_party/fast/fast_11.c diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 6c20d76eeac..ffa065f08fe 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -28,6 +28,10 @@ tracking between which failed */ #undef DUMP_FAILURE +/* define this to generate PNG images with content of search areas + on every itteration of tracking */ +#undef DUMP_ALWAYS + #include "libmv-capi.h" #include "third_party/gflags/gflags/gflags.h" @@ -45,6 +49,7 @@ #include "libmv/tracking/trklt_region_tracker.h" #include "libmv/tracking/lmicklt_region_tracker.h" #include "libmv/tracking/pyramid_region_tracker.h" +#include "libmv/tracking/track_region.h" #include "libmv/simple_pipeline/callbacks.h" #include "libmv/simple_pipeline/tracks.h" @@ -59,7 +64,7 @@ #include #include -#ifdef DUMP_FAILURE +#if defined(DUMP_FAILURE) || defined (DUMP_ALWAYS) # include #endif @@ -97,7 +102,7 @@ void libmv_initLogging(const char *argv0) void libmv_startDebugLogging(void) { google::SetCommandLineOption("logtostderr", "1"); - google::SetCommandLineOption("v", "0"); + google::SetCommandLineOption("v", "2"); google::SetCommandLineOption("stderrthreshold", "1"); google::SetCommandLineOption("minloglevel", "0"); V3D::optimizerVerbosenessLevel = 1; @@ -158,20 +163,35 @@ libmv_RegionTracker *libmv_bruteRegionTrackerNew(int half_window_size, double mi return (libmv_RegionTracker *)brute_region_tracker; } -static void floatBufToImage(const float *buf, int width, int height, libmv::FloatImage *image) +static void floatBufToImage(const float *buf, int width, int height, int channels, libmv::FloatImage *image) { - int x, y, a = 0; + int x, y, k, a = 0; - image->resize(height, width); + image->Resize(height, width, channels); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - (*image)(y, x, 0) = buf[a++]; + for (k = 0; k < channels; k++) { + (*image)(y, x, k) = buf[a++]; + } + } + } +} + +static void imageToFloatBuf(const libmv::FloatImage *image, int channels, float *buf) +{ + int x, y, k, a = 0; + + for (y = 0; y < image->Height(); y++) { + for (x = 0; x < image->Width(); x++) { + for (k = 0; k < channels; k++) { + buf[a++] = (*image)(y, x, k); + } } } } -#ifdef DUMP_FAILURE +#if defined(DUMP_FAILURE) || defined (DUMP_ALWAYS) void savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, char *file_name) { png_infop info_ptr; @@ -234,14 +254,14 @@ static void saveImage(char *prefix, libmv::FloatImage image, int x0, int y0) row_pointers[y]= (png_bytep)malloc(sizeof(png_byte)*4*image.Width()); for (x = 0; x < image.Width(); x++) { - if (x0 == x && y0 == y) { + if (x0 == x && image.Height() - y0 - 1 == y) { row_pointers[y][x*4+0]= 255; row_pointers[y][x*4+1]= 0; row_pointers[y][x*4+2]= 0; row_pointers[y][x*4+3]= 255; } else { - float pixel = image(y, x, 0); + float pixel = image(image.Height() - y - 1, x, 0); row_pointers[y][x*4+0]= pixel*255; row_pointers[y][x*4+1]= pixel*255; row_pointers[y][x*4+2]= pixel*255; @@ -302,19 +322,23 @@ int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *im libmv::RegionTracker *region_tracker = (libmv::RegionTracker *)libmv_tracker; libmv::FloatImage old_patch, new_patch; - floatBufToImage(ima1, width, height, &old_patch); - floatBufToImage(ima2, width, height, &new_patch); + floatBufToImage(ima1, width, height, 1, &old_patch); + floatBufToImage(ima2, width, height, 1, &new_patch); -#ifndef DUMP_FAILURE +#if !defined(DUMP_FAILURE) && !defined(DUMP_ALWAYS) return region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2); #else { - double sx2 = *x2, sy2 = *y2; + /* double sx2 = *x2, sy2 = *y2; */ int result = region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2); +#if defined(DUMP_ALWAYS) + { +#else if (!result) { +#endif saveImage("old_patch", old_patch, x1, y1); - saveImage("new_patch", new_patch, sx2, sy2); + saveImage("new_patch", new_patch, *x2, *y2); } return result; @@ -329,6 +353,103 @@ void libmv_regionTrackerDestroy(libmv_RegionTracker *libmv_tracker) delete region_tracker; } +/* ************ Planar tracker ************ */ + +/* TrackRegion (new planar tracker) */ +int libmv_trackRegion(const struct libmv_trackRegionOptions *options, + const float *image1, const float *image2, + int width, int height, + const double *x1, const double *y1, + struct libmv_trackRegionResult *result, + double *x2, double *y2) +{ + double xx1[5], yy1[5]; + double xx2[5], yy2[5]; + bool tracking_result = false; + + /* Convert to doubles for the libmv api. The four corners and the center. */ + for (int i = 0; i < 5; ++i) { + xx1[i] = x1[i]; + yy1[i] = y1[i]; + xx2[i] = x2[i]; + yy2[i] = y2[i]; + } + + libmv::TrackRegionOptions track_region_options; + switch (options->motion_model) { +#define LIBMV_CONVERT(the_model) \ + case libmv::TrackRegionOptions::the_model: \ + track_region_options.mode = libmv::TrackRegionOptions::the_model; \ + break; + LIBMV_CONVERT(TRANSLATION) + LIBMV_CONVERT(TRANSLATION_ROTATION) + LIBMV_CONVERT(TRANSLATION_SCALE) + LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE) + LIBMV_CONVERT(AFFINE) + LIBMV_CONVERT(HOMOGRAPHY) +#undef LIBMV_CONVERT + } + + track_region_options.minimum_correlation = options->minimum_correlation; + track_region_options.max_iterations = options->num_iterations; + track_region_options.sigma = options->sigma; + track_region_options.num_extra_points = 1; + track_region_options.image1_mask = NULL; + track_region_options.use_brute_initialization = options->use_brute; + track_region_options.use_normalized_intensities = options->use_normalization; + + /* Convert from raw float buffers to libmv's FloatImage. */ + libmv::FloatImage old_patch, new_patch; + floatBufToImage(image1, width, height, 1, &old_patch); + floatBufToImage(image2, width, height, 1, &new_patch); + + libmv::TrackRegionResult track_region_result; + libmv::TrackRegion(old_patch, new_patch, xx1, yy1, track_region_options, xx2, yy2, &track_region_result); + + /* Convert to floats for the blender api. */ + for (int i = 0; i < 5; ++i) { + x2[i] = xx2[i]; + y2[i] = yy2[i]; + } + + /* TODO(keir): Update the termination string with failure details. */ + if (track_region_result.termination == libmv::TrackRegionResult::PARAMETER_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::FUNCTION_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::GRADIENT_TOLERANCE || + track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE) + { + tracking_result = true; + } + +#if defined(DUMP_FAILURE) || defined(DUMP_ALWAYS) +#if defined(DUMP_ALWAYS) + { +#else + if (!tracking_result) { +#endif + saveImage("old_patch", old_patch, x1[4], y1[4]); + saveImage("new_patch", new_patch, x2[4], y2[4]); + } +#endif + + return tracking_result; +} + +void libmv_samplePlanarPatch(const float *image, int width, int height, + int channels, const double *xs, const double *ys, + int num_samples_x, int num_samples_y, float *patch, + double *warped_position_x, double *warped_position_y) +{ + libmv::FloatImage libmv_image, libmv_patch; + + floatBufToImage(image, width, height, channels, &libmv_image); + + libmv::SamplePlanarPatch(libmv_image, xs, ys, num_samples_x, num_samples_y, + &libmv_patch, warped_position_x, warped_position_y); + + imageToFloatBuf(&libmv_patch, channels, patch); +} + /* ************ Tracks ************ */ libmv_Tracks *libmv_tracksNew(void) diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index bccc4706832..6f4b5dea384 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -50,6 +50,32 @@ int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const fl int width, int height, double x1, double y1, double *x2, double *y2); void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker); +/* TrackRegion (new planar tracker) */ +struct libmv_trackRegionOptions { + int motion_model; + int num_iterations; + int use_brute; + int use_normalization; + double minimum_correlation; + double sigma; +}; +struct libmv_trackRegionResult { + int termination; + const char *termination_reason; + double correlation; +}; +int libmv_trackRegion(const struct libmv_trackRegionOptions *options, + const float *image1, const float *image2, + int width, int height, + const double *x1, const double *y1, + struct libmv_trackRegionResult *result, + double *x2, double *y2); + +void libmv_samplePlanarPatch(const float *image, int width, int height, + int channels, const double *xs, const double *ys, + int num_samples_x, int num_samples_y, float *patch, + double *warped_position_x, double *warped_position_y); + /* Tracks */ struct libmv_Tracks *libmv_tracksNew(void); void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y); diff --git a/extern/libmv/libmv/image/sample.h b/extern/libmv/libmv/image/sample.h index e842747e6d4..a8850effeab 100644 --- a/extern/libmv/libmv/image/sample.h +++ b/extern/libmv/libmv/image/sample.h @@ -34,25 +34,22 @@ inline T SampleNearest(const Array3D &image, return image(i, j, v); } -static inline void LinearInitAxis(float fx, int width, - int *x1, int *x2, - float *dx1, float *dx2) { - const int ix = int(fx); +inline void LinearInitAxis(float x, int size, + int *x1, int *x2, + float *dx) { + const int ix = static_cast(x); if (ix < 0) { *x1 = 0; *x2 = 0; - *dx1 = 1; - *dx2 = 0; - } else if (ix > width-2) { - *x1 = width-1; - *x2 = width-1; - *dx1 = 1; - *dx2 = 0; + *dx = 1.0; + } else if (ix > size - 2) { + *x1 = size - 1; + *x2 = size - 1; + *dx = 1.0; } else { *x1 = ix; - *x2 = *x1 + 1; - *dx1 = *x2 - fx; - *dx2 = 1 - *dx1; + *x2 = ix + 1; + *dx = *x2 - x; } } @@ -60,18 +57,47 @@ static inline void LinearInitAxis(float fx, int width, template inline T SampleLinear(const Array3D &image, float y, float x, int v = 0) { int x1, y1, x2, y2; - float dx1, dy1, dx2, dy2; + float dx, dy; - LinearInitAxis(y, image.Height(), &y1, &y2, &dy1, &dy2); - LinearInitAxis(x, image.Width(), &x1, &x2, &dx1, &dx2); + // Take the upper left corner as integer pixel positions. + x -= 0.5; + y -= 0.5; + + LinearInitAxis(y, image.Height(), &y1, &y2, &dy); + LinearInitAxis(x, image.Width(), &x1, &x2, &dx); const T im11 = image(y1, x1, v); const T im12 = image(y1, x2, v); const T im21 = image(y2, x1, v); const T im22 = image(y2, x2, v); - return T(dy1 * ( dx1 * im11 + dx2 * im12 ) + - dy2 * ( dx1 * im21 + dx2 * im22 )); + return T( dy * ( dx * im11 + (1.0 - dx) * im12 ) + + (1 - dy) * ( dx * im21 + (1.0 - dx) * im22 )); +} + +/// Linear interpolation, of all channels. The sample is assumed to have the +/// same size as the number of channels in image. +template +inline void SampleLinear(const Array3D &image, float y, float x, T *sample) { + int x1, y1, x2, y2; + float dx, dy; + + // Take the upper left corner as integer pixel positions. + x -= 0.5; + y -= 0.5; + + LinearInitAxis(y, image.Height(), &y1, &y2, &dy); + LinearInitAxis(x, image.Width(), &x1, &x2, &dx); + + for (int i = 0; i < image.Depth(); ++i) { + const T im11 = image(y1, x1, i); + const T im12 = image(y1, x2, i); + const T im21 = image(y2, x1, i); + const T im22 = image(y2, x2, i); + + sample[i] = T( dy * ( dx * im11 + (1.0 - dx) * im12 ) + + (1 - dy) * ( dx * im21 + (1.0 - dx) * im22 )); + } } // Downsample all channels by 2. If the image has odd width or height, the last diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc new file mode 100644 index 00000000000..366392f3923 --- /dev/null +++ b/extern/libmv/libmv/multiview/homography.cc @@ -0,0 +1,267 @@ +// Copyright (c) 2008, 2009 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "libmv/logging/logging.h" +#include "libmv/multiview/homography.h" +#include "libmv/multiview/homography_parameterization.h" + +namespace libmv { +/** 2D Homography transformation estimation in the case that points are in + * euclidean coordinates. + * + * x = H y + * x and y vector must have the same direction, we could write + * crossproduct(|x|, * H * |y| ) = |0| + * + * | 0 -1 x2| |a b c| |y1| |0| + * | 1 0 -x1| * |d e f| * |y2| = |0| + * |-x2 x1 0| |g h 1| |1 | |0| + * + * That gives : + * + * (-d+x2*g)*y1 + (-e+x2*h)*y2 + -f+x2 |0| + * (a-x1*g)*y1 + (b-x1*h)*y2 + c-x1 = |0| + * (-x2*a+x1*d)*y1 + (-x2*b+x1*e)*y2 + -x2*c+x1*f |0| + */ +bool Homography2DFromCorrespondencesLinearEuc( + const Mat &x1, + const Mat &x2, + Mat3 *H, + double expected_precision) { + assert(2 == x1.rows()); + assert(4 <= x1.cols()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + + int n = x1.cols(); + MatX8 L = Mat::Zero(n * 3, 8); + Mat b = Mat::Zero(n * 3, 1); + for (int i = 0; i < n; ++i) { + int j = 3 * i; + L(j, 0) = x1(0, i); // a + L(j, 1) = x1(1, i); // b + L(j, 2) = 1.0; // c + L(j, 6) = -x2(0, i) * x1(0, i); // g + L(j, 7) = -x2(0, i) * x1(1, i); // h + b(j, 0) = x2(0, i); // i + + ++j; + L(j, 3) = x1(0, i); // d + L(j, 4) = x1(1, i); // e + L(j, 5) = 1.0; // f + L(j, 6) = -x2(1, i) * x1(0, i); // g + L(j, 7) = -x2(1, i) * x1(1, i); // h + b(j, 0) = x2(1, i); // i + + // This ensures better stability + // TODO(julien) make a lite version without this 3rd set + ++j; + L(j, 0) = x2(1, i) * x1(0, i); // a + L(j, 1) = x2(1, i) * x1(1, i); // b + L(j, 2) = x2(1, i); // c + L(j, 3) = -x2(0, i) * x1(0, i); // d + L(j, 4) = -x2(0, i) * x1(1, i); // e + L(j, 5) = -x2(0, i) ; // f + } + // Solve Lx=B + Vec h = L.fullPivLu().solve(b); + Homography2DNormalizedParameterization::To(h, H); + if ((L * h).isApprox(b, expected_precision)) { + return true; + } else { + return false; + } +} + +/** 2D Homography transformation estimation in the case that points are in + * homogeneous coordinates. + * + * | 0 -x3 x2| |a b c| |y1| -x3*d+x2*g -x3*e+x2*h -x3*f+x2*1 |y1| (-x3*d+x2*g)*y1 (-x3*e+x2*h)*y2 (-x3*f+x2*1)*y3 |0| + * | x3 0 -x1| * |d e f| * |y2| = x3*a-x1*g x3*b-x1*h x3*c-x1*1 * |y2| = (x3*a-x1*g)*y1 (x3*b-x1*h)*y2 (x3*c-x1*1)*y3 = |0| + * |-x2 x1 0| |g h 1| |y3| -x2*a+x1*d -x2*b+x1*e -x2*c+x1*f |y3| (-x2*a+x1*d)*y1 (-x2*b+x1*e)*y2 (-x2*c+x1*f)*y3 |0| + * X = |a b c d e f g h|^t + */ +bool Homography2DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat3 *H, + double expected_precision) { + if (x1.rows() == 2) { + return Homography2DFromCorrespondencesLinearEuc(x1, x2, H, + expected_precision); + } + assert(3 == x1.rows()); + assert(4 <= x1.cols()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + + const int x = 0; + const int y = 1; + const int w = 2; + int n = x1.cols(); + MatX8 L = Mat::Zero(n * 3, 8); + Mat b = Mat::Zero(n * 3, 1); + for (int i = 0; i < n; ++i) { + int j = 3 * i; + L(j, 0) = x2(w, i) * x1(x, i);//a + L(j, 1) = x2(w, i) * x1(y, i);//b + L(j, 2) = x2(w, i) * x1(w, i);//c + L(j, 6) = -x2(x, i) * x1(x, i);//g + L(j, 7) = -x2(x, i) * x1(y, i);//h + b(j, 0) = x2(x, i) * x1(w, i); + + ++j; + L(j, 3) = x2(w, i) * x1(x, i);//d + L(j, 4) = x2(w, i) * x1(y, i);//e + L(j, 5) = x2(w, i) * x1(w, i);//f + L(j, 6) = -x2(y, i) * x1(x, i);//g + L(j, 7) = -x2(y, i) * x1(y, i);//h + b(j, 0) = x2(y, i) * x1(w, i); + + // This ensures better stability + ++j; + L(j, 0) = x2(y, i) * x1(x, i);//a + L(j, 1) = x2(y, i) * x1(y, i);//b + L(j, 2) = x2(y, i) * x1(w, i);//c + L(j, 3) = -x2(x, i) * x1(x, i);//d + L(j, 4) = -x2(x, i) * x1(y, i);//e + L(j, 5) = -x2(x, i) * x1(w, i);//f + } + // Solve Lx=B + Vec h = L.fullPivLu().solve(b); + if ((L * h).isApprox(b, expected_precision)) { + Homography2DNormalizedParameterization::To(h, H); + return true; + } else { + return false; + } +} +/** + * x2 ~ A * x1 + * x2^t * Hi * A *x1 = 0 + * H1 = H2 = H3 = + * | 0 0 0 1| |-x2w| |0 0 0 0| | 0 | | 0 0 1 0| |-x2z| + * | 0 0 0 0| -> | 0 | |0 0 1 0| -> |-x2z| | 0 0 0 0| -> | 0 | + * | 0 0 0 0| | 0 | |0-1 0 0| | x2y| |-1 0 0 0| | x2x| + * |-1 0 0 0| | x2x| |0 0 0 0| | 0 | | 0 0 0 0| | 0 | + * H4 = H5 = H6 = + * |0 0 0 0| | 0 | | 0 1 0 0| |-x2y| |0 0 0 0| | 0 | + * |0 0 0 1| -> |-x2w| |-1 0 0 0| -> | x2x| |0 0 0 0| -> | 0 | + * |0 0 0 0| | 0 | | 0 0 0 0| | 0 | |0 0 0 1| |-x2w| + * |0-1 0 0| | x2y| | 0 0 0 0| | 0 | |0 0-1 0| | x2z| + * |a b c d| + * A = |e f g h| + * |i j k l| + * |m n o 1| + * + * x2^t * H1 * A *x1 = (-x2w*a +x2x*m )*x1x + (-x2w*b +x2x*n )*x1y + (-x2w*c +x2x*o )*x1z + (-x2w*d +x2x*1 )*x1w = 0 + * x2^t * H2 * A *x1 = (-x2z*e +x2y*i )*x1x + (-x2z*f +x2y*j )*x1y + (-x2z*g +x2y*k )*x1z + (-x2z*h +x2y*l )*x1w = 0 + * x2^t * H3 * A *x1 = (-x2z*a +x2x*i )*x1x + (-x2z*b +x2x*j )*x1y + (-x2z*c +x2x*k )*x1z + (-x2z*d +x2x*l )*x1w = 0 + * x2^t * H4 * A *x1 = (-x2w*e +x2y*m )*x1x + (-x2w*f +x2y*n )*x1y + (-x2w*g +x2y*o )*x1z + (-x2w*h +x2y*1 )*x1w = 0 + * x2^t * H5 * A *x1 = (-x2y*a +x2x*e )*x1x + (-x2y*b +x2x*f )*x1y + (-x2y*c +x2x*g )*x1z + (-x2y*d +x2x*h )*x1w = 0 + * x2^t * H6 * A *x1 = (-x2w*i +x2z*m )*x1x + (-x2w*j +x2z*n )*x1y + (-x2w*k +x2z*o )*x1z + (-x2w*l +x2z*1 )*x1w = 0 + * + * X = |a b c d e f g h i j k l m n o|^t +*/ +bool Homography3DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat4 *H, + double expected_precision) { + assert(4 == x1.rows()); + assert(5 <= x1.cols()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + const int x = 0; + const int y = 1; + const int z = 2; + const int w = 3; + int n = x1.cols(); + MatX15 L = Mat::Zero(n * 6, 15); + Mat b = Mat::Zero(n * 6, 1); + for (int i = 0; i < n; ++i) { + int j = 6 * i; + L(j, 0) = -x2(w, i) * x1(x, i);//a + L(j, 1) = -x2(w, i) * x1(y, i);//b + L(j, 2) = -x2(w, i) * x1(z, i);//c + L(j, 3) = -x2(w, i) * x1(w, i);//d + L(j,12) = x2(x, i) * x1(x, i);//m + L(j,13) = x2(x, i) * x1(y, i);//n + L(j,14) = x2(x, i) * x1(z, i);//o + b(j, 0) = -x2(x, i) * x1(w, i); + + ++j; + L(j, 4) = -x2(z, i) * x1(x, i);//e + L(j, 5) = -x2(z, i) * x1(y, i);//f + L(j, 6) = -x2(z, i) * x1(z, i);//g + L(j, 7) = -x2(z, i) * x1(w, i);//h + L(j, 8) = x2(y, i) * x1(x, i);//i + L(j, 9) = x2(y, i) * x1(y, i);//j + L(j,10) = x2(y, i) * x1(z, i);//k + L(j,11) = x2(y, i) * x1(w, i);//l + + ++j; + L(j, 0) = -x2(z, i) * x1(x, i);//a + L(j, 1) = -x2(z, i) * x1(y, i);//b + L(j, 2) = -x2(z, i) * x1(z, i);//c + L(j, 3) = -x2(z, i) * x1(w, i);//d + L(j, 8) = x2(x, i) * x1(x, i);//i + L(j, 9) = x2(x, i) * x1(y, i);//j + L(j,10) = x2(x, i) * x1(z, i);//k + L(j,11) = x2(x, i) * x1(w, i);//l + + ++j; + L(j, 4) = -x2(w, i) * x1(x, i);//e + L(j, 5) = -x2(w, i) * x1(y, i);//f + L(j, 6) = -x2(w, i) * x1(z, i);//g + L(j, 7) = -x2(w, i) * x1(w, i);//h + L(j,12) = x2(y, i) * x1(x, i);//m + L(j,13) = x2(y, i) * x1(y, i);//n + L(j,14) = x2(y, i) * x1(z, i);//o + b(j, 0) = -x2(y, i) * x1(w, i); + + ++j; + L(j, 0) = -x2(y, i) * x1(x, i);//a + L(j, 1) = -x2(y, i) * x1(y, i);//b + L(j, 2) = -x2(y, i) * x1(z, i);//c + L(j, 3) = -x2(y, i) * x1(w, i);//d + L(j, 4) = x2(x, i) * x1(x, i);//e + L(j, 5) = x2(x, i) * x1(y, i);//f + L(j, 6) = x2(x, i) * x1(z, i);//g + L(j, 7) = x2(x, i) * x1(w, i);//h + + ++j; + L(j, 8) = -x2(w, i) * x1(x, i);//i + L(j, 9) = -x2(w, i) * x1(y, i);//j + L(j,10) = -x2(w, i) * x1(z, i);//k + L(j,11) = -x2(w, i) * x1(w, i);//l + L(j,12) = x2(z, i) * x1(x, i);//m + L(j,13) = x2(z, i) * x1(y, i);//n + L(j,14) = x2(z, i) * x1(z, i);//o + b(j, 0) = -x2(z, i) * x1(w, i); + } + // Solve Lx=B + Vec h = L.fullPivLu().solve(b); + if ((L * h).isApprox(b, expected_precision)) { + Homography3DNormalizedParameterization::To(h, H); + return true; + } else { + return false; + } +} +} // namespace libmv diff --git a/extern/libmv/libmv/multiview/homography.h b/extern/libmv/libmv/multiview/homography.h new file mode 100644 index 00000000000..786fd3df8ca --- /dev/null +++ b/extern/libmv/libmv/multiview/homography.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_H_ +#define LIBMV_MULTIVIEW_HOMOGRAPHY_H_ + +#include "libmv/numeric/numeric.h" + +namespace libmv { + +/** + * 2D homography transformation estimation. + * + * This function estimates the homography transformation from a list of 2D + * correspondences which represents either: + * + * - 3D points on a plane, with a general moving camera. + * - 3D points with a rotating camera (pure rotation). + * - 3D points + different planar projections + * + * \param x1 The first 2xN or 3xN matrix of euclidean or homogeneous points. + * \param x2 The second 2xN or 3xN matrix of euclidean or homogeneous points. + * \param H The 3x3 homography transformation matrix (8 dof) such that + * x2 = H * x1 with |a b c| + * H = |d e f| + * |g h 1| + * \param expected_precision The expected precision in order for instance + * to accept almost homography matrices. + * + * \return True if the transformation estimation has succeeded. + * \note There must be at least 4 non-colinear points. + */ +bool Homography2DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat3 *H, + double expected_precision = + EigenDouble::dummy_precision()); + +/** + * 3D Homography transformation estimation. + * + * This function can be used in order to estimate the homography transformation + * from a list of 3D correspondences. + * + * \param[in] x1 The first 4xN matrix of homogeneous points + * \param[in] x2 The second 4xN matrix of homogeneous points + * \param[out] H The 4x4 homography transformation matrix (15 dof) such that + * x2 = H * x1 with |a b c d| + * H = |e f g h| + * |i j k l| + * |m n o 1| + * \param[in] expected_precision The expected precision in order for instance + * to accept almost homography matrices. + * + * \return true if the transformation estimation has succeeded + * + * \note Need at least 5 non coplanar points + * \note Points coordinates must be in homogeneous coordinates + */ +bool Homography3DFromCorrespondencesLinear(const Mat &x1, + const Mat &x2, + Mat4 *H, + double expected_precision = + EigenDouble::dummy_precision()); +} // namespace libmv + +#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_H_ diff --git a/extern/libmv/libmv/multiview/homography_parameterization.h b/extern/libmv/libmv/multiview/homography_parameterization.h new file mode 100644 index 00000000000..b31642eea15 --- /dev/null +++ b/extern/libmv/libmv/multiview/homography_parameterization.h @@ -0,0 +1,91 @@ +// Copyright (c) 2011 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_ +#define LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_ + +#include "libmv/numeric/numeric.h" + +namespace libmv { + +/** A parameterization of the 2D homography matrix that uses 8 parameters so + * that the matrix is normalized (H(2,2) == 1). + * The homography matrix H is built from a list of 8 parameters (a, b,...g, h) + * as follows + * |a b c| + * H = |d e f| + * |g h 1| + */ +template +class Homography2DNormalizedParameterization { + public: + typedef Eigen::Matrix Parameters; // a, b, ... g, h + typedef Eigen::Matrix Parameterized; // H + + /// Convert from the 8 parameters to a H matrix. + static void To(const Parameters &p, Parameterized *h) { + *h << p(0), p(1), p(2), + p(3), p(4), p(5), + p(6), p(7), 1.0; + } + + /// Convert from a H matrix to the 8 parameters. + static void From(const Parameterized &h, Parameters *p) { + *p << h(0, 0), h(0, 1), h(0, 2), + h(1, 0), h(1, 1), h(1, 2), + h(2, 0), h(2, 1); + } +}; + +/** A parameterization of the 2D homography matrix that uses 15 parameters so + * that the matrix is normalized (H(3,3) == 1). + * The homography matrix H is built from a list of 15 parameters (a, b,...n, o) + * as follows + * |a b c d| + * H = |e f g h| + * |i j k l| + * |m n o 1| + */ +template +class Homography3DNormalizedParameterization { + public: + typedef Eigen::Matrix Parameters; // a, b, ... n, o + typedef Eigen::Matrix Parameterized; // H + + /// Convert from the 15 parameters to a H matrix. + static void To(const Parameters &p, Parameterized *h) { + *h << p(0), p(1), p(2), p(3), + p(4), p(5), p(6), p(7), + p(8), p(9), p(10), p(11), + p(12), p(13), p(14), 1.0; + } + + /// Convert from a H matrix to the 15 parameters. + static void From(const Parameterized &h, Parameters *p) { + *p << h(0, 0), h(0, 1), h(0, 2), h(0, 3), + h(1, 0), h(1, 1), h(1, 2), h(1, 3), + h(2, 0), h(2, 1), h(2, 2), h(2, 3), + h(3, 0), h(3, 1), h(3, 2); + } +}; + +} // namespace libmv + +#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_ diff --git a/extern/libmv/libmv/tracking/esm_region_tracker.cc b/extern/libmv/libmv/tracking/esm_region_tracker.cc index 221fa4d081b..a8dc46d439b 100644 --- a/extern/libmv/libmv/tracking/esm_region_tracker.cc +++ b/extern/libmv/libmv/tracking/esm_region_tracker.cc @@ -29,6 +29,7 @@ #include "libmv/image/correlation.h" #include "libmv/image/sample.h" #include "libmv/numeric/numeric.h" +#include "libmv/tracking/track_region.h" namespace libmv { @@ -72,6 +73,44 @@ bool EsmRegionTracker::Track(const FloatImage &image1, return false; } + // XXX + // TODO(keir): Delete the block between the XXX's once the planar tracker is + // integrated into blender. + // + // For now, to test, replace the ESM tracker with the Ceres tracker in + // translation mode. In the future, this should get removed and alloed to + // co-exist, since Ceres is not as fast as the ESM implementation since it + // specializes for translation. + double xx1[4], yy1[4]; + double xx2[4], yy2[4]; + // Clockwise winding, starting from the "origin" (top-left). + xx1[0] = xx2[0] = x1 - half_window_size; + yy1[0] = yy2[0] = y1 - half_window_size; + + xx1[1] = xx2[1] = x1 + half_window_size; + yy1[1] = yy2[1] = y1 - half_window_size; + + xx1[2] = xx2[2] = x1 + half_window_size; + yy1[2] = yy2[2] = y1 + half_window_size; + + xx1[3] = xx2[3] = x1 - half_window_size; + yy1[3] = yy2[3] = y1 + half_window_size; + + TrackRegionOptions options; + options.mode = TrackRegionOptions::TRANSLATION; + options.max_iterations = 20; + options.sigma = sigma; + options.use_esm = true; + + TrackRegionResult result; + TrackRegion(image1, image2, xx1, yy1, options, xx2, yy2, &result); + + *x2 = xx2[0] + half_window_size; + *y2 = yy2[0] + half_window_size; + + return true; + + // XXX int width = 2 * half_window_size + 1; // TODO(keir): Avoid recomputing gradients for e.g. the pyramid tracker. diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc new file mode 100644 index 00000000000..e65ead50c80 --- /dev/null +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -0,0 +1,1391 @@ +// Copyright (c) 2012 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// +// Author: mierle@google.com (Keir Mierle) +// +// TODO(keir): While this tracking code works rather well, it has some +// outragous inefficiencies. There is probably a 5-10x speedup to be had if a +// smart coder went through the TODO's and made the suggested performance +// enhancements. + +// Necessary for M_E when building with MSVC. +#define _USE_MATH_DEFINES + +#include "libmv/tracking/track_region.h" + +#include +#include +#include +#include "ceres/ceres.h" +#include "libmv/logging/logging.h" +#include "libmv/image/image.h" +#include "libmv/image/sample.h" +#include "libmv/image/convolve.h" +#include "libmv/multiview/homography.h" +#include "libmv/numeric/numeric.h" + +namespace libmv { + +using ceres::Jet; +using ceres::JetOps; +using ceres::Chain; + +TrackRegionOptions::TrackRegionOptions() + : mode(TRANSLATION), + minimum_correlation(0), + max_iterations(20), + use_esm(true), + use_brute_initialization(true), + use_normalized_intensities(false), + sigma(0.9), + num_extra_points(0), + regularization_coefficient(0.0), + image1_mask(NULL) { +} + +namespace { + +// TODO(keir): Consider adding padding. +template +bool InBounds(const FloatImage &image, + const T &x, + const T &y) { + return 0.0 <= x && x < image.Width() && + 0.0 <= y && y < image.Height(); +} + +bool AllInBounds(const FloatImage &image, + const double *x, + const double *y) { + for (int i = 0; i < 4; ++i) { + if (!InBounds(image, x[i], y[i])) { + return false; + } + } + return true; +} + +// Sample the image at position (x, y) but use the gradient, if present, to +// propagate derivatives from x and y. This is needed to integrate the numeric +// image gradients with Ceres's autodiff framework. +template +static T SampleWithDerivative(const FloatImage &image_and_gradient, + const T &x, + const T &y) { + float scalar_x = JetOps::GetScalar(x); + float scalar_y = JetOps::GetScalar(y); + + // Note that sample[1] and sample[2] will be uninitialized in the scalar + // case, but that is not an issue because the Chain::Rule below will not read + // the uninitialized values. + float sample[3]; + if (JetOps::IsScalar()) { + // For the scalar case, only sample the image. + sample[0] = SampleLinear(image_and_gradient, scalar_y, scalar_x, 0); + } else { + // For the derivative case, sample the gradient as well. + SampleLinear(image_and_gradient, scalar_y, scalar_x, sample); + } + T xy[2] = { x, y }; + return Chain::Rule(sample[0], sample + 1, xy); +} + +template +class BoundaryCheckingCallback : public ceres::IterationCallback { + public: + BoundaryCheckingCallback(const FloatImage& image2, + const Warp &warp, + const double *x1, const double *y1) + : image2_(image2), warp_(warp), x1_(x1), y1_(y1) {} + + virtual ceres::CallbackReturnType operator()( + const ceres::IterationSummary& summary) { + // Warp the original 4 points with the current warp into image2. + double x2[4]; + double y2[4]; + for (int i = 0; i < 4; ++i) { + warp_.Forward(warp_.parameters, x1_[i], y1_[i], x2 + i, y2 + i); + } + // Enusre they are all in bounds. + if (!AllInBounds(image2_, x2, y2)) { + return ceres::SOLVER_ABORT; + } + return ceres::SOLVER_CONTINUE; + } + + private: + const FloatImage &image2_; + const Warp &warp_; + const double *x1_; + const double *y1_; +}; + +template +class PixelDifferenceCostFunctor { + public: + PixelDifferenceCostFunctor(const TrackRegionOptions &options, + const FloatImage &image_and_gradient1, + const FloatImage &image_and_gradient2, + const Mat3 &canonical_to_image1, + int num_samples_x, + int num_samples_y, + const Warp &warp) + : options_(options), + image_and_gradient1_(image_and_gradient1), + image_and_gradient2_(image_and_gradient2), + canonical_to_image1_(canonical_to_image1), + num_samples_x_(num_samples_x), + num_samples_y_(num_samples_y), + warp_(warp), + pattern_and_gradient_(num_samples_y_, num_samples_x_, 3), + pattern_positions_(num_samples_y_, num_samples_x_, 2), + pattern_mask_(num_samples_y_, num_samples_x_, 1) { + ComputeCanonicalPatchAndNormalizer(); + } + + void ComputeCanonicalPatchAndNormalizer() { + src_mean_ = 0.0; + double num_samples = 0.0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Compute the position; cache it. + Vec3 image_position = canonical_to_image1_ * Vec3(c, r, 1); + image_position /= image_position(2); + pattern_positions_(r, c, 0) = image_position(0); + pattern_positions_(r, c, 1) = image_position(1); + + // Sample the pattern and gradients. + SampleLinear(image_and_gradient1_, + image_position(1), // SampleLinear is r, c. + image_position(0), + &pattern_and_gradient_(r, c, 0)); + + // Sample sample the mask. + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + SampleLinear(*options_.image1_mask, + image_position(1), // SampleLinear is r, c. + image_position(0), + &pattern_mask_(r, c, 0)); + mask_value = pattern_mask_(r, c); + } + src_mean_ += pattern_and_gradient_(r, c, 0) * mask_value; + num_samples += mask_value; + } + } + src_mean_ /= num_samples; + } + + template + bool operator()(const T *warp_parameters, T *residuals) const { + if (options_.image1_mask != NULL) { + VLOG(2) << "Using a mask."; + } + for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { + VLOG(2) << "warp_parameters[" << i << "]: " << warp_parameters[i]; + } + + T dst_mean = T(1.0); + if (options_.use_normalized_intensities) { + ComputeNormalizingCoefficient(warp_parameters, + &dst_mean); + } + + int cursor = 0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Use the pre-computed image1 position. + Vec2 image1_position(pattern_positions_(r, c, 0), + pattern_positions_(r, c, 1)); + + // Sample the mask early; if it's zero, this pixel has no effect. This + // allows early bailout from the expensive sampling that happens below. + // + // Note that partial masks are not short circuited. To see why short + // circuiting produces bitwise-exact same results, consider that the + // residual for each pixel is + // + // residual = mask * (src - dst) , + // + // and for jets, multiplying by a scalar multiplies the derivative + // components by the scalar as well. Therefore, if the mask is exactly + // zero, then so too will the final residual and derivatives. + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + mask_value = pattern_mask_(r, c); + if (mask_value == 0.0) { + residuals[cursor++] = T(0.0); + continue; + } + } + + // Compute the location of the destination pixel. + T image2_position[2]; + warp_.Forward(warp_parameters, + T(image1_position[0]), + T(image1_position[1]), + &image2_position[0], + &image2_position[1]); + + // Sample the destination, propagating derivatives. + T dst_sample = SampleWithDerivative(image_and_gradient2_, + image2_position[0], + image2_position[1]); + + // Sample the source. This is made complicated by ESM mode. + T src_sample; + if (options_.use_esm && !JetOps::IsScalar()) { + // In ESM mode, the derivative of the source is also taken into + // account. This changes the linearization in a way that causes + // better convergence. Copy the derivative of the warp parameters + // onto the jets for the image1 position. This is the ESM hack. + T image1_position_jet[2] = { + image2_position[0], // Order is x, y. This matches the + image2_position[1] // derivative order in the patch. + }; + JetOps::SetScalar(image1_position[0], image1_position_jet + 0); + JetOps::SetScalar(image1_position[1], image1_position_jet + 1); + + // Now that the image1 positions have the jets applied from the + // image2 position (the ESM hack), chain the image gradients to + // obtain a sample with the derivative with respect to the warp + // parameters attached. + src_sample = Chain::Rule(pattern_and_gradient_(r, c), + &pattern_and_gradient_(r, c, 1), + image1_position_jet); + + // The jacobians for these should be averaged. Due to the subtraction + // below, flip the sign of the src derivative so that the effect + // after subtraction of the jets is that they are averaged. + JetOps::ScaleDerivative(-0.5, &src_sample); + JetOps::ScaleDerivative(0.5, &dst_sample); + } else { + // This is the traditional, forward-mode KLT solution. + src_sample = T(pattern_and_gradient_(r, c)); + } + + // Normalize the samples by the mean values of each signal. The typical + // light model assumes multiplicative intensity changes with changing + // light, so this is a reasonable choice. Note that dst_mean has + // derivative information attached thanks to autodiff. + if (options_.use_normalized_intensities) { + src_sample /= T(src_mean_); + dst_sample /= dst_mean; + } + + // The difference is the error. + T error = src_sample - dst_sample; + + // Weight the error by the mask, if one is present. + if (options_.image1_mask != NULL) { + error *= T(mask_value); + } + residuals[cursor++] = error; + } + } + return true; + } + + // For normalized matching, the average and + template + void ComputeNormalizingCoefficient(const T *warp_parameters, + T *dst_mean) const { + + *dst_mean = T(0.0); + double num_samples = 0.0; + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Use the pre-computed image1 position. + Vec2 image1_position(pattern_positions_(r, c, 0), + pattern_positions_(r, c, 1)); + + // Sample the mask early; if it's zero, this pixel has no effect. This + // allows early bailout from the expensive sampling that happens below. + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + mask_value = pattern_mask_(r, c); + if (mask_value == 0.0) { + continue; + } + } + + // Compute the location of the destination pixel. + T image2_position[2]; + warp_.Forward(warp_parameters, + T(image1_position[0]), + T(image1_position[1]), + &image2_position[0], + &image2_position[1]); + + + // Sample the destination, propagating derivatives. + // TODO(keir): This accumulation can, surprisingly, be done as a + // pre-pass by using integral images. This is complicated by the need + // to store the jets in the integral image, but it is possible. + T dst_sample = SampleWithDerivative(image_and_gradient2_, + image2_position[0], + image2_position[1]); + + // Weight the sample by the mask, if one is present. + if (options_.image1_mask != NULL) { + dst_sample *= T(mask_value); + } + + *dst_mean += dst_sample; + num_samples += mask_value; + } + } + *dst_mean /= T(num_samples); + LG << "Normalization for dst:" << *dst_mean; + } + + // TODO(keir): Consider also computing the cost here. + double PearsonProductMomentCorrelationCoefficient( + const double *warp_parameters) const { + for (int i = 0; i < Warp::NUM_PARAMETERS; ++i) { + VLOG(2) << "Correlation warp_parameters[" << i << "]: " + << warp_parameters[i]; + } + + // The single-pass PMCC computation is somewhat numerically unstable, but + // it's sufficient for the tracker. + double sX = 0, sY = 0, sXX = 0, sYY = 0, sXY = 0; + + // Due to masking, it's important to account for fractional samples. + // For example, samples with a 50% mask are counted as a half sample. + double num_samples = 0; + + for (int r = 0; r < num_samples_y_; ++r) { + for (int c = 0; c < num_samples_x_; ++c) { + // Use the pre-computed image1 position. + Vec2 image1_position(pattern_positions_(r, c, 0), + pattern_positions_(r, c, 1)); + + double mask_value = 1.0; + if (options_.image1_mask != NULL) { + mask_value = pattern_mask_(r, c); + if (mask_value == 0.0) { + continue; + } + } + + // Compute the location of the destination pixel. + double image2_position[2]; + warp_.Forward(warp_parameters, + image1_position[0], + image1_position[1], + &image2_position[0], + &image2_position[1]); + + double x = pattern_and_gradient_(r, c); + double y = SampleLinear(image_and_gradient2_, + image2_position[1], // SampleLinear is r, c. + image2_position[0]); + + // Weight the signals by the mask, if one is present. + if (options_.image1_mask != NULL) { + x *= mask_value; + y *= mask_value; + num_samples += mask_value; + } else { + num_samples++; + } + sX += x; + sY += y; + sXX += x*x; + sYY += y*y; + sXY += x*y; + } + } + // Normalize. + sX /= num_samples; + sY /= num_samples; + sXX /= num_samples; + sYY /= num_samples; + sXY /= num_samples; + + double var_x = sXX - sX*sX; + double var_y = sYY - sY*sY; + double covariance_xy = sXY - sX*sY; + + double correlation = covariance_xy / sqrt(var_x * var_y); + LG << "Covariance xy: " << covariance_xy + << ", var 1: " << var_x << ", var 2: " << var_y + << ", correlation: " << correlation; + return correlation; + } + + private: + const TrackRegionOptions &options_; + const FloatImage &image_and_gradient1_; + const FloatImage &image_and_gradient2_; + const Mat3 &canonical_to_image1_; + int num_samples_x_; + int num_samples_y_; + const Warp &warp_; + double src_mean_; + FloatImage pattern_and_gradient_; + + // This contains the position from where the cached pattern samples were + // taken from. This is also used to warp from src to dest without going from + // canonical pixels to src first. + FloatImage pattern_positions_; + + FloatImage pattern_mask_; +}; + +template +class WarpRegularizingCostFunctor { + public: + WarpRegularizingCostFunctor(const TrackRegionOptions &options, + const double *x1, + const double *y1, + const double *x2_original, + const double *y2_original, + const Warp &warp) + : options_(options), + x1_(x1), + y1_(y1), + x2_original_(x2_original), + y2_original_(y2_original), + warp_(warp) { + // Compute the centroid of the first guess quad. + // TODO(keir): Use Quad class here. + original_centroid_[0] = 0.0; + original_centroid_[1] = 0.0; + for (int i = 0; i < 4; ++i) { + original_centroid_[0] += x2_original[i]; + original_centroid_[1] += y2_original[i]; + } + original_centroid_[0] /= 4; + original_centroid_[1] /= 4; + } + + template + bool operator()(const T *warp_parameters, T *residuals) const { + T dst_centroid[2] = { T(0.0), T(0.0) }; + for (int i = 0; i < 4; ++i) { + T image1_position[2] = { T(x1_[i]), T(y1_[i]) }; + T image2_position[2]; + warp_.Forward(warp_parameters, + T(x1_[i]), + T(y1_[i]), + &image2_position[0], + &image2_position[1]); + + // Subtract the positions. Note that this ignores the centroids. + residuals[2 * i + 0] = image2_position[0] - image1_position[0]; + residuals[2 * i + 1] = image2_position[1] - image1_position[1]; + + // Accumulate the dst centroid. + dst_centroid[0] += image2_position[0]; + dst_centroid[1] += image2_position[1]; + } + dst_centroid[0] /= T(4.0); + dst_centroid[1] /= T(4.0); + + // Adjust for the centroids. + for (int i = 0; i < 4; ++i) { + residuals[2 * i + 0] += T(original_centroid_[0]) - dst_centroid[0]; + residuals[2 * i + 1] += T(original_centroid_[1]) - dst_centroid[1]; + } + + // Reweight the residuals. + for (int i = 0; i < 8; ++i) { + residuals[i] *= T(options_.regularization_coefficient); + } + + return true; + } + + const TrackRegionOptions &options_; + const double *x1_; + const double *y1_; + const double *x2_original_; + const double *y2_original_; + double original_centroid_[2]; + const Warp &warp_; +}; + +// Compute the warp from rectangular coordinates, where one corner is the +// origin, and the opposite corner is at (num_samples_x, num_samples_y). +Mat3 ComputeCanonicalHomography(const double *x1, + const double *y1, + int num_samples_x, + int num_samples_y) { + Mat canonical(2, 4); + canonical << 0, num_samples_x, num_samples_x, 0, + 0, 0, num_samples_y, num_samples_y; + + Mat xy1(2, 4); + xy1 << x1[0], x1[1], x1[2], x1[3], + y1[0], y1[1], y1[2], y1[3]; + + Mat3 H; + if (!Homography2DFromCorrespondencesLinear(canonical, xy1, &H, 1e-12)) { + LG << "Couldn't construct homography."; + } + return H; +} + +class Quad { + public: + Quad(const double *x, const double *y) : x_(x), y_(y) { + // Compute the centroid and store it. + centroid_ = Vec2(0.0, 0.0); + for (int i = 0; i < 4; ++i) { + centroid_ += Vec2(x_[i], y_[i]); + } + centroid_ /= 4.0; + } + + // The centroid of the four points representing the quad. + const Vec2& Centroid() const { + return centroid_; + } + + // The average magnitude of the four points relative to the centroid. + double Scale() const { + double scale = 0.0; + for (int i = 0; i < 4; ++i) { + scale += (Vec2(x_[i], y_[i]) - Centroid()).norm(); + } + return scale / 4.0; + } + + Vec2 CornerRelativeToCentroid(int i) const { + return Vec2(x_[i], y_[i]) - centroid_; + } + + private: + const double *x_; + const double *y_; + Vec2 centroid_; +}; + +struct TranslationWarp { + TranslationWarp(const double *x1, const double *y1, + const double *x2, const double *y2) { + Vec2 t = Quad(x2, y2).Centroid() - Quad(x1, y1).Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + } + + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + *x2 = x1 + warp_parameters[0]; + *y2 = y1 + warp_parameters[1]; + } + + // Translation x, translation y. + enum { NUM_PARAMETERS = 2 }; + double parameters[NUM_PARAMETERS]; +}; + +struct TranslationScaleWarp { + TranslationScaleWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q2.Centroid() - q1.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // The difference in scales is the estimate for the scale. + parameters[2] = 1.0 - q2.Scale() / q1.Scale(); + } + + // The strange way of parameterizing the translation and scaling is to make + // the knobs that the optimizer sees easy to adjust. This is less important + // for the scaling case than the rotation case. + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Scale uniformly about the origin. + const T scale = 1.0 + warp_parameters[2]; + const T x1_origin_scaled = scale * x1_origin; + const T y1_origin_scaled = scale * y1_origin; + + // Translate back into the space of Q1 (but scaled). + const T x1_scaled = x1_origin_scaled + q1.Centroid()(0); + const T y1_scaled = y1_origin_scaled + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_scaled + warp_parameters[0]; + *y2 = y1_scaled + warp_parameters[1]; + } + + // Translation x, translation y, scale. + enum { NUM_PARAMETERS = 3 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +// Assumes the given points are already zero-centroid and the same size. +Mat2 OrthogonalProcrustes(const Mat2 &correlation_matrix) { + Eigen::JacobiSVD svd(correlation_matrix, + Eigen::ComputeFullU | Eigen::ComputeFullV); + return svd.matrixV() * svd.matrixU().transpose(); +} + +struct TranslationRotationWarp { + TranslationRotationWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q2.Centroid() - q1.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // Obtain the rotation via orthorgonal procrustes. + Mat2 correlation_matrix; + for (int i = 0; i < 4; ++i) { + correlation_matrix += q1.CornerRelativeToCentroid(i) * + q2.CornerRelativeToCentroid(i).transpose(); + } + Mat2 R = OrthogonalProcrustes(correlation_matrix); + parameters[2] = atan2(R(1, 0), R(0, 0)); + + LG << "Correlation_matrix:\n" << correlation_matrix; + LG << "R:\n" << R; + LG << "Theta:" << parameters[2]; + } + + // The strange way of parameterizing the translation and rotation is to make + // the knobs that the optimizer sees easy to adjust. The reason is that while + // it is always the case that it is possible to express composed rotations + // and translations as a single translation and rotation, the numerical + // values needed for the composition are often large in magnitude. This is + // enough to throw off any minimizer, since it must do the equivalent of + // compose rotations and translations. + // + // Instead, use the parameterization below that offers a parameterization + // that exposes the degrees of freedom in a way amenable to optimization. + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Rotate about the origin (i.e. centroid of Q1). + const T theta = warp_parameters[2]; + const T costheta = cos(theta); + const T sintheta = sin(theta); + const T x1_origin_rotated = costheta * x1_origin - sintheta * y1_origin; + const T y1_origin_rotated = sintheta * x1_origin + costheta * y1_origin; + + // Translate back into the space of Q1 (but scaled). + const T x1_rotated = x1_origin_rotated + q1.Centroid()(0); + const T y1_rotated = y1_origin_rotated + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_rotated + warp_parameters[0]; + *y2 = y1_rotated + warp_parameters[1]; + } + + // Translation x, translation y, rotation about the center of Q1 degrees. + enum { NUM_PARAMETERS = 3 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +struct TranslationRotationScaleWarp { + TranslationRotationScaleWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q2.Centroid() - q1.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // The difference in scales is the estimate for the scale. + parameters[2] = 1.0 - q2.Scale() / q1.Scale(); + + // Obtain the rotation via orthorgonal procrustes. + Mat2 correlation_matrix; + for (int i = 0; i < 4; ++i) { + correlation_matrix += q1.CornerRelativeToCentroid(i) * + q2.CornerRelativeToCentroid(i).transpose(); + } + Mat2 R = OrthogonalProcrustes(correlation_matrix); + parameters[3] = atan2(R(1, 0), R(0, 0)); + + LG << "Correlation_matrix:\n" << correlation_matrix; + LG << "R:\n" << R; + LG << "Theta:" << parameters[3]; + } + + // The strange way of parameterizing the translation and rotation is to make + // the knobs that the optimizer sees easy to adjust. The reason is that while + // it is always the case that it is possible to express composed rotations + // and translations as a single translation and rotation, the numerical + // values needed for the composition are often large in magnitude. This is + // enough to throw off any minimizer, since it must do the equivalent of + // compose rotations and translations. + // + // Instead, use the parameterization below that offers a parameterization + // that exposes the degrees of freedom in a way amenable to optimization. + template + void Forward(const T *warp_parameters, + const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Rotate about the origin (i.e. centroid of Q1). + const T theta = warp_parameters[3]; + const T costheta = cos(theta); + const T sintheta = sin(theta); + const T x1_origin_rotated = costheta * x1_origin - sintheta * y1_origin; + const T y1_origin_rotated = sintheta * x1_origin + costheta * y1_origin; + + // Scale uniformly about the origin. + const T scale = 1.0 + warp_parameters[2]; + const T x1_origin_rotated_scaled = scale * x1_origin_rotated; + const T y1_origin_rotated_scaled = scale * y1_origin_rotated; + + // Translate back into the space of Q1 (but scaled and rotated). + const T x1_rotated_scaled = x1_origin_rotated_scaled + q1.Centroid()(0); + const T y1_rotated_scaled = y1_origin_rotated_scaled + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_rotated_scaled + warp_parameters[0]; + *y2 = y1_rotated_scaled + warp_parameters[1]; + } + + // Translation x, translation y, rotation about the center of Q1 degrees, + // scale. + enum { NUM_PARAMETERS = 4 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +struct AffineWarp { + AffineWarp(const double *x1, const double *y1, + const double *x2, const double *y2) + : q1(x1, y1) { + Quad q2(x2, y2); + + // The difference in centroids is the best guess for translation. + Vec2 t = q2.Centroid() - q1.Centroid(); + parameters[0] = t[0]; + parameters[1] = t[1]; + + // Estimate the four affine parameters with the usual least squares. + Mat Q1(8, 4); + Vec Q2(8); + for (int i = 0; i < 4; ++i) { + Vec2 v1 = q1.CornerRelativeToCentroid(i); + Vec2 v2 = q2.CornerRelativeToCentroid(i); + + Q1.row(2 * i + 0) << v1[0], v1[1], 0, 0 ; + Q1.row(2 * i + 1) << 0, 0, v1[0], v1[1]; + + Q2(2 * i + 0) = v2[0]; + Q2(2 * i + 1) = v2[1]; + } + + // TODO(keir): Check solution quality. + Vec4 a = Q1.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Q2); + parameters[2] = a[0]; + parameters[3] = a[1]; + parameters[4] = a[2]; + parameters[5] = a[3]; + + LG << "a:" << a.transpose(); + LG << "t:" << t.transpose(); + } + + // See comments in other parameterizations about why the centroid is used. + template + void Forward(const T *p, const T &x1, const T& y1, T *x2, T* y2) const { + // Make the centroid of Q1 the origin. + const T x1_origin = x1 - q1.Centroid()(0); + const T y1_origin = y1 - q1.Centroid()(1); + + // Apply the affine transformation. + const T x1_origin_affine = p[2] * x1_origin + p[3] * y1_origin; + const T y1_origin_affine = p[4] * x1_origin + p[5] * y1_origin; + + // Translate back into the space of Q1 (but affine transformed). + const T x1_affine = x1_origin_affine + q1.Centroid()(0); + const T y1_affine = y1_origin_affine + q1.Centroid()(1); + + // Translate into the space of Q2. + *x2 = x1_affine + p[0]; + *y2 = y1_affine + p[1]; + } + + // Translation x, translation y, rotation about the center of Q1 degrees, + // scale. + enum { NUM_PARAMETERS = 6 }; + double parameters[NUM_PARAMETERS]; + + Quad q1; +}; + +struct HomographyWarp { + HomographyWarp(const double *x1, const double *y1, + const double *x2, const double *y2) { + Mat quad1(2, 4); + quad1 << x1[0], x1[1], x1[2], x1[3], + y1[0], y1[1], y1[2], y1[3]; + + Mat quad2(2, 4); + quad2 << x2[0], x2[1], x2[2], x2[3], + y2[0], y2[1], y2[2], y2[3]; + + Mat3 H; + if (!Homography2DFromCorrespondencesLinear(quad1, quad2, &H, 1e-12)) { + LG << "Couldn't construct homography."; + } + + // Assume H(2, 2) != 0, and fix scale at H(2, 2) == 1.0. + H /= H(2, 2); + + // Assume H is close to identity, so subtract out the diagonal. + H(0, 0) -= 1.0; + H(1, 1) -= 1.0; + + CHECK_NE(H(2, 2), 0.0) << H; + for (int i = 0; i < 8; ++i) { + parameters[i] = H(i / 3, i % 3); + LG << "Parameters[" << i << "]: " << parameters[i]; + } + } + + template + static void Forward(const T *p, + const T &x1, const T& y1, T *x2, T* y2) { + // Homography warp with manual 3x3 matrix multiply. + const T xx2 = (1.0 + p[0]) * x1 + p[1] * y1 + p[2]; + const T yy2 = p[3] * x1 + (1.0 + p[4]) * y1 + p[5]; + const T zz2 = p[6] * x1 + p[7] * y1 + 1.0; + *x2 = xx2 / zz2; + *y2 = yy2 / zz2; + } + + enum { NUM_PARAMETERS = 8 }; + double parameters[NUM_PARAMETERS]; +}; + +// Determine the number of samples to use for x and y. Quad winding goes: +// +// 0 1 +// 3 2 +// +// The idea is to take the maximum x or y distance. This may be oversampling. +// TODO(keir): Investigate the various choices; perhaps average is better? +void PickSampling(const double *x1, const double *y1, + const double *x2, const double *y2, + int *num_samples_x, int *num_samples_y) { + Vec2 a0(x1[0], y1[0]); + Vec2 a1(x1[1], y1[1]); + Vec2 a2(x1[2], y1[2]); + Vec2 a3(x1[3], y1[3]); + + Vec2 b0(x1[0], y1[0]); + Vec2 b1(x1[1], y1[1]); + Vec2 b2(x1[2], y1[2]); + Vec2 b3(x1[3], y1[3]); + + double x_dimensions[4] = { + (a1 - a0).norm(), + (a3 - a2).norm(), + (b1 - b0).norm(), + (b3 - b2).norm() + }; + + double y_dimensions[4] = { + (a3 - a0).norm(), + (a1 - a2).norm(), + (b3 - b0).norm(), + (b1 - b2).norm() + }; + const double kScaleFactor = 1.0; + *num_samples_x = static_cast( + kScaleFactor * *std::max_element(x_dimensions, x_dimensions + 4)); + *num_samples_y = static_cast( + kScaleFactor * *std::max_element(y_dimensions, y_dimensions + 4)); + LG << "Automatic num_samples_x: " << *num_samples_x + << ", num_samples_y: " << *num_samples_y; +} + +bool SearchAreaTooBigForDescent(const FloatImage &image2, + const double *x2, const double *y2) { + // TODO(keir): Check the bounds and enable only when it makes sense. + return true; +} + +bool PointOnRightHalfPlane(const Vec2 &a, const Vec2 &b, double x, double y) { + Vec2 ba = b - a; + return ((Vec2(x, y) - b).transpose() * Vec2(-ba.y(), ba.x())) > 0; +} + +// Determine if a point is in a quad. The quad is arranged as: +// +// +-------> x +// | +// | a0------a1 +// | | | +// | | | +// | | | +// | a3------a2 +// v +// y +// +// The implementation does up to four half-plane comparisons. +bool PointInQuad(const double *xs, const double *ys, double x, double y) { + Vec2 a0(xs[0], ys[0]); + Vec2 a1(xs[1], ys[1]); + Vec2 a2(xs[2], ys[2]); + Vec2 a3(xs[3], ys[3]); + + return PointOnRightHalfPlane(a0, a1, x, y) && + PointOnRightHalfPlane(a1, a2, x, y) && + PointOnRightHalfPlane(a2, a3, x, y) && + PointOnRightHalfPlane(a3, a0, x, y); +} + +// This makes it possible to map between Eigen float arrays and FloatImage +// without using comparisons. +typedef Eigen::Array FloatArray; + +// This creates a pattern in the frame of image2, from the pixel is image1, +// based on the initial guess represented by the two quads x1, y1, and x2, y2. +template +void CreateBrutePattern(const double *x1, const double *y1, + const double *x2, const double *y2, + const FloatImage &image1, + const FloatImage *image1_mask, + FloatArray *pattern, + FloatArray *mask, + int *origin_x, + int *origin_y) { + // Get integer bounding box of quad2 in image2. + int min_x = static_cast(floor(*std::min_element(x2, x2 + 4))); + int min_y = static_cast(floor(*std::min_element(y2, y2 + 4))); + int max_x = static_cast(ceil (*std::max_element(x2, x2 + 4))); + int max_y = static_cast(ceil (*std::max_element(y2, y2 + 4))); + + int w = max_x - min_x; + int h = max_y - min_y; + + pattern->resize(h, w); + mask->resize(h, w); + + Warp inverse_warp(x2, y2, x1, y1); + + // r,c are in the coordinate frame of image2. + for (int r = min_y; r < max_y; ++r) { + for (int c = min_x; c < max_x; ++c) { + // i and j are in the coordinate frame of the pattern in image2. + int i = r - min_y; + int j = c - min_x; + + double dst_x = c; + double dst_y = r; + double src_x; + double src_y; + inverse_warp.Forward(inverse_warp.parameters, + dst_x, dst_y, + &src_x, &src_y); + + if (PointInQuad(x1, y1, src_x, src_y)) { + (*pattern)(i, j) = SampleLinear(image1, src_y, src_x); + (*mask)(i, j) = 1.0; + if (image1_mask) { + (*mask)(i, j) = SampleLinear(*image1_mask, src_y, src_x);; + } + } else { + (*pattern)(i, j) = 0.0; + (*mask)(i, j) = 0.0; + } + } + } + *origin_x = min_x; + *origin_y = min_y; +} + +// Compute a translation-only estimate of the warp, using brute force search. A +// smarter implementation would use the FFT to compute the normalized cross +// correlation. Instead, this is a dumb implementation. Surprisingly, it is +// fast enough in practice. +// +// TODO(keir): The normalization is less effective for the brute force search +// than it is with the Ceres solver. It's unclear if this is a bug or due to +// the original frame being too different from the reprojected reference in the +// destination frame. +// +// The likely solution is to use the previous frame, instead of the original +// pattern, when doing brute initialization. Unfortunately that implies a +// totally different warping interface, since access to more than a the source +// and current destination frame is necessary. +template +void BruteTranslationOnlyInitialize(const FloatImage &image1, + const FloatImage *image1_mask, + const FloatImage &image2, + const int num_extra_points, + const bool use_normalized_intensities, + const double *x1, const double *y1, + double *x2, double *y2) { + // Create the pattern to match in the space of image2, assuming our inital + // guess isn't too far from the template in image1. If there is no image1 + // mask, then the resulting mask is binary. + FloatArray pattern; + FloatArray mask; + int origin_x = -1, origin_y = -1; + CreateBrutePattern(x1, y1, x2, y2, + image1, image1_mask, + &pattern, &mask, + &origin_x, &origin_y); + + // For normalization, premultiply the pattern by the inverse pattern mean. + double mask_sum = 1.0; + if (use_normalized_intensities) { + mask_sum = mask.sum(); + double inverse_pattern_mean = mask_sum / ((mask * pattern).sum()); + pattern *= inverse_pattern_mean; + } + + // Use Eigen on the images via maps for strong vectorization. + Map search(image2.Data(), image2.Height(), image2.Width()); + + // Try all possible locations inside the search area. Yes, everywhere. + // + // TODO(keir): There are a number of possible optimizations here. One choice + // is to make a grid and only try one out of every N possible samples. + // + // Another, slightly more clever idea, is to compute some sort of spatial + // frequency distribution of the pattern patch. If the spatial resolution is + // high (e.g. a grating pattern or fine lines) then checking every possible + // translation is necessary, since a 1-pixel shift may induce a massive + // change in the cost function. If the image is a blob or splotch with blurry + // edges, then fewer samples are necessary since a few pixels offset won't + // change the cost function much. + double best_sad = std::numeric_limits::max(); + int best_r = -1; + int best_c = -1; + int w = pattern.cols(); + int h = pattern.rows(); + for (int r = 0; r < (image2.Height() - h); ++r) { + for (int c = 0; c < (image2.Width() - w); ++c) { + // Compute the weighted sum of absolute differences, Eigen style. Note + // that the block from the search image is never stored in a variable, to + // avoid copying overhead and permit inlining. + double sad; + if (use_normalized_intensities) { + // TODO(keir): It's really dumb to recompute the search mean for every + // shift. A smarter implementation would use summed area tables + // instead, reducing the mean calculation to an O(1) operation. + double inverse_search_mean = + mask_sum / ((mask * search.block(r, c, h, w)).sum()); + sad = (mask * (pattern - (search.block(r, c, h, w) * + inverse_search_mean))).abs().sum(); + } else { + sad = (mask * (pattern - search.block(r, c, h, w))).abs().sum(); + } + if (sad < best_sad) { + best_r = r; + best_c = c; + best_sad = sad; + } + } + } + CHECK_NE(best_r, -1); + CHECK_NE(best_c, -1); + + LG << "Brute force translation found a shift. " + << "best_c: " << best_c << ", best_r: " << best_r << ", " + << "origin_x: " << origin_x << ", origin_y: " << origin_y << ", " + << "dc: " << (best_c - origin_x) << ", " + << "dr: " << (best_r - origin_y) + << ", tried " << ((image2.Height() - h) * (image2.Width() - w)) + << " shifts."; + + // Apply the shift. + for (int i = 0; i < 4 + num_extra_points; ++i) { + x2[i] += best_c - origin_x; + y2[i] += best_r - origin_y; + } +} + +} // namespace + +template +void TemplatedTrackRegion(const FloatImage &image1, + const FloatImage &image2, + const double *x1, const double *y1, + const TrackRegionOptions &options, + double *x2, double *y2, + TrackRegionResult *result) { + for (int i = 0; i < 4; ++i) { + LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); guess (" + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " + << (y2[i] - y1[i]) << ")."; + } + if (options.use_normalized_intensities) { + LG << "Using normalized intensities."; + } + + // Bail early if the points are already outside. + if (!AllInBounds(image1, x1, y1)) { + result->termination = TrackRegionResult::SOURCE_OUT_OF_BOUNDS; + return; + } + if (!AllInBounds(image2, x2, y2)) { + result->termination = TrackRegionResult::DESTINATION_OUT_OF_BOUNDS; + return; + } + // TODO(keir): Check quads to ensure there is some area. + + // Keep a copy of the "original" guess for regularization. + double x2_original[4]; + double y2_original[4]; + for (int i = 0; i < 4; ++i) { + x2_original[i] = x2[i]; + y2_original[i] = y2[i]; + } + + // Prepare the image and gradient. + Array3Df image_and_gradient1; + Array3Df image_and_gradient2; + BlurredImageAndDerivativesChannels(image1, options.sigma, + &image_and_gradient1); + BlurredImageAndDerivativesChannels(image2, options.sigma, + &image_and_gradient2); + + // Possibly do a brute-force translation-only initialization. + if (SearchAreaTooBigForDescent(image2, x2, y2) && + options.use_brute_initialization) { + LG << "Running brute initialization..."; + BruteTranslationOnlyInitialize(image_and_gradient1, + options.image1_mask, + image2, + options.num_extra_points, + options.use_normalized_intensities, + x1, y1, x2, y2); + for (int i = 0; i < 4; ++i) { + LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute (" + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) + << ", " << (y2[i] - y1[i]) << ")."; + } + } + + // Prepare the initial warp parameters from the four correspondences. + // Note: This must happen after the brute initialization runs, since the + // brute initialization mutates x2 and y2 in place. + Warp warp(x1, y1, x2, y2); + + // Decide how many samples to use in the x and y dimensions. + int num_samples_x; + int num_samples_y; + PickSampling(x1, y1, x2, y2, &num_samples_x, &num_samples_y); + + + // Compute the warp from rectangular coordinates. + Mat3 canonical_homography = ComputeCanonicalHomography(x1, y1, + num_samples_x, + num_samples_y); + + ceres::Problem problem; + + // Construct the warp cost function. AutoDiffCostFunction takes ownership. + PixelDifferenceCostFunctor *pixel_difference_cost_function = + new PixelDifferenceCostFunctor(options, + image_and_gradient1, + image_and_gradient2, + canonical_homography, + num_samples_x, + num_samples_y, + warp); + problem.AddResidualBlock( + new ceres::AutoDiffCostFunction< + PixelDifferenceCostFunctor, + ceres::DYNAMIC, + Warp::NUM_PARAMETERS>(pixel_difference_cost_function, + num_samples_x * num_samples_y), + NULL, + warp.parameters); + + // Construct the regularizing cost function + if (options.regularization_coefficient != 0.0) { + WarpRegularizingCostFunctor *regularizing_warp_cost_function = + new WarpRegularizingCostFunctor(options, + x1, y2, + x2_original, + y2_original, + warp); + + problem.AddResidualBlock( + new ceres::AutoDiffCostFunction< + WarpRegularizingCostFunctor, + 8 /* num_residuals */, + Warp::NUM_PARAMETERS>(regularizing_warp_cost_function), + NULL, + warp.parameters); + } + + // Configure the solve. + ceres::Solver::Options solver_options; + solver_options.linear_solver_type = ceres::DENSE_QR; + solver_options.max_num_iterations = options.max_iterations; + solver_options.update_state_every_iteration = true; + solver_options.parameter_tolerance = 1e-16; + solver_options.function_tolerance = 1e-16; + + // Prevent the corners from going outside the destination image. + BoundaryCheckingCallback callback(image2, warp, x1, y1); + solver_options.callbacks.push_back(&callback); + + // Run the solve. + ceres::Solver::Summary summary; + ceres::Solve(solver_options, &problem, &summary); + + LG << "Summary:\n" << summary.FullReport(); + + // Update the four points with the found solution; if the solver failed, then + // the warp parameters are the identity (so ignore failure). + // + // Also warp any extra points on the end of the array. + for (int i = 0; i < 4 + options.num_extra_points; ++i) { + warp.Forward(warp.parameters, x1[i], y1[i], x2 + i, y2 + i); + LG << "Warped point " << i << ": (" << x1[i] << ", " << y1[i] << ") -> (" + << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) << ", " + << (y2[i] - y1[i]) << ")."; + } + + // TODO(keir): Update the result statistics. + // TODO(keir): Add a normalize-cross-correlation variant. + + CHECK_NE(summary.termination_type, ceres::USER_ABORT) << "Libmv bug."; + if (summary.termination_type == ceres::USER_ABORT) { + result->termination = TrackRegionResult::FELL_OUT_OF_BOUNDS; + return; + } +#define HANDLE_TERMINATION(termination_enum) \ + if (summary.termination_type == ceres::termination_enum) { \ + result->termination = TrackRegionResult::termination_enum; \ + return; \ + } + + // Avoid computing correlation for tracking failures. + HANDLE_TERMINATION(DID_NOT_RUN); + HANDLE_TERMINATION(NUMERICAL_FAILURE); + + // Otherwise, run a final correlation check. + if (options.minimum_correlation > 0.0) { + result->correlation = pixel_difference_cost_function-> + PearsonProductMomentCorrelationCoefficient(warp.parameters); + if (result->correlation < options.minimum_correlation) { + LG << "Failing with insufficient correlation."; + result->termination = TrackRegionResult::INSUFFICIENT_CORRELATION; + return; + } + } + + HANDLE_TERMINATION(PARAMETER_TOLERANCE); + HANDLE_TERMINATION(FUNCTION_TOLERANCE); + HANDLE_TERMINATION(GRADIENT_TOLERANCE); + HANDLE_TERMINATION(NO_CONVERGENCE); +#undef HANDLE_TERMINATION +}; + +void TrackRegion(const FloatImage &image1, + const FloatImage &image2, + const double *x1, const double *y1, + const TrackRegionOptions &options, + double *x2, double *y2, + TrackRegionResult *result) { + // Enum is necessary due to templated nature of autodiff. +#define HANDLE_MODE(mode_enum, mode_type) \ + if (options.mode == TrackRegionOptions::mode_enum) { \ + TemplatedTrackRegion(image1, image2, \ + x1, y1, \ + options, \ + x2, y2, \ + result); \ + return; \ + } + HANDLE_MODE(TRANSLATION, TranslationWarp); + HANDLE_MODE(TRANSLATION_SCALE, TranslationScaleWarp); + HANDLE_MODE(TRANSLATION_ROTATION, TranslationRotationWarp); + HANDLE_MODE(TRANSLATION_ROTATION_SCALE, TranslationRotationScaleWarp); + HANDLE_MODE(AFFINE, AffineWarp); + HANDLE_MODE(HOMOGRAPHY, HomographyWarp); +#undef HANDLE_MODE +} + +bool SamplePlanarPatch(const FloatImage &image, + const double *xs, const double *ys, + int num_samples_x, int num_samples_y, + FloatImage *patch, + double *warped_position_x, double *warped_position_y) { + // Bail early if the points are outside the image. + if (!AllInBounds(image, xs, ys)) { + LG << "Can't sample patch: out of bounds."; + return false; + } + + // Make the patch have the appropriate size, and match the depth of image. + patch->Resize(num_samples_y, num_samples_x, image.Depth()); + + // Compute the warp from rectangular coordinates. + Mat3 canonical_homography = ComputeCanonicalHomography(xs, ys, + num_samples_x, + num_samples_y); + + // Walk over the coordinates in the canonical space, sampling from the image + // in the original space and copying the result into the patch. + for (int r = 0; r < num_samples_y; ++r) { + for (int c = 0; c < num_samples_x; ++c) { + Vec3 image_position = canonical_homography * Vec3(c, r, 1); + image_position /= image_position(2); + SampleLinear(image, image_position(1), + image_position(0), + &(*patch)(r, c, 0)); + } + } + + Vec3 warped_position = canonical_homography.inverse() * Vec3(xs[4], ys[4], 1); + warped_position /= warped_position(2); + + *warped_position_x = warped_position(0); + *warped_position_y = warped_position(1); + + return true; +} + +} // namespace libmv diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h new file mode 100644 index 00000000000..0de11239da6 --- /dev/null +++ b/extern/libmv/libmv/tracking/track_region.h @@ -0,0 +1,146 @@ +// Copyright (c) 2012 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#ifndef LIBMV_TRACKING_TRACK_REGION_H_ + +// Necessary for M_E when building with MSVC. +#define _USE_MATH_DEFINES + +#include "libmv/tracking/esm_region_tracker.h" + +#include "libmv/image/image.h" +#include "libmv/image/sample.h" +#include "libmv/numeric/numeric.h" + +namespace libmv { + +struct TrackRegionOptions { + TrackRegionOptions(); + + enum Mode { + TRANSLATION, + TRANSLATION_ROTATION, + TRANSLATION_SCALE, + TRANSLATION_ROTATION_SCALE, + AFFINE, + HOMOGRAPHY, + }; + Mode mode; + + double minimum_correlation; + int max_iterations; + + // Use the "Efficient Second-order Minimization" scheme. This increases + // convergence speed at the cost of more per-iteration work. + bool use_esm; + + // If true, apply a brute-force translation-only search before attempting the + // full search. This is not enabled if the destination image ("image2") is + // too small; in that case eithen the basin of attraction is close enough + // that the nearby minima is correct, or the search area is too small. + bool use_brute_initialization; + + // If true, normalize the image patches by their mean before doing the sum of + // squared error calculation. This is reasonable since the effect of + // increasing light intensity is multiplicative on the pixel intensities. + // + // Note: This does nearly double the solving time, so it is not advised to + // turn this on all the time. + bool use_normalized_intensities; + + // The size in pixels of the blur kernel used to both smooth the image and + // take the image derivative. + double sigma; + + // Extra points that should get transformed by the warp. This is useful + // because the actual warp parameters are not exposed. + int num_extra_points; + + // For motion models other than translation, the optimizer sometimes has + // trouble deciding what to do around flat areas in the cost function. This + // leads to the optimizer picking poor solutions near the minimum. Visually, + // the effect is that the quad corners jiggle around, even though the center + // of the patch is well estimated. regularization_coefficient controls a term + // in the sum of squared error cost that makes it expensive for the optimizer + // to pick a warp that changes the shape of the patch dramatically (e.g. + // rotating, scaling, skewing, etc). + // + // In particular it adds an 8-residual cost function to the optimization, + // where each corner induces 2 residuals: the difference between the warped + // and the initial guess. However, the patch centroids are subtracted so that + // only patch distortions are penalized. + // + // If zero, no regularization is used. + double regularization_coefficient; + + // If non-null, this is used as the pattern mask. It should match the size of + // image1, even though only values inside the image1 quad are examined. The + // values must be in the range 0.0 to 0.1. + FloatImage *image1_mask; +}; + +struct TrackRegionResult { + enum Termination { + // Ceres termination types, duplicated; though, not the int values. + PARAMETER_TOLERANCE, + FUNCTION_TOLERANCE, + GRADIENT_TOLERANCE, + NO_CONVERGENCE, + DID_NOT_RUN, + NUMERICAL_FAILURE, + + // Libmv specific errors. + SOURCE_OUT_OF_BOUNDS, + DESTINATION_OUT_OF_BOUNDS, + FELL_OUT_OF_BOUNDS, + INSUFFICIENT_CORRELATION, + CONFIGURATION_ERROR, + }; + Termination termination; + + int num_iterations; + double correlation; + + // Final parameters? + bool used_brute_translation_initialization; +}; + +// Always needs 4 correspondences. +void TrackRegion(const FloatImage &image1, + const FloatImage &image2, + const double *x1, const double *y1, + const TrackRegionOptions &options, + double *x2, double *y2, + TrackRegionResult *result); + +// Sample a "canonical" version of the passed planar patch, using bilinear +// sampling. The passed corners must be within the image, and have at least two +// pixels of border around them. (so e.g. a corner of the patch cannot lie +// directly on the edge of the image). Four corners are always required. All +// channels are interpolated. +bool SamplePlanarPatch(const FloatImage &image, + const double *xs, const double *ys, + int num_samples_x, int num_samples_y, + FloatImage *patch, + double *warped_position_x, double *warped_position_y); + +} // namespace libmv + +#endif // LIBMV_TRACKING_TRACK_REGION_H_ diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index d0f0f3de276..1cef4624a04 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -230,10 +230,9 @@ class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): sub.prop(settings, "default_search_size") col.label(text="Tracker:") - col.prop(settings, "default_tracker", text="") - - if settings.default_tracker == 'KLT': - col.prop(settings, "default_pyramid_levels") + col.prop(settings, "default_motion_model") + col.prop(settings, "default_use_brute") + col.prop(settings, "default_use_normalization") col.prop(settings, "default_correlation_min") col.separator() @@ -575,10 +574,9 @@ class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel): active = clip.tracking.tracks.active if active: - col.prop(active, "tracker") - - if active.tracker == 'KLT': - col.prop(active, "pyramid_levels") + col.prop(active, "motion_model") + col.prop(active, "use_brute") + col.prop(active, "use_normalization") col.prop(active, "correlation_min") col.separator() diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 4d9a5746c87..8c28dd93a5e 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -48,7 +48,7 @@ struct Object; struct Scene; void BKE_tracking_init_settings(struct MovieTracking *tracking); -void BKE_tracking_clamp_track(struct MovieTrackingTrack *track, int event); +void BKE_tracking_clamp_marker(struct MovieTrackingMarker *marker, int event); void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear); struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, struct ListBase *tracksbase, @@ -57,6 +57,7 @@ struct MovieTrackingMarker *BKE_tracking_insert_marker(struct MovieTrackingTrack struct MovieTrackingMarker *marker); void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr); +void BKE_tracking_marker_pattern_minmax(struct MovieTrackingMarker *marker, float min[2], float max[2]); struct MovieTrackingMarker *BKE_tracking_get_marker(struct MovieTrackingTrack *track, int framenr); struct MovieTrackingMarker *BKE_tracking_ensure_marker(struct MovieTrackingTrack *track, int framenr); struct MovieTrackingMarker *BKE_tracking_exact_marker(struct MovieTrackingTrack *track, int framenr); @@ -70,12 +71,15 @@ void BKE_tracking_clear_path(struct MovieTrackingTrack *track, int ref_frame, in void BKE_tracking_join_tracks(struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); void BKE_tracking_free(struct MovieTracking *tracking); +struct ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, + struct ImBuf *struct_ibuf, struct MovieTrackingMarker *marker, + int num_samples_x, int num_samples_y, float pos[2]); struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int margin, int anchored, - float pos[2], int origin[2]); + struct MovieTrackingMarker *marker, int anchored, int disable_channels); struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int margin, int anchored, - float pos[2], int origin[2]); + struct MovieTrackingMarker *marker, int anchored, int disable_channels); +struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, int width, int height); void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); @@ -189,7 +193,6 @@ void BKE_tracking_dopesheet_update(struct MovieTracking *tracking, int sort_meth #define CLAMP_PAT_POS 2 #define CLAMP_SEARCH_DIM 3 #define CLAMP_SEARCH_POS 4 -#define CLAMP_PYRAMID_LEVELS 5 #define TRACK_AREA_NONE -1 #define TRACK_AREA_POINT 1 diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index abdc8835d43..8b91ee29c59 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1032,6 +1032,11 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->track_preview = NULL; } + if (scopes->track_search) { + IMB_freeImBuf(scopes->track_search); + scopes->track_search = NULL; + } + scopes->marker = NULL; scopes->track = NULL; @@ -1052,7 +1057,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->track_disabled = FALSE; if (ibuf && (ibuf->rect || ibuf->rect_float)) { - ImBuf *tmpibuf; + ImBuf *search_ibuf; MovieTrackingMarker undist_marker = *marker; if (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { @@ -1070,27 +1075,36 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip undist_marker.pos[1] /= height * aspy; } - /* NOTE: margin should be kept in sync with value from ui_draw_but_TRACKPREVIEW */ - tmpibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, &undist_marker, 3 /* margin */, - 1 /* anchor */, scopes->track_pos, NULL); + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, TRUE, TRUE); + + if (!search_ibuf->rect_float) { + /* sampling happens in float buffer */ + IMB_float_from_rect(search_ibuf); + } - if (tmpibuf->rect_float) - IMB_rect_from_float(tmpibuf); + scopes->undist_marker = undist_marker; + scopes->track_search = search_ibuf; - if (tmpibuf->rect) - scopes->track_preview = tmpibuf; - else - IMB_freeImBuf(tmpibuf); + scopes->frame_width = ibuf->x; + scopes->frame_height = ibuf->y; } IMB_freeImBuf(ibuf); } if ((track->flag & TRACK_LOCKED) == 0) { + float pat_min[2], pat_max[2]; + scopes->marker = marker; scopes->track = track; - scopes->slide_scale[0] = track->pat_max[0] - track->pat_min[0]; - scopes->slide_scale[1] = track->pat_max[1] - track->pat_min[1]; + + /* XXX: would work fine with non-transformed patterns, but would likely fail + * with transformed patterns, but that would be easier to debug when + * we'll have real pattern sampling (at least to test) */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + scopes->slide_scale[0] = pat_max[0] - pat_min[0]; + scopes->slide_scale[1] = pat_max[1] - pat_min[1]; } } } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index fb78e89cc30..938bff81470 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -20,6 +20,7 @@ * * Contributor(s): Blender Foundation, * Sergey Sharybin + * Keir Mierle * * ***** END GPL LICENSE BLOCK ***** */ @@ -59,6 +60,8 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "raskter.h" + #ifdef WITH_LIBMV # include "libmv-capi.h" #else @@ -73,6 +76,141 @@ static struct { ListBase tracks; } tracking_clipboard; +/*********************** space transformation functions *************************/ + +/* Three coordinate frames: Frame, Search, and Marker + * Two units: Pixels, Unified + * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search + * window relative coordinates in pixels, and "frame_unified" are unified 0..1 + * coordinates relative to the entire frame. + */ +static void unified_to_pixel(int frame_width, int frame_height, + const float unified_coords[2], float pixel_coords[2]) +{ + pixel_coords[0] = unified_coords[0] * frame_width; + pixel_coords[1] = unified_coords[1] * frame_height; +} + +static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], + float frame_unified_coords[2]) +{ + frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0]; + frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1]; +} + +static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + const float marker_unified_coords[2], float frame_pixel_coords[2]) +{ + marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); + unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords); +} + +static void get_search_origin_frame_pixel(int frame_width, int frame_height, + const MovieTrackingMarker *marker, float frame_pixel[2]) +{ + /* Get the lower left coordinate of the search window and snap to pixel coordinates */ + marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel); + frame_pixel[0] = (int)frame_pixel[0]; + frame_pixel[1] = (int)frame_pixel[1]; +} + +#ifdef WITH_LIBMV +static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2]) +{ + unified_coords[0] = pixel_coords[0] / frame_width; + unified_coords[1] = pixel_coords[1] / frame_height; +} + +static void marker_unified_to_search_pixel(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + const float marker_unified[2], float search_pixel[2]) +{ + float frame_pixel[2]; + float search_origin_frame_pixel[2]; + + marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel); + get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); + sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); +} + +static void search_pixel_to_marker_unified(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + const float search_pixel[2], float marker_unified[2]) +{ + float frame_unified[2]; + float search_origin_frame_pixel[2]; + + get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); + add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); + pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified); + + /* marker pos is in frame unified */ + sub_v2_v2v2(marker_unified, frame_unified, marker->pos); +} + +/* Each marker has 5 coordinates associated with it that get warped with + * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). + * This function puts those 5 points into the appropriate frame for tracking + * (the "search" coordinate frame). + */ +static void get_marker_coords_for_tracking(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + double search_pixel_x[5], double search_pixel_y[5]) +{ + int i; + float unified_coords[2]; + float pixel_coords[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; i++) { + marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords); + search_pixel_x[i] = pixel_coords[0]; + search_pixel_y[i] = pixel_coords[1]; + } + /* Convert the center position (aka "pos"); this is the origin */ + unified_coords[0] = 0.0; + unified_coords[1] = 0.0; + marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords); + + search_pixel_x[4] = pixel_coords[0]; + search_pixel_y[4] = pixel_coords[1]; +} + +/* Inverse of above. */ +static void set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker, + const double search_pixel_x[5], const double search_pixel_y[5]) +{ + int i; + float marker_unified[2]; + float search_pixel[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; i++) { + search_pixel[0] = search_pixel_x[i]; + search_pixel[1] = search_pixel_y[i]; + search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]); + } + + /* Convert the center position (aka "pos"); this is the origin */ + search_pixel[0] = search_pixel_x[4]; + search_pixel[1] = search_pixel_y[4]; + search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified); + + /* If the tracker tracked nothing, then "marker_unified" would be zero. + * Otherwise, the entire patch shifted, and that delta should be applied to + * all the coordinates. + */ + for (i = 0; i < 4; i++) { + marker->pattern_corners[i][0] -= marker_unified[0]; + marker->pattern_corners[i][1] -= marker_unified[1]; + } + + marker->pos[0] += marker_unified[0]; + marker->pos[1] += marker_unified[1]; +} +#endif + /*********************** common functions *************************/ void BKE_tracking_init_settings(MovieTracking *tracking) @@ -81,11 +219,10 @@ void BKE_tracking_init_settings(MovieTracking *tracking) tracking->camera.pixel_aspect = 1.0f; tracking->camera.units = CAMERA_UNITS_MM; - tracking->settings.default_tracker = TRACKER_HYBRID; + tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; tracking->settings.default_minimum_correlation = 0.75; tracking->settings.default_pattern_size = 11; tracking->settings.default_search_size = 61; - tracking->settings.default_pyramid_levels = 2; tracking->settings.keyframe1 = 1; tracking->settings.keyframe2 = 30; tracking->settings.dist = 1; @@ -99,105 +236,68 @@ void BKE_tracking_init_settings(MovieTracking *tracking) BKE_tracking_new_object(tracking, "Camera"); } -void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) +void BKE_tracking_clamp_marker(MovieTrackingMarker *marker, int event) { int a; - float pat_min[2]; - float pat_max[2]; - float max_pyramid_level_factor = 1.0; - - if (track->tracker == TRACKER_KLT) { - max_pyramid_level_factor = 1 << (track->pyramid_levels - 1); - } - - /* sort */ - for (a = 0; a < 2; a++) { - if (track->pat_min[a] > track->pat_max[a]) - SWAP(float, track->pat_min[a], track->pat_max[a]); - - if (track->search_min[a] > track->search_max[a]) - SWAP(float, track->search_min[a], track->search_max[a]); - } + float pat_min[2], pat_max[2]; - /* compute the effective pattern size, which differs from the fine resolution - * pattern size for the pyramid KLT tracker */ - for (a = 0; a < 2; a++) { - pat_min[a] = max_pyramid_level_factor * track->pat_min[a]; - pat_max[a] = max_pyramid_level_factor * track->pat_max[a]; - } + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); if (event == CLAMP_PAT_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - track->search_min[a] = MIN2(pat_min[a], track->search_min[a]); - track->search_max[a] = MAX2(pat_max[a], track->search_max[a]); + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); } } else if (event == CLAMP_PAT_POS) { float dim[2]; - sub_v2_v2v2(dim, track->pat_max, track->pat_min); + sub_v2_v2v2(dim, pat_max, pat_min); for (a = 0; a < 2; a++) { + int b; /* pattern shouldn't be moved outside of search */ - if (pat_min[a] < track->search_min[a]) { - track->pat_min[a] = track->search_min[a] - (pat_min[a] - track->pat_min[a]); - track->pat_max[a] = track->pat_min[a] + dim[a]; + if (pat_min[a] < marker->search_min[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; } - if (track->pat_max[a] > track->search_max[a]) { - track->pat_max[a] = track->search_max[a] - (pat_max[a] - track->pat_max[a]); - track->pat_min[a] = track->pat_max[a] - dim[a]; + if (pat_max[a] > marker->search_max[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; } } } else if (event == CLAMP_SEARCH_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - track->search_min[a] = MIN2(pat_min[a], track->search_min[a]); - track->search_max[a] = MAX2(pat_max[a], track->search_max[a]); + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); } } else if (event == CLAMP_SEARCH_POS) { float dim[2]; - sub_v2_v2v2(dim, track->search_max, track->search_min); + sub_v2_v2v2(dim, marker->search_max, marker->search_min); for (a = 0; a < 2; a++) { /* search shouldn't be moved inside pattern */ - if (track->search_min[a] > pat_min[a]) { - track->search_min[a] = pat_min[a]; - track->search_max[a] = track->search_min[a] + dim[a]; - } - if (track->search_max[a] < pat_max[a]) { - track->search_max[a] = pat_max[a]; - track->search_min[a] = track->search_max[a] - dim[a]; + if (marker->search_min[a] > pat_min[a]) { + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = marker->search_min[a] + dim[a]; } - } - } - else if (event == CLAMP_PYRAMID_LEVELS || (event == CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT)) { - float dim[2]; - sub_v2_v2v2(dim, track->pat_max, track->pat_min); - { - float search_ratio = 2.3f * max_pyramid_level_factor; - - /* resize the search area to something sensible based - * on the number of pyramid levels */ - for (a = 0; a < 2; a++) { - track->search_min[a] = search_ratio * track->pat_min[a]; - track->search_max[a] = search_ratio * track->pat_max[a]; + if (marker->search_max[a] < pat_max[a]) { + marker->search_max[a] = pat_max[a]; + marker->search_min[a] = marker->search_max[a] - dim[a]; } } } - - /* marker's center should be in center of pattern */ - if (event == CLAMP_PAT_DIM || event == CLAMP_PAT_POS) { + else if (event == CLAMP_SEARCH_DIM) { float dim[2]; - - sub_v2_v2v2(dim, track->pat_max, track->pat_min); - + sub_v2_v2v2(dim, pat_max, pat_min); for (a = 0; a < 2; a++) { - track->pat_min[a] = -dim[a] / 2.0f; - track->pat_max[a] = dim[a] / 2.0f; + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = pat_max[a]; } } } @@ -245,29 +345,32 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track"); strcpy(track->name, "Track"); - track->tracker = settings->default_tracker; - track->pyramid_levels = settings->default_pyramid_levels; + track->motion_model = settings->default_motion_model; track->minimum_correlation = settings->default_minimum_correlation; track->margin = settings->default_margin; track->pattern_match = settings->default_pattern_match; track->frames_limit = settings->default_frames_limit; track->flag = settings->default_flag; + track->algorithm_flag = settings->default_algorithm_flag; memset(&marker, 0, sizeof(marker)); marker.pos[0] = x; marker.pos[1] = y; marker.framenr = framenr; - copy_v2_v2(track->pat_max, pat); - negate_v2_v2(track->pat_min, pat); + marker.pattern_corners[0][0] = -pat[0]; + marker.pattern_corners[0][1] = -pat[1]; - copy_v2_v2(track->search_max, search); - negate_v2_v2(track->search_min, search); + marker.pattern_corners[1][0] = pat[0]; + marker.pattern_corners[1][1] = -pat[1]; - BKE_tracking_insert_marker(track, &marker); + negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]); + negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]); - if (track->tracker == TRACKER_KLT) - BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); + copy_v2_v2(marker.search_max, search); + negate_v2_v2(marker.search_min, search); + + BKE_tracking_insert_marker(track, &marker); BLI_addtail(tracksbase, track); BKE_track_unique_name(tracksbase, track); @@ -337,6 +440,16 @@ void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) } } +void BKE_tracking_marker_pattern_minmax(MovieTrackingMarker *marker, float min[2], float max[2]) +{ + INIT_MINMAX2(min, max); + + DO_MINMAX2(marker->pattern_corners[0], min, max); + DO_MINMAX2(marker->pattern_corners[1], min, max); + DO_MINMAX2(marker->pattern_corners[2], min, max); + DO_MINMAX2(marker->pattern_corners[3], min, max); +} + MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr) { int a = track->markersnr - 1; @@ -527,7 +640,8 @@ void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) { /* both tracks are enabled on this frame, so find the whole segment * on which tracks are intersecting and blend tracks using linear - * interpolation to prevent jumps */ + * interpolation to prevent jumps + */ MovieTrackingMarker *marker_a, *marker_b; int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; @@ -827,7 +941,8 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) /* duplicate currently operating tracks to temporary list. * this is needed to keep names in unique state and it's faster to change names - * of currently operating tracks (if needed) */ + * of currently operating tracks (if needed) + */ for (a = 0; a < map->num_tracks; a++) { int replace_sel = 0, replace_rot = 0; MovieTrackingTrack *new_track, *old; @@ -929,10 +1044,14 @@ static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *custo typedef struct TrackContext { #ifdef WITH_LIBMV - float keyframed_pos[2]; + /* the reference marker and cutout search area */ + MovieTrackingMarker marker; - struct libmv_RegionTracker *region_tracker; - float *patch; /* keyframed patch */ + /* keyframed patch. This is the search area */ + float *search_area; + int search_area_height; + int search_area_width; + int framenr; #else int pad; #endif @@ -999,49 +1118,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u if ((marker->flag & MARKER_DISABLED) == 0) { TrackContext track_context; - memset(&track_context, 0, sizeof(TrackContext)); - -#ifdef WITH_LIBMV - { - float patx = (int)((track->pat_max[0] - track->pat_min[0]) * width), - paty = (int)((track->pat_max[1] - track->pat_min[1]) * height); - - float search_size_x = (track->search_max[0] - track->search_min[0]) * width; - float search_size_y = (track->search_max[1] - track->search_min[1]) * height; - float pattern_size_x = (track->pat_max[0] - track->pat_min[0]) * width; - float pattern_size_y = (track->pat_max[1] - track->pat_min[1]) * height; - int wndx = (int)patx / 2, wndy = (int)paty / 2; - int half_wnd = MAX2(wndx, wndy); - - /* compute the maximum pyramid size */ - float search_to_pattern_ratio = MIN2(search_size_x, search_size_y) - / MAX2(pattern_size_x, pattern_size_y); - float log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2; - int max_pyramid_levels = floor(log2_search_to_pattern_ratio + 1); - - /* try to accommodate the user's choice of pyramid level in a way - * that doesn't cause the coarsest pyramid pattern to be larger - * than the search size */ - int level = MIN2(track->pyramid_levels, max_pyramid_levels); - - struct libmv_RegionTracker *region_tracker; - - if (track->tracker == TRACKER_KLT) { - region_tracker = libmv_pyramidRegionTrackerNew(100, level, half_wnd, - track->minimum_correlation); - } - else if (track->tracker == TRACKER_HYBRID) { - region_tracker = libmv_hybridRegionTrackerNew(100, half_wnd, track->minimum_correlation); - } - else if (track->tracker == TRACKER_SAD) { - region_tracker = libmv_bruteRegionTrackerNew(MAX2(wndx, wndy), track->minimum_correlation); - } - - track_context.region_tracker = region_tracker; - } -#endif - tracks_map_insert(context->tracks_map, track, &track_context); } } @@ -1059,7 +1136,8 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u * would be used for images * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might * be stored in a different location - * ignore all the rest possible flags for now */ + * ignore all the rest possible flags for now + */ context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS; context->user = *user; @@ -1077,11 +1155,8 @@ static void track_context_free(void *customdata) TrackContext *track_context = (TrackContext *)customdata; #if WITH_LIBMV - if (track_context->region_tracker) - libmv_regionTrackerDestroy(track_context->region_tracker); - - if (track_context->patch) - MEM_freeN(track_context->patch); + if (track_context->search_area) + MEM_freeN(track_context->search_area); #else (void) track_context; @@ -1100,7 +1175,8 @@ void BKE_tracking_context_free(MovieTrackingContext *context) /* zap channels from the imbuf that are disabled by the user. this can lead to * better tracks sometimes. however, instead of simply zeroing the channels - * out, do a partial grayscale conversion so the display is better. */ + * out, do a partial grayscale conversion so the display is better. + */ void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale) { @@ -1111,7 +1187,8 @@ void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disab return; /* If only some components are selected, it's important to rescale the result - * appropriately so that e.g. if only blue is selected, it's not zeroed out. */ + * appropriately so that e.g. if only blue is selected, it's not zeroed out. + */ scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) + (disable_blue ? 0.0f : 0.0722f); @@ -1167,116 +1244,249 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g track->flag & TRACK_DISABLE_GREEN, track->flag & TRACK_DISABLE_BLUE, grayscale); } -static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2]) +ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, + ImBuf *search_ibuf, MovieTrackingMarker *marker, + int num_samples_x, int num_samples_y, float pos[2]) { - ImBuf *tmpibuf; - int x, y; - int x1, y1, w, h; - float mpos[2]; + ImBuf *pattern_ibuf; + double src_pixel_x[5], src_pixel_y[5]; + double warped_position_x, warped_position_y; - copy_v2_v2(mpos, marker->pos); - if (anchored) - add_v2_v2(mpos, track->offset); + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - if (pos) - zero_v2(pos); + if (!search_ibuf->rect_float) { + IMB_float_from_rect(search_ibuf); + } - x = mpos[0]*ibuf->x; - y = mpos[1]*ibuf->y; + get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); - w = (max[0] - min[0]) * ibuf->x; - h = (max[1] - min[1]) * ibuf->y; + libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4, + src_pixel_x, src_pixel_y, num_samples_x, + num_samples_y, pattern_ibuf->rect_float, + &warped_position_x, &warped_position_y); - /* dimensions should be odd */ - w = w | 1; - h = h | 1; + if (pos) { + pos[0] = warped_position_x; + pos[1] = warped_position_y; + } - x1 = x - (int)(w * (-min[0] / (max[0] - min[0]))); - y1 = y - (int)(h * (-min[1] / (max[1] - min[1]))); + return pattern_ibuf; +} - if (ibuf->rect_float) - tmpibuf = IMB_allocImBuf(w + margin * 2, h + margin * 2, 32, IB_rectfloat); - else - tmpibuf = IMB_allocImBuf(w + margin * 2, h + margin * 2, 32, IB_rect); +ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) +{ + ImBuf *pattern_ibuf, *search_ibuf; + float pat_min[2], pat_max[2]; + int num_samples_x, num_samples_y; + + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x; + num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y; - tmpibuf->profile = ibuf->profile; + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1 - margin, y1 - margin, w + margin * 2, h + margin * 2); + pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, marker, + num_samples_x, num_samples_y, NULL); + + IMB_freeImBuf(search_ibuf); + + return pattern_ibuf; +} + +ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) +{ + ImBuf *searchibuf; + int x, y, w, h; + float search_origin[2]; - if (pos != NULL) { - pos[0] = mpos[0] * ibuf->x - x1 + margin; - pos[1] = mpos[1] * ibuf->y - y1 + margin; + get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin); + + x = search_origin[0]; + y = search_origin[1]; + + if (anchored) { + x += track->offset[0] * ibuf->x; + y += track->offset[1] * ibuf->y; } - if (origin != NULL) { - origin[0] = x1 - margin; - origin[1] = y1 - margin; + w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; + h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; + + searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); + searchibuf->profile = ibuf->profile; + + IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); + + if (disable_channels) { + if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { + disable_imbuf_channels(searchibuf, track, TRUE); + } } - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE)) - { - disable_imbuf_channels(tmpibuf, track, TRUE /* grayscale */); + return searchibuf; +} + +static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) +{ + bGPDlayer *layer; + + if (!track->gpd) + return NULL; + + layer = track->gpd->layers.first; + + while (layer) { + if (layer->flag & GP_LAYER_ACTIVE) + return layer; + + layer = layer->next; } - return tmpibuf; + return NULL; } -ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int margin, int anchored, float pos[2], int origin[2]) +static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTrackingMarker *marker, + bGPDlayer *layer, ImBuf *ibuf, int width, int height) { - return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin); + bGPDframe *frame = layer->frames.first; + float *mask; + int x, y; + float aspy = 1.0f / tracking->camera.pixel_aspect; + + mask = MEM_callocN(ibuf->x * ibuf->y * sizeof(float), "track mask"); + + while (frame) { + bGPDstroke *stroke = frame->strokes.first; + + while (stroke) { + bGPDspoint *stroke_points = stroke->points; + float *mask_points, *fp; + int i; + + if (stroke->flag & GP_STROKE_2DSPACE) { + fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float), + "track mask rasterization points"); + + for (i = 0; i < stroke->totpoints; i++, fp += 2) { + fp[0] = stroke_points[i].x * width / ibuf->x - marker->search_min[0]; + fp[1] = stroke_points[i].y * height * aspy / ibuf->x - marker->search_min[1]; + } + + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); + + MEM_freeN(mask_points); + } + + stroke = stroke->next; + } + + frame = frame->next; + } + + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + float *pixel = &ibuf->rect_float[4 * (y * ibuf->x + x)]; + float val = mask[y * ibuf->x + x]; + + pixel[0] = val; + pixel[1] = val; + pixel[2] = val; + pixel[3] = 1.0f; + } + } + + MEM_freeN(mask); + + IMB_rect_from_float(ibuf); } -ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int margin, int anchored, float pos[2], int origin[2]) +ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int width, int height) { - return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin); + ImBuf *ibuf; + bGPDlayer *layer = track_mask_gpencil_layer_get(track); + int mask_width, mask_height; + + mask_width = (marker->search_max[0] - marker->search_min[0]) * width; + mask_height = (marker->search_max[1] - marker->search_min[1]) * height; + + ibuf = IMB_allocImBuf(mask_width, mask_height, 32, IB_rect | IB_rectfloat); + + if (layer) { + track_mask_gpencil_layer_rasterize(tracking, marker, layer, ibuf, width, height); + } + else { + float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + IMB_rectfill(ibuf, white); + } + + return ibuf; } #ifdef WITH_LIBMV -static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int *width_r, int *height_r, float pos[2], int origin[2]) + +/* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ +static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, + float weight_red, float weight_green, float weight_blue) { - ImBuf *tmpibuf; - float *pixels, *fp; - int x, y, width, height; + int i; - width = (track->search_max[0] - track->search_min[0]) * ibuf->x; - height = (track->search_max[1] - track->search_min[1]) * ibuf->y; + for (i = 0; i < num_pixels; i++) { + const float *pixel = rgba + 4 * i; - tmpibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin); - disable_imbuf_channels(tmpibuf, track, FALSE /* don't grayscale */); + gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]; + } +} - *width_r = width; - *height_r = height; +static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels, + float weight_red, float weight_green, float weight_blue) +{ + int i; - fp = pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); - for (y = 0; y < (int)height; y++) { - for (x = 0; x < (int)width; x++) { - int pixel = tmpibuf->x * y + x; + for (i = 0; i < num_pixels; i++) { + const unsigned char *pixel = rgba + i * 4; - if (tmpibuf->rect_float) { - float *rrgbf = tmpibuf->rect_float + pixel * 4; + *gray++ = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; + } +} - *fp = 0.2126 * rrgbf[0] + 0.7152 * rrgbf[1] + 0.0722 * rrgbf[2]; - } - else { - unsigned char *rrgb = (unsigned char*)tmpibuf->rect + pixel * 4; +static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int *width_r, int *height_r) +{ + ImBuf *searchibuf; + float *gray_pixels; + int width, height; - *fp = (0.2126 * rrgb[0] + 0.7152 * rrgb[1] + 0.0722 * rrgb[2]) / 255.0f; - } + searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE); - fp++; - } + width = searchibuf->x; + height = searchibuf->y; + + *width_r = searchibuf->x; + *height_r = searchibuf->y; + + gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); + + if (searchibuf->rect_float) { + float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height, + 0.2126f, 0.7152f, 0.0722f); + } + else { + uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height, + 0.2126f, 0.7152f, 0.0722f); } - IMB_freeImBuf(tmpibuf); + IMB_freeImBuf(searchibuf); - return pixels; + return gray_pixels; } static unsigned char *get_ucharbuf(ImBuf *ibuf) @@ -1400,10 +1610,12 @@ void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) int BKE_tracking_next(MovieTrackingContext *context) { - ImBuf *ibuf_new; + ImBuf *destination_ibuf; int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr); int a, ok = FALSE, map_size; + int frame_width, frame_height; + map_size = tracks_map_size(context->tracks_map); /* nothing to track, avoid unneeded frames reading to save time and memory */ @@ -1415,28 +1627,31 @@ int BKE_tracking_next(MovieTrackingContext *context) else context->user.framenr++; - ibuf_new = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); - if (!ibuf_new) + destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, + context->clip_flag, MOVIECLIP_CACHE_SKIP); + if (!destination_ibuf) return FALSE; - #pragma omp parallel for private(a) shared(ibuf_new, ok) if (map_size>1) + frame_width = destination_ibuf->x; + frame_height = destination_ibuf->y; + + #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1) for (a = 0; a < map_size; a++) { TrackContext *track_context = NULL; MovieTrackingTrack *track; MovieTrackingMarker *marker; - tracks_map_get(context->tracks_map, a, &track, (void**)&track_context); + tracks_map_get(context->tracks_map, a, &track, (void **)&track_context); marker = BKE_tracking_exact_marker(track, curfra); if (marker && (marker->flag & MARKER_DISABLED) == 0) { #ifdef WITH_LIBMV - int width, height, origin[2], tracked = 0, need_readjust = 0; - float pos[2], margin[2], dim[2]; - double x1, y1, x2, y2; - ImBuf *ibuf = NULL; + int width, height, tracked = 0, need_readjust = 0; + float margin[2], dim[2], pat_min[2], pat_max[2]; MovieTrackingMarker marker_new, *marker_keyed; int onbound = FALSE, nextfra; + double dst_pixel_x[5], dst_pixel_y[5]; if (track->pattern_match == TRACK_MATCH_KEYFRAME) need_readjust = context->first_time; @@ -1449,11 +1664,12 @@ int BKE_tracking_next(MovieTrackingContext *context) nextfra = curfra + 1; /* margin from frame boundaries */ - sub_v2_v2v2(dim, track->pat_max, track->pat_min); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + sub_v2_v2v2(dim, pat_max, pat_min); margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; - margin[0] = MAX2(margin[0], (float)track->margin / ibuf_new->x); - margin[1] = MAX2(margin[1], (float)track->margin / ibuf_new->y); + margin[0] = MAX2(margin[0], (float)track->margin / destination_ibuf->x); + margin[1] = MAX2(margin[1], (float)track->margin / destination_ibuf->y); /* do not track markers which are too close to boundary */ if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || @@ -1462,58 +1678,83 @@ int BKE_tracking_next(MovieTrackingContext *context) onbound = TRUE; } else { + /* to convert to the x/y split array format for libmv. */ + double src_pixel_x[5]; + double src_pixel_y[5]; + + /* settings for the tracker */ + struct libmv_trackRegionOptions options; + struct libmv_trackRegionResult result; + float *patch_new; if (need_readjust) { + ImBuf *reference_ibuf = NULL; /* calculate patch for keyframed position */ - ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); + reference_ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); + track_context->marker = *marker_keyed; - if (track_context->patch) - MEM_freeN(track_context->patch); + if (track_context->search_area) + MEM_freeN(track_context->search_area); - track_context->patch = get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, - track_context->keyframed_pos, origin); + track_context->search_area = get_search_floatbuf(reference_ibuf, track, + marker_keyed, &width, &height); + track_context->search_area_height = height; + track_context->search_area_width = width; - IMB_freeImBuf(ibuf); + IMB_freeImBuf(reference_ibuf); } - patch_new = get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin); + /* for now track to the same search area dimension as marker has got for current frame + * will make all tracked markers in currently tracked segment have the same search area + * size, but it's quite close to what is actually needed + */ + patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); + + /* Configure the tracker */ + options.motion_model = track->motion_model; - x1 = track_context->keyframed_pos[0]; - y1 = track_context->keyframed_pos[1]; + options.use_brute = + ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0); - x2 = pos[0]; - y2 = pos[1]; + options.use_normalization = + ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0); - tracked = libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new, - width, height, x1, y1, &x2, &y2); + options.num_iterations = 50; + options.minimum_correlation = track->minimum_correlation; + options.sigma = 0.9; + /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ + get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y); + get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); + + /* Run the tracker! */ + tracked = libmv_trackRegion(&options, + track_context->search_area, patch_new, + width, height, + src_pixel_x, src_pixel_y, + &result, + dst_pixel_x, dst_pixel_y); MEM_freeN(patch_new); } - if (tracked && !onbound && finite(x2) && finite(y2)) { + if (tracked && !onbound) { + memset(&marker_new, 0, sizeof(marker_new)); + marker_new = *marker; + set_marker_coords_from_tracking(frame_width, frame_height, &marker_new, dst_pixel_x, dst_pixel_y); + marker_new.flag |= MARKER_TRACKED; + marker_new.framenr = nextfra; + if (context->first_time) { #pragma omp critical { /* check if there's no keyframe/tracked markers before tracking marker. - * if so -- create disabled marker before currently tracking "segment" */ - put_disabled_marker(track, marker, !context->backwards, 0); + * if so -- create disabled marker before currently tracking "segment" + */ + put_disabled_marker(track, &marker_new, !context->backwards, 0); } } - memset(&marker_new, 0, sizeof(marker_new)); - - if (!onbound) { - marker_new.pos[0] = (origin[0] + x2) / ibuf_new->x; - marker_new.pos[1] = (origin[1] + y2) / ibuf_new->y; - } - else { - copy_v2_v2(marker_new.pos, marker->pos); - } - - marker_new.flag |= MARKER_TRACKED; - marker_new.framenr = nextfra; - #pragma omp critical { BKE_tracking_insert_marker(track, &marker_new); @@ -1542,7 +1783,7 @@ int BKE_tracking_next(MovieTrackingContext *context) } } - IMB_freeImBuf(ibuf_new); + IMB_freeImBuf(destination_ibuf); context->first_time = FALSE; context->frames++; @@ -2765,7 +3006,8 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, if (tangle == 0.0f) { /* if angle is zero, then it's much faster to use rect copy - * but could be issues with subpixel precisions */ + * but could be issues with subpixel precisions + */ IMB_rectcpy(tmpibuf, ibuf, tloc[0] - (tscale - 1.0f) * width / 2.0f, tloc[1] - (tscale - 1.0f) * height / 2.0f, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fccdcbef564..cd0bbb314eb 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5362,6 +5362,7 @@ static void lib_link_screen(FileData *fd, Main *main) sclip->clip = newlibadr_us(fd, sc->id.lib, sclip->clip); sclip->mask = newlibadr_us(fd, sc->id.lib, sclip->mask); + sclip->scopes.track_search = NULL; sclip->scopes.track_preview = NULL; sclip->draw_context = NULL; sclip->scopes.ok = 0; @@ -7084,12 +7085,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main) track = clip->tracking.tracks.first; while (track) { - if (track->pyramid_levels == 0) - track->pyramid_levels = 2; - if (track->minimum_correlation == 0.0f) track->minimum_correlation = 0.75f; - + track = track->next; } } @@ -7107,10 +7105,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (clip= main->movieclip.first; clip; clip= clip->id.next) { MovieTrackingSettings *settings= &clip->tracking.settings; - - if (settings->default_pyramid_levels == 0) { - settings->default_tracker= TRACKER_KLT; - settings->default_pyramid_levels = 2; + + if (settings->default_pattern_size == 0.0f) { + settings->default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; settings->default_minimum_correlation = 0.75; settings->default_pattern_size = 11; settings->default_search_size = 51; @@ -7638,6 +7635,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 8)) { /* set new deactivation values for game settings */ @@ -7702,6 +7700,46 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTrackingTrack *track; + + track = clip->tracking.tracks.first; + while (track) { + int i; + + for (i = 0; i < track->markersnr; i++) { + MovieTrackingMarker *marker = &track->markers[i]; + + if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && + is_zero_v2(marker->pattern_corners[3]) && is_zero_v2(marker->pattern_corners[3])) + { + marker->pattern_corners[0][0] = track->pat_min[0]; + marker->pattern_corners[0][1] = track->pat_min[1]; + + marker->pattern_corners[1][0] = track->pat_max[0]; + marker->pattern_corners[1][1] = track->pat_min[1]; + + marker->pattern_corners[2][0] = track->pat_max[0]; + marker->pattern_corners[2][1] = track->pat_max[1]; + + marker->pattern_corners[3][0] = track->pat_min[0]; + marker->pattern_corners[3][1] = track->pat_max[1]; + } + + if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) { + copy_v2_v2(marker->search_min, track->search_min); + copy_v2_v2(marker->search_max, track->search_max); + } + } + + track = track->next; + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index f6339d4456f..f368e7cf4c7 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -43,6 +43,7 @@ #include "BKE_colortools.h" #include "BKE_texture.h" +#include "BKE_tracking.h" #include "IMB_imbuf.h" @@ -1507,36 +1508,10 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax); } -static ImBuf *scale_trackpreview_ibuf(ImBuf *ibuf, float track_pos[2], int width, float height, int margin) -{ - ImBuf *scaleibuf; - const float scalex = ((float)ibuf->x - 2 * margin) / width; - const float scaley = ((float)ibuf->y - 2 * margin) / height; - /* NOTE: 1.0f = 0.5f for integer coordinate coorrection (center of pixel vs. left bottom corner of bixel) - * and 0.5f for centering image in preview (cross is draving at exact center of widget so image - * should be shifted by half of pixel for correct centering) - sergey */ - float off_x = (int)track_pos[0] - track_pos[0] + 1.0f; - float off_y = (int)track_pos[1] - track_pos[1] + 1.0f; - int x, y; - - scaleibuf = IMB_allocImBuf(width, height, 32, IB_rect); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float src_x = scalex * (x) + margin - off_x; - float src_y = scaley * (y) + margin - off_y; - - bicubic_interpolation(ibuf, scaleibuf, src_x, src_y, x, y); - } - } - - return scaleibuf; -} - void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti) { rctf rect; - int ok = 0; + int ok = 0, width, height; GLint scissor[4]; MovieClipScopes *scopes = (MovieClipScopes *)but->poin; @@ -1545,6 +1520,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; rect.ymax = (float)recti->ymax - 1; + width = rect.xmax - rect.xmin + 1; + height = rect.ymax - rect.ymin; + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1562,40 +1540,53 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc ok = 1; } - else if (scopes->track_preview) { - /* additional margin around image */ - /* NOTE: should be kept in sync with value from BKE_movieclip_update_scopes */ - const int margin = 3; - float zoomx, zoomy, track_pos[2], off_x, off_y; - int a, width, height; + else if ((scopes->track_search) && + ((!scopes->track_preview) || + (scopes->track_preview->x != width || scopes->track_preview->y != height))) + { + ImBuf *tmpibuf; + + if (scopes->track_preview) + IMB_freeImBuf(scopes->track_preview); + + tmpibuf = BKE_tracking_sample_pattern_imbuf(scopes->frame_width, scopes->frame_height, + scopes->track_search, &scopes->undist_marker, + width, height, scopes->track_pos); + + if (tmpibuf->rect_float) + IMB_rect_from_float(tmpibuf); + + // XXX: for debug only + // tmpibuf->ftype = PNG; + // IMB_saveiff(tmpibuf, "sample.png", IB_rect); + + if (tmpibuf->rect) + scopes->track_preview = tmpibuf; + else + IMB_freeImBuf(tmpibuf); + } + + if (!ok && scopes->track_preview) { + float track_pos[2]; + int a; ImBuf *drawibuf; glPushMatrix(); - track_pos[0] = scopes->track_pos[0] - margin; - track_pos[1] = scopes->track_pos[1] - margin; + track_pos[0] = scopes->track_pos[0]; + track_pos[1] = scopes->track_pos[1]; /* draw content of pattern area */ glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]); - width = rect.xmax - rect.xmin + 1; - height = rect.ymax - rect.ymin; - if (width > 0 && height > 0) { - zoomx = (float)width / (scopes->track_preview->x - 2 * margin); - zoomy = (float)height / (scopes->track_preview->y - 2 * margin); - - off_x = ((int)track_pos[0] - track_pos[0] + 0.5f) * zoomx; - off_y = ((int)track_pos[1] - track_pos[1] + 0.5f) * zoomy; - - drawibuf = scale_trackpreview_ibuf(scopes->track_preview, track_pos, width, height, margin); + drawibuf = scopes->track_preview; glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, drawibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, drawibuf->rect); - IMB_freeImBuf(drawibuf); /* draw cross for pizel position */ - glTranslatef(off_x + rect.xmin + track_pos[0] * zoomx, off_y + rect.ymin + track_pos[1] * zoomy, 0.f); + glTranslatef(rect.xmin + track_pos[0], rect.ymin + track_pos[1], 0.f); glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, rect.xmax - rect.xmin, diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index e69e1f15b6e..ca2ae6e8461 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -186,12 +186,13 @@ typedef struct { MovieClip *clip; MovieClipUser *user; /* user of clip */ MovieTrackingTrack *track; + MovieTrackingMarker *marker; int framenr; /* current frame number */ float marker_pos[2]; /* position of marker in pixel coords */ - float track_pat[2]; /* position and dimensions of marker pattern in pixel coords */ + float marker_pat[2]; /* position and dimensions of marker pattern in pixel coords */ float track_offset[2]; /* offset of "parenting" point */ - float track_search_pos[2], track_search[2]; /* position and dimensions of marker search in pixel coords */ + float marker_search_pos[2], marker_search[2]; /* position and dimensions of marker search in pixel coords */ int marker_flag; /* marker's flags */ } MarkerUpdateCb; @@ -238,60 +239,63 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) ok = TRUE; } else if (event == B_MARKER_PAT_DIM) { - float dim[2], pat_dim[2]; + float dim[2], pat_dim[2], pat_min[2], pat_max[2]; + float scale_x, scale_y; + int a; - sub_v2_v2v2(pat_dim, cb->track->pat_max, cb->track->pat_min); + BKE_tracking_marker_pattern_minmax(cb->marker, pat_min, pat_max); - dim[0] = cb->track_pat[0] / width; - dim[1] = cb->track_pat[1] / height; + sub_v2_v2v2(pat_dim, pat_max, pat_min); - sub_v2_v2(dim, pat_dim); - mul_v2_fl(dim, 0.5f); + dim[0] = cb->marker_pat[0] / width; + dim[1] = cb->marker_pat[1] / height; - cb->track->pat_min[0] -= dim[0]; - cb->track->pat_min[1] -= dim[1]; + scale_x = dim[0] / pat_dim[0]; + scale_y = dim[1] / pat_dim[1]; - cb->track->pat_max[0] += dim[0]; - cb->track->pat_max[1] += dim[1]; + for (a = 0; a < 4; a++) { + cb->marker->pattern_corners[a][0] *= scale_x; + cb->marker->pattern_corners[a][1] *= scale_y; + } - BKE_tracking_clamp_track(cb->track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(cb->marker, CLAMP_PAT_DIM); ok = TRUE; } else if (event == B_MARKER_SEARCH_POS) { float delta[2], side[2]; - sub_v2_v2v2(side, cb->track->search_max, cb->track->search_min); + sub_v2_v2v2(side, cb->marker->search_max, cb->marker->search_min); mul_v2_fl(side, 0.5f); - delta[0] = cb->track_search_pos[0] / width; - delta[1] = cb->track_search_pos[1] / height; + delta[0] = cb->marker_search_pos[0] / width; + delta[1] = cb->marker_search_pos[1] / height; - sub_v2_v2v2(cb->track->search_min, delta, side); - add_v2_v2v2(cb->track->search_max, delta, side); + sub_v2_v2v2(cb->marker->search_min, delta, side); + add_v2_v2v2(cb->marker->search_max, delta, side); - BKE_tracking_clamp_track(cb->track, CLAMP_SEARCH_POS); + BKE_tracking_clamp_marker(cb->marker, CLAMP_SEARCH_POS); ok = TRUE; } else if (event == B_MARKER_SEARCH_DIM) { float dim[2], search_dim[2]; - sub_v2_v2v2(search_dim, cb->track->search_max, cb->track->search_min); + sub_v2_v2v2(search_dim, cb->marker->search_max, cb->marker->search_min); - dim[0] = cb->track_search[0] / width; - dim[1] = cb->track_search[1] / height; + dim[0] = cb->marker_search[0] / width; + dim[1] = cb->marker_search[1] / height; sub_v2_v2(dim, search_dim); mul_v2_fl(dim, 0.5f); - cb->track->search_min[0] -= dim[0]; - cb->track->search_min[1] -= dim[1]; + cb->marker->search_min[0] -= dim[0]; + cb->marker->search_min[1] -= dim[1]; - cb->track->search_max[0] += dim[0]; - cb->track->search_max[1] += dim[1]; + cb->marker->search_max[0] += dim[0]; + cb->marker->search_max[1] += dim[1]; - BKE_tracking_clamp_track(cb->track, CLAMP_SEARCH_DIM); + BKE_tracking_clamp_marker(cb->marker, CLAMP_SEARCH_DIM); ok = TRUE; } @@ -337,6 +341,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P MovieTrackingMarker *marker; MarkerUpdateCb *cb; const char *tip; + float pat_min[2], pat_max[2]; if (!ptr->data) return; @@ -366,6 +371,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P cb->clip = clip; cb->user = user; cb->track = track; + cb->marker = marker; cb->marker_flag = marker->flag; cb->framenr = user->framenr; @@ -383,7 +389,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P } else { int width, height, step, digits; - float pat_dim[2], pat_pos[2], search_dim[2], search_pos[2]; + float pat_dim[2], search_dim[2], search_pos[2]; uiLayout *col; BKE_movieclip_get_size(clip, user, &width, &height); @@ -399,19 +405,18 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P step = 100; digits = 2; - sub_v2_v2v2(pat_dim, track->pat_max, track->pat_min); - sub_v2_v2v2(search_dim, track->search_max, track->search_min); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - add_v2_v2v2(search_pos, track->search_max, track->search_min); - mul_v2_fl(search_pos, 0.5); + sub_v2_v2v2(pat_dim, pat_max, pat_min); + sub_v2_v2v2(search_dim, marker->search_max, marker->search_min); - add_v2_v2v2(pat_pos, track->pat_max, track->pat_min); - mul_v2_fl(pat_pos, 0.5); + add_v2_v2v2(search_pos, marker->search_max, marker->search_min); + mul_v2_fl(search_pos, 0.5); to_pixel_space(cb->marker_pos, marker->pos, width, height); - to_pixel_space(cb->track_pat, pat_dim, width, height); - to_pixel_space(cb->track_search, search_dim, width, height); - to_pixel_space(cb->track_search_pos, search_pos, width, height); + to_pixel_space(cb->marker_pat, pat_dim, width, height); + to_pixel_space(cb->marker_search, search_dim, width, height); + to_pixel_space(cb->marker_search_pos, search_pos, width, height); to_pixel_space(cb->track_offset, track->offset, width, height); cb->marker_flag = marker->flag; @@ -447,19 +452,19 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P -10*height, 10.0*height, step, digits, "Y-offset to parenting point"); uiDefBut(block, LABEL, 0, "Pattern Area:", 0, 114, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->track_pat[0], 3.0f, + uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->marker_pat[0], 3.0f, 10.0*width, step, digits, "Width of marker's pattern in screen coordinates"); - uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->track_pat[1], 3.0f, + uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->marker_pat[1], 3.0f, 10.0*height, step, digits, "Height of marker's pattern in screen coordinates"); uiDefBut(block, LABEL, 0, "Search Area:", 0, 57, 300, 19, NULL, 0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->track_search_pos[0], + uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->marker_search_pos[0], -width, width, step, digits, "X-position of search at frame relative to marker's position"); - uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->track_search_pos[1], + uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->marker_search_pos[1], -height, height, step, digits, "X-position of search at frame relative to marker's position"); - uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->track_search[0], 3.0f, + uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->marker_search[0], 3.0f, 10.0*width, step, digits, "Width of marker's search in screen soordinates"); - uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->track_search[1], 3.0f, + uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->marker_search[1], 3.0f, 10.0*height, step, digits, "Height of marker's search in screen soordinates"); uiBlockEndAlign(block); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 93a32fb06fc..9332413b33b 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -456,14 +456,17 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT if ((marker->flag & MARKER_DISABLED) == 0) { float pos[2]; - rctf r; + float p[2]; - BLI_init_rctf(&r, track->pat_min[0], track->pat_max[0], track->pat_min[1], track->pat_max[1]); add_v2_v2v2(pos, marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, pos, pos); - if (BLI_in_rctf(&r, pos[0] - marker_pos[0], pos[1] - marker_pos[1])) { + sub_v2_v2v2(p, pos, marker_pos); + + if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1], + marker->pattern_corners[2], marker->pattern_corners[3])) + { if (tiny) glPointSize(3.0f); else glPointSize(4.0f); glBegin(GL_POINTS); @@ -499,10 +502,10 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT if (sc->flag & SC_SHOW_MARKER_PATTERN) { glBegin(GL_LINE_LOOP); - glVertex2f(track->pat_min[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_max[1]); - glVertex2f(track->pat_min[0], track->pat_max[1]); + glVertex2fv(marker->pattern_corners[0]); + glVertex2fv(marker->pattern_corners[1]); + glVertex2fv(marker->pattern_corners[2]); + glVertex2fv(marker->pattern_corners[3]); glEnd(); } @@ -510,10 +513,10 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0); if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) { glBegin(GL_LINE_LOOP); - glVertex2f(track->search_min[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_max[1]); - glVertex2f(track->search_min[0], track->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_max[1]); glEnd(); } glPopMatrix(); @@ -556,8 +559,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra /* marker position and offset position */ if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) { - float pos[2]; - rctf r; + float pos[2], p[2]; if (track->flag & TRACK_LOCKED) { if (act) @@ -574,11 +576,14 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra glColor3fv(col); } - BLI_init_rctf(&r, track->pat_min[0], track->pat_max[0], track->pat_min[1], track->pat_max[1]); add_v2_v2v2(pos, marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, pos, pos); - if (BLI_in_rctf(&r, pos[0] - marker_pos[0], pos[1] - marker_pos[1])) { + sub_v2_v2v2(p, pos, marker_pos); + + if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1], + marker->pattern_corners[2], marker->pattern_corners[3])) + { if (!tiny) glPointSize(2.0f); @@ -651,10 +656,10 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } glBegin(GL_LINE_LOOP); - glVertex2f(track->pat_min[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_max[1]); - glVertex2f(track->pat_min[0], track->pat_max[1]); + glVertex2fv(marker->pattern_corners[0]); + glVertex2fv(marker->pattern_corners[1]); + glVertex2fv(marker->pattern_corners[2]); + glVertex2fv(marker->pattern_corners[3]); glEnd(); } @@ -684,70 +689,82 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } glBegin(GL_LINE_LOOP); - glVertex2f(track->search_min[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_min[1]); - glVertex2f(track->search_max[0], track->search_max[1]); - glVertex2f(track->search_min[0], track->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_min[1]); + glVertex2f(marker->search_max[0], marker->search_max[1]); + glVertex2f(marker->search_min[0], marker->search_max[1]); glEnd(); } - /* pyramid */ - if (sel && TRACK_VIEW_SELECTED(sc, track) && - (track->tracker == TRACKER_KLT) && - (marker->flag & MARKER_DISABLED) == 0) - { - if (track->flag & TRACK_LOCKED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->pat_flag & SELECT) - UI_ThemeColorShade(TH_LOCK_MARKER, 64); - else UI_ThemeColor(TH_LOCK_MARKER); - } - else if (marker->flag & MARKER_DISABLED) { - if (act) - UI_ThemeColor(TH_ACT_MARKER); - else if (track->pat_flag & SELECT) - UI_ThemeColorShade(TH_DIS_MARKER, 128); - else UI_ThemeColor(TH_DIS_MARKER); - } - else { - if (track->pat_flag & SELECT) - glColor3fv(scol); - else - glColor3fv(col); - } - - { - int i = 0; - glPushMatrix(); - glEnable(GL_LINE_STIPPLE); - for (i = 1; i < track->pyramid_levels; ++i) { - glScalef(2.0f, 2.0f, 1.0); - } - /* only draw a pattern for the coarsest level */ - glBegin(GL_LINE_LOOP); - glVertex2f(track->pat_min[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_min[1]); - glVertex2f(track->pat_max[0], track->pat_max[1]); - glVertex2f(track->pat_min[0], track->pat_max[1]); - glEnd(); - glDisable(GL_LINE_STIPPLE); - glPopMatrix(); - } - } - if (tiny) glDisable(GL_LINE_STIPPLE); glPopMatrix(); } +static float get_shortest_pattern_side(MovieTrackingMarker *marker) +{ + int i, next; + float len = FLT_MAX; + + for (i = 0; i < 4; i++) { + float cur_len; + + next = (i + 1) % 4; + + cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); + + len = MIN2(cur_len, len); + } + + return len; +} + +static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2]) +{ + float tdx, tdy; + + tdx = dx; + tdy = dy; + + if (outline) { + tdx += px[0]; + tdy += px[1]; + } + + glBegin(GL_QUADS); + glVertex3f(x - tdx, y + tdy, 0.0f); + glVertex3f(x + tdx, y + tdy, 0.0f); + glVertex3f(x + tdx, y - tdy, 0.0f); + glVertex3f(x - tdx, y - tdy, 0.0f); + glEnd(); +} + +static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2]) +{ + float tdx, tdy; + + tdx = dx * 2.0f; + tdy = dy * 2.0f; + + if (outline) { + tdx += px[0]; + tdy += px[1]; + } + + glBegin(GL_TRIANGLES); + glVertex3f(x, y, 0.0f); + glVertex3f(x - tdx, y, 0.0f); + glVertex3f(x, y + tdy, 0.0f); + glEnd(); +} + static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, float marker_pos[2], int outline, int sel, int act, int width, int height) { - float x, y, dx, dy, patdx, patdy, searchdx, searchdy, tdx, tdy; + float dx, dy, patdx, patdy, searchdx, searchdy; int tiny = sc->flag & SC_SHOW_TINY_MARKER; - float col[3], scol[3], px[2]; + float col[3], scol[3], px[2], side; if ((tiny && outline) || (marker->flag & MARKER_DISABLED)) return; @@ -768,11 +785,12 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo dx = 6.0f / width / sc->zoom; dy = 6.0f / height / sc->zoom; - patdx = MIN2(dx * 2.0f / 3.0f, (track->pat_max[0] - track->pat_min[0]) / 6.0f); - patdy = MIN2(dy * 2.0f / 3.0f, (track->pat_max[1] - track->pat_min[1]) / 6.0f); + side = get_shortest_pattern_side(marker); + patdx = MIN2(dx * 2.0f / 3.0f, side / 6.0f); + patdy = MIN2(dy * 2.0f / 3.0f, side * width / height / 6.0f); - searchdx = MIN2(dx, (track->search_max[0] - track->search_min[0]) / 6.0f); - searchdy = MIN2(dy, (track->search_max[1] - track->search_min[1]) / 6.0f); + searchdx = MIN2(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f); + searchdy = MIN2(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f); px[0] = 1.0f / sc->zoom / width / sc->scale; px[1] = 1.0f / sc->zoom / height / sc->scale; @@ -786,41 +804,10 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo } /* search offset square */ - x = track->search_min[0]; - y = track->search_max[1]; - - tdx = searchdx; - tdy = searchdy; - - if (outline) { - tdx += px[0]; - tdy += px[1]; - } - - glBegin(GL_QUADS); - glVertex3f(x - tdx, y + tdy, 0); - glVertex3f(x + tdx, y + tdy, 0); - glVertex3f(x + tdx, y - tdy, 0); - glVertex3f(x - tdx, y - tdy, 0); - glEnd(); + draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px); /* search re-sizing triangle */ - x = track->search_max[0]; - y = track->search_min[1]; - - tdx = searchdx * 2.0f; - tdy = searchdy * 2.0f; - - if (outline) { - tdx += px[0]; - tdy += px[1]; - } - - glBegin(GL_TRIANGLES); - glVertex3f(x, y, 0); - glVertex3f(x - tdx, y, 0); - glVertex3f(x, y + tdy, 0); - glEnd(); + draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px); } if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) { @@ -831,42 +818,26 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo glColor3fv(col); } - /* pattern offset square */ - x = track->pat_min[0]; - y = track->pat_max[1]; + /* XXX: need to be real check if affine tracking is enabled, but for now not + * sure how to do this, so assume affine tracker is always enabled */ + if (TRUE) { + int i; - tdx = patdx; - tdy = patdy; - - if (outline) { - tdx += px[0]; - tdy += px[1]; + /* pattern's corners sliding squares */ + for (i = 0; i < 4; i++) { + draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1], + patdx / 1.5f, patdy / 1.5f, outline, px); + } } + else { + /* pattern offset square */ + draw_marker_slide_square(marker->pattern_corners[3][0], marker->pattern_corners[3][1], + patdx, patdy, outline, px); - glBegin(GL_QUADS); - glVertex3f(x - tdx, y + tdy, 0); - glVertex3f(x + tdx, y + tdy, 0); - glVertex3f(x + tdx, y - tdy, 0); - glVertex3f(x - tdx, y - tdy, 0); - glEnd(); - - /* pattern re-sizing triangle */ - x = track->pat_max[0]; - y = track->pat_min[1]; - - tdx = patdx*2.0f; - tdy = patdy*2.0f; - - if (outline) { - tdx += px[0]; - tdy += px[1]; + /* pattern re-sizing triangle */ + draw_marker_slide_triangle(marker->pattern_corners[1][0], marker->pattern_corners[1][1], + patdx, patdy, outline, px); } - - glBegin(GL_TRIANGLES); - glVertex3f(x, y, 0); - glVertex3f(x - tdx, y, 0); - glVertex3f(x, y + tdy, 0); - glEnd(); } glPopMatrix(); @@ -905,12 +876,15 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) { - dx = track->search_min[0]; - dy = track->search_min[1]; + dx = marker->search_min[0]; + dy = marker->search_min[1]; } else if (sc->flag & SC_SHOW_MARKER_PATTERN) { - dx = track->pat_min[0]; - dy = track->pat_min[1]; + float pat_min[2], pat_max[2]; + + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + dx = pat_min[0]; + dy = pat_min[1]; } pos[0] = (marker_pos[0] + dx) * width; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a49319abd20..54724881e37 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -306,6 +306,9 @@ static void clip_free(SpaceLink *sl) if (sc->scopes.track_preview) IMB_freeImBuf(sc->scopes.track_preview); + if (sc->scopes.track_search) + IMB_freeImBuf(sc->scopes.track_search); + ED_space_clip_free_texture_buffer(sc); } @@ -323,6 +326,7 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) SpaceClip *scn = MEM_dupallocN(sl); /* clear or remove stuff from old */ + scn->scopes.track_search = NULL; scn->scopes.track_preview = NULL; scn->scopes.ok = FALSE; scn->draw_context = NULL; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 08fc84d193c..f6e9622f0a5 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -79,6 +79,8 @@ #include "clip_intern.h" // own include +static float dist_to_crns(float co[2], float pos[2], float crns[4][2]); + /********************** add marker operator *********************/ static void add_marker(SpaceClip *sc, float x, float y) @@ -260,15 +262,16 @@ typedef struct { int mval[2]; int width, height; - float *min, *max, *pos, *offset; - float smin[2], smax[2], spos[2], soff[2]; + float *min, *max, *pos, *offset, (*corners)[2]; + float smin[2], smax[2], spos[2], soff[2], scorners[4][2]; float (*smarkers)[2]; - int lock, accurate; + int lock, accurate, scale; } SlideMarkerData; static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTrack *track, - MovieTrackingMarker *marker, wmEvent *event, int area, int action, int width, int height) + MovieTrackingMarker *marker, wmEvent *event, + int area, int corner, int action, int width, int height) { SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data"); int framenr = ED_space_clip_clip_framenr(sc); @@ -288,10 +291,9 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra } else if (area == TRACK_AREA_PAT) { if (action == SLIDE_ACTION_SIZE) { - data->min = track->pat_min; - data->max = track->pat_max; + data->corners = marker->pattern_corners; } - else { + else if (action == SLIDE_ACTION_OFFSET) { int a; data->pos = marker->pos; @@ -303,15 +305,28 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra for (a = 0; a < track->markersnr; a++) copy_v2_v2(data->smarkers[a], track->markers[a].pos); } + else if (action == SLIDE_ACTION_POS) { + data->corners = marker->pattern_corners; + data->pos = marker->pattern_corners[corner]; + + copy_v2_v2(data->spos, data->pos); + } } else if (area == TRACK_AREA_SEARCH) { - data->min = track->search_min; - data->max = track->search_max; + data->min = marker->search_min; + data->max = marker->search_max; } - if (area == TRACK_AREA_SEARCH || (area == TRACK_AREA_PAT && action != SLIDE_ACTION_OFFSET)) { - copy_v2_v2(data->smin, data->min); - copy_v2_v2(data->smax, data->max); + if ((area == TRACK_AREA_SEARCH) || + (area == TRACK_AREA_PAT && action != SLIDE_ACTION_OFFSET)) + { + if (data->corners) { + memcpy(data->scorners, data->corners, sizeof(data->scorners)); + } + else { + copy_v2_v2(data->smin, data->min); + copy_v2_v2(data->smax, data->max); + } } data->mval[0] = event->mval[0]; @@ -326,9 +341,7 @@ static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTra return data; } -/* corner = 0: right-bottom corner, - * corner = 1: left-top corner */ -static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, +static int mouse_on_corner(SpaceClip *sc, MovieTrackingMarker *marker, int area, float co[2], int corner, int width, int height) { int inside = 0; @@ -337,12 +350,11 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki float crn[2], dx, dy, tdx, tdy; if (area == TRACK_AREA_SEARCH) { - copy_v2_v2(min, track->search_min); - copy_v2_v2(max, track->search_max); + copy_v2_v2(min, marker->search_min); + copy_v2_v2(max, marker->search_max); } else { - copy_v2_v2(min, track->pat_min); - copy_v2_v2(max, track->pat_max); + BKE_tracking_marker_pattern_minmax(marker, min, max); } dx = size / width / sc->zoom; @@ -370,22 +382,95 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki return inside; } +static int get_mouse_pattern_corner(SpaceClip *sc, MovieTrackingMarker *marker, float co[2], int width, int height) +{ + int i, next; + float len = FLT_MAX, dx, dy; + + for (i = 0; i < 4; i++) { + float cur_len; + + next = (i + 1) % 4; + + cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); + + len = MIN2(cur_len, len); + } + + dx = 6.0f / width / sc->zoom; + dy = 6.0f / height / sc->zoom; + + dx = MIN2(dx * 2.0f / 3.0f, len / 6.0f); + dy = MIN2(dy * 2.0f / 3.0f, len * width / height / 6.0f); + + for (i = 0; i < 4; i++) { + float crn[2]; + int inside; + + add_v2_v2v2(crn, marker->pattern_corners[i], marker->pos); + + inside = IN_RANGE_INCL(co[0], crn[0] - dx, crn[0] + dx) && + IN_RANGE_INCL(co[1], crn[1] - dy, crn[1] + dy); + + if (inside) + return i; + } + + return -1; +} + static int mouse_on_offset(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, - float co[2], int width, int height) + float co[2], int width, int height) { float pos[2], dx, dy; + float pat_min[2], pat_max[2]; + + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); add_v2_v2v2(pos, marker->pos, track->offset); dx = 12.0f / width / sc->zoom; dy = 12.0f / height / sc->zoom; - dx = MIN2(dx, (track->pat_max[0] - track->pat_min[0]) / 2.0f); - dy = MIN2(dy, (track->pat_max[1] - track->pat_min[1]) / 2.0f); + dx = MIN2(dx, (pat_max[0] - pat_min[0]) / 2.0f); + dy = MIN2(dy, (pat_max[1] - pat_min[1]) / 2.0f); return co[0] >= pos[0] - dx && co[0] <= pos[0] + dx && co[1] >= pos[1] - dy && co[1] <= pos[1] + dy; } +static int slide_check_corners(float (*corners)[2]) +{ + int i, next, prev; + float cross = 0.0f; + float p[2] = {0.0f, 0.0f}; + + if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3])) + return FALSE; + + for (i = 0; i < 4; i++) { + float v1[2], v2[2], cur_cross; + + next = (i + 1) % 4; + prev = (4 + i - 1) % 4; + + sub_v2_v2v2(v1, corners[i], corners[prev]); + sub_v2_v2v2(v2, corners[next], corners[i]); + + cur_cross = cross_v2v2(v1, v2); + + if (fabsf(cur_cross) > FLT_EPSILON) { + if (cross == 0.0f) { + cross = cur_cross; + } + else if (cross * cur_cross < 0.0f) { + return FALSE; + } + } + } + + return TRUE; +} + static void hide_cursor(bContext *C) { wmWindow *win = CTX_wm_window(C); @@ -424,28 +509,45 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) { - if (!customdata) + if (!customdata) { if (mouse_on_offset(sc, track, marker, co, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_POINT, + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_POINT, 0, SLIDE_ACTION_POS, width, height); + } if (sc->flag & SC_SHOW_MARKER_SEARCH) { - if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 1, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, + if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 1, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0, SLIDE_ACTION_OFFSET, width, height); - else if (mouse_on_corner(sc, track, marker, TRACK_AREA_SEARCH, co, 0, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, + } + else if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 0, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_SEARCH, 0, SLIDE_ACTION_SIZE, width, height); + } } if (!customdata && (sc->flag & SC_SHOW_MARKER_PATTERN)) { - if (mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 1, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, - SLIDE_ACTION_OFFSET, width, height); - - if (!customdata && mouse_on_corner(sc, track, marker, TRACK_AREA_PAT, co, 0, width, height)) - customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, - SLIDE_ACTION_SIZE, width, height); + /* XXX: need to be real check if affine tracking is enabled, but for now not + * sure how to do this, so assume affine tracker is always enabled */ + if (TRUE) { + int corner = get_mouse_pattern_corner(sc, marker, co, width, height); + + if (corner != -1) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, corner, + SLIDE_ACTION_POS, width, height); + } + } + else { + if (mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 1, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0, + SLIDE_ACTION_OFFSET, width, height); + } + + if (!customdata && mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 0, width, height)) { + customdata = create_slide_marker_data(sc, track, marker, event, TRACK_AREA_PAT, 0, + SLIDE_ACTION_SIZE, width, height); + } + } } if (customdata) @@ -493,9 +595,16 @@ static void cancel_mouse_slide(SlideMarkerData *data) copy_v2_v2(data->pos, data->spos); } else { - if (data->action == SLIDE_ACTION_SIZE) { - copy_v2_v2(data->min, data->smin); - copy_v2_v2(data->max, data->smax); + if ((data->action == SLIDE_ACTION_SIZE) || + (data->action == SLIDE_ACTION_POS && data->area == TRACK_AREA_PAT)) + { + if (data->corners) { + memcpy(data->corners, data->scorners, sizeof(data->scorners)); + } + else { + copy_v2_v2(data->min, data->smin); + copy_v2_v2(data->max, data->smax); + } } else { int a; @@ -531,6 +640,10 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) data->lock = event->val == KM_RELEASE; + if (data->action == SLIDE_ACTION_POS) + if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) + data->scale = event->val == KM_PRESS; + if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) data->accurate = event->val == KM_PRESS; @@ -560,8 +673,6 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) else { data->pos[0] = data->spos[0] + dx; data->pos[1] = data->spos[1] + dy; - - data->marker->flag &= ~MARKER_TRACKED; } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -569,18 +680,33 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } else { if (data->action == SLIDE_ACTION_SIZE) { - data->min[0] = data->smin[0] - dx; - data->max[0] = data->smax[0] + dx; + if (data->corners) { + data->corners[0][0] = data->scorners[0][0] - dx; + data->corners[0][1] = data->scorners[0][1] + dy; + + data->corners[1][0] = data->scorners[1][0] + dx; + data->corners[1][1] = data->scorners[1][1] + dy; - data->min[1] = data->smin[1] + dy; - data->max[1] = data->smax[1] - dy; + data->corners[2][0] = data->scorners[2][0] + dx; + data->corners[2][1] = data->scorners[2][1] - dy; + + data->corners[3][0] = data->scorners[3][0] - dx; + data->corners[3][1] = data->scorners[3][1] - dy; + } + else { + data->min[0] = data->smin[0] - dx; + data->max[0] = data->smax[0] + dx; + + data->min[1] = data->smin[1] + dy; + data->max[1] = data->smax[1] - dy; + } if (data->area == TRACK_AREA_SEARCH) - BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_DIM); + BKE_tracking_clamp_marker(data->marker, CLAMP_SEARCH_DIM); else - BKE_tracking_clamp_track(data->track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(data->marker, CLAMP_PAT_DIM); } - else { + else if (data->action == SLIDE_ACTION_OFFSET) { float d[2] = {dx, dy}; if (data->area == TRACK_AREA_SEARCH) { @@ -597,10 +723,43 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) } if (data->area == TRACK_AREA_SEARCH) - BKE_tracking_clamp_track(data->track, CLAMP_SEARCH_POS); + BKE_tracking_clamp_marker(data->marker, CLAMP_SEARCH_POS); + } + else if (data->action == SLIDE_ACTION_POS) { + if (data->scale) { + float scale = 1.0f + 10.0f * (dx - dy); + + if (scale > 0.0f) { + int a; + + for (a = 0; a < 4; a++) { + mul_v2_v2fl(data->corners[a], data->scorners[a], scale); + } + } + } + else { + float spos[2]; + + copy_v2_v2(spos, data->pos); + + /* corners might've been scaled before, restore their original position */ + memcpy(data->corners, data->scorners, sizeof(data->scorners)); + + data->pos[0] = data->spos[0] + dx; + data->pos[1] = data->spos[1] + dy; + + if (!slide_check_corners(data->corners)) { + copy_v2_v2(data->pos, spos); + } + } + + /* currently only patterns are allowed to have such combination of event and data */ + BKE_tracking_clamp_marker(data->marker, CLAMP_PAT_DIM); } } + data->marker->flag &= ~MARKER_TRACKED; + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); break; @@ -673,31 +832,41 @@ static int mouse_on_rect(float co[2], float pos[2], float min[2], float max[2], mouse_on_side(co, pos[0] + max[0], pos[1] + min[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy); } +static int mouse_on_crns(float co[2], float pos[2], float crns[4][2], float epsx, float epsy) +{ + float dist = dist_to_crns(co, pos, crns); + + return dist < MAX2(epsx, epsy); +} + static int track_mouse_area(SpaceClip *sc, float co[2], MovieTrackingTrack *track) { int framenr = ED_space_clip_clip_framenr(sc); MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + float pat_min[2], pat_max[2]; float epsx, epsy; int width, height; ED_space_clip_size(sc, &width, &height); - epsx = MIN4(track->pat_min[0] - track->search_min[0], track->search_max[0] - track->pat_max[0], - fabsf(track->pat_min[0]), fabsf(track->pat_max[0])) / 2; - epsy = MIN4(track->pat_min[1] - track->search_min[1], track->search_max[1] - track->pat_max[1], - fabsf(track->pat_min[1]), fabsf(track->pat_max[1])) / 2; + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + epsx = MIN4(pat_min[0] - marker->search_min[0], marker->search_max[0] - pat_max[0], + fabsf(pat_min[0]), fabsf(pat_max[0])) / 2; + epsy = MIN4(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1], + fabsf(pat_min[1]), fabsf(pat_max[1])) / 2; epsx = MAX2(epsx, 2.0f / width); epsy = MAX2(epsy, 2.0f / height); if (sc->flag & SC_SHOW_MARKER_SEARCH) { - if (mouse_on_rect(co, marker->pos, track->search_min, track->search_max, epsx, epsy)) + if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy)) return TRACK_AREA_SEARCH; } if ((marker->flag & MARKER_DISABLED) == 0) { if (sc->flag & SC_SHOW_MARKER_PATTERN) - if (mouse_on_rect(co, marker->pos, track->pat_min, track->pat_max, epsx, epsy)) + if (mouse_on_crns(co, marker->pos, marker->pattern_corners, epsx, epsy)) return TRACK_AREA_PAT; epsx = 12.0f / width; @@ -728,6 +897,21 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2]) return MIN4(d1, d2, d3, d4); } +static float dist_to_crns(float co[2], float pos[2], float crns[4][2]) +{ + float d1, d2, d3, d4; + float p[2] = {co[0] - pos[0], co[1] - pos[1]}; + float *v1 = crns[0], *v2 = crns[1], + *v3 = crns[2], *v4 = crns[3]; + + d1 = dist_to_line_segment_v2(p, v1, v2); + d2 = dist_to_line_segment_v2(p, v2, v3); + d3 = dist_to_line_segment_v2(p, v3, v4); + d4 = dist_to_line_segment_v2(p, v4, v1); + + return MIN4(d1, d2, d3, d4); +} + static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2]) { MovieTrackingTrack *track = NULL, *cur; @@ -743,15 +927,15 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas /* distance to marker point */ d1 = sqrtf((co[0] - marker->pos[0] - cur->offset[0]) * (co[0] - marker->pos[0] - cur->offset[0]) + - (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1])); + (co[1] - marker->pos[1] - cur->offset[1]) * (co[1] - marker->pos[1] - cur->offset[1])); /* distance to pattern boundbox */ if (sc->flag & SC_SHOW_MARKER_PATTERN) - d2 = dist_to_rect(co, marker->pos, cur->pat_min, cur->pat_max); + d2 = dist_to_crns(co, marker->pos, marker->pattern_corners); /* distance to search boundbox */ if (sc->flag & SC_SHOW_MARKER_SEARCH && TRACK_VIEW_SELECTED(sc, cur)) - d3 = dist_to_rect(co, marker->pos, cur->search_min, cur->search_max); + d3 = dist_to_rect(co, marker->pos, marker->search_min, marker->search_max); /* choose minimal distance. useful for cases of overlapped markers. */ dist = MIN3(d1, d2, d3); @@ -861,7 +1045,8 @@ void CLIP_OT_select(wmOperatorType *ot) /* api callbacks */ ot->exec = select_exec; ot->invoke = select_invoke; - ot->poll = ED_space_clip_tracking_poll; + //ot->poll = ED_space_clip_tracking_poll; // so mask view can Ctrl+RMB markers + ot->poll = ED_space_clip_view_clip_poll; /* flags */ ot->flag = OPTYPE_UNDO; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ea86083fac4..d41294c7875 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -815,6 +815,14 @@ int transformEvent(TransInfo *t, wmEvent *event) initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; } + else if (t->mode == TFM_RESIZE) { + if (t->options & CTX_MOVIECLIP) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } + } break; case TFM_MODAL_SNAP_INV_ON: @@ -2730,6 +2738,9 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { copy_v3_v3(center, td->center); } + else if (t->options & CTX_MOVIECLIP) { + copy_v3_v3(center, td->center); + } else { copy_v3_v3(center, t->center); } @@ -3103,6 +3114,10 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short { center = td->center; } + + if (t->options & CTX_MOVIECLIP) { + center = td->center; + } } if (t->flag & T_POINTS) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ce65127c896..007ec3c5250 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5588,23 +5588,24 @@ typedef struct TransDataTracking { short coord; } TransDataTracking; -static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, MovieTrackingTrack *track, - int area, float loc[2], float rel[2], const float off[2]) +static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, + MovieTrackingTrack *track, MovieTrackingMarker *marker, + int area, float loc[2], float rel[2], const float off[2], float aspx, float aspy) { int anchor = area == TRACK_AREA_POINT && off; tdt->mode = transDataTracking_ModeTracks; if (anchor) { - td2d->loc[0] = rel[0]; /* hold original location */ - td2d->loc[1] = rel[1]; + td2d->loc[0] = rel[0] * aspx; /* hold original location */ + td2d->loc[1] = rel[1] * aspy; tdt->loc= loc; td2d->loc2d = loc; /* current location */ } else { - td2d->loc[0] = loc[0]; /* hold original location */ - td2d->loc[1] = loc[1]; + td2d->loc[0] = loc[0] * aspx; /* hold original location */ + td2d->loc[1] = loc[1] * aspy; td2d->loc2d = loc; /* current location */ } @@ -5618,8 +5619,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra if (rel) { if (!anchor) { - td2d->loc[0] += rel[0]; - td2d->loc[1] += rel[1]; + td2d->loc[0] += rel[0] * aspx; + td2d->loc[1] += rel[1] * aspy; } copy_v2_v2(tdt->srelative, rel); @@ -5630,9 +5631,12 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra td->flag = 0; td->loc = td2d->loc; - copy_v3_v3(td->center, td->loc); copy_v3_v3(td->iloc, td->loc); + //copy_v3_v3(td->center, td->loc); + td->center[0] = marker->pos[0] * aspx; + td->center[1] = marker->pos[1] * aspy; + memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; @@ -5647,27 +5651,37 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra } static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, - TransDataTracking *tdt, MovieTrackingTrack *track) + TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy) { int framenr = ED_space_clip_clip_framenr(sc); MovieTrackingMarker *marker = BKE_tracking_ensure_marker(track, framenr); tdt->flag = marker->flag; - marker->flag &= ~(MARKER_DISABLED|MARKER_TRACKED); + marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, track->offset, marker->pos, track->offset); + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, + track->offset, marker->pos, track->offset, aspx, aspy); - if (track->flag & SELECT) - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, marker->pos, NULL, NULL); + if (track->flag & SELECT) { + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, + marker->pos, NULL, NULL, aspx, aspy); + } if (track->pat_flag & SELECT) { - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_min, marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_PAT, track->pat_max, marker->pos, NULL); + int a; + + for (a = 0; a < 4; a++) { + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT, + marker->pattern_corners[a], marker->pos, NULL, aspx, aspy); + } } if (track->search_flag & SELECT) { - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_min, marker->pos, NULL); - markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_SEARCH, track->search_max, marker->pos, NULL); + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, + marker->search_min, marker->pos, NULL, aspx, aspy); + + markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH, + marker->search_max, marker->pos, NULL, aspx, aspy); } } @@ -5694,6 +5708,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) MovieTrackingMarker *marker; TransDataTracking *tdt; int framenr = ED_space_clip_clip_framenr(sc); + float aspx, aspy; /* count */ t->total = 0; @@ -5709,7 +5724,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) t->total++; if (track->pat_flag & SELECT) - t->total+= 2; + t->total+= 4; if (track->search_flag & SELECT) t->total+= 2; @@ -5721,6 +5736,8 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) if (t->total == 0) return; + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); + td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransTracking TransData"); td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransTracking TransData2D"); tdt = t->customData = MEM_callocN(t->total*sizeof(TransDataTracking), "TransTracking TransDataTracking"); @@ -5733,25 +5750,23 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { marker = BKE_tracking_get_marker(track, framenr); - trackToTransData(sc, td, td2d, tdt, track); + trackToTransData(sc, td, td2d, tdt, track, aspx, aspy); /* offset */ td++; td2d++; tdt++; - if ((marker->flag & MARKER_DISABLED) == 0) { - if (track->flag & SELECT) { - td++; - td2d++; - tdt++; - } + if (track->flag & SELECT) { + td++; + td2d++; + tdt++; + } - if (track->pat_flag & SELECT) { - td += 2; - td2d += 2; - tdt +=2; - } + if (track->pat_flag & SELECT) { + td += 4; + td2d += 4; + tdt += 4; } if (track->search_flag & SELECT) { @@ -5903,9 +5918,6 @@ static void createTransTrackingData(bContext *C, TransInfo *t) if (!clip || width == 0 || height == 0) return; - if (!ELEM(t->mode, TFM_RESIZE, TFM_TRANSLATION)) - return; - if (ar->regiontype == RGN_TYPE_PREVIEW) { /* transformation was called from graph editor */ createTransTrackingCurvesData(C, t); @@ -5973,10 +5985,14 @@ static void cancelTransTracking(TransInfo *t) void flushTransTracking(TransInfo *t) { + SpaceClip *sc = t->sa->spacedata.first; TransData *td; TransData2D *td2d; TransDataTracking *tdt; int a; + float aspx, aspy; + + ED_space_clip_aspect_dimension_aware(sc, &aspx, &aspy); if (t->state == TRANS_CANCEL) cancelTransTracking(t); @@ -5984,31 +6000,46 @@ void flushTransTracking(TransInfo *t) /* flush to 2d vector from internally used 3d vector */ for (a=0, td= t->data, td2d= t->data2d, tdt= t->customData; atotal; a++, td2d++, td++, tdt++) { if (tdt->mode == transDataTracking_ModeTracks) { - if (t->flag & T_ALT_TRANSFORM) { - if (tdt->area == TRACK_AREA_POINT && tdt->relative) { - float d[2], d2[2]; + float loc2d[2]; - if (!tdt->smarkers) { - tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); - for (a = 0; a < tdt->markersnr; a++) - copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); - } + if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) { + continue; + } + + loc2d[0] = td2d->loc[0] / aspx; + loc2d[1] = td2d->loc[1] / aspy; + + if (t->flag & T_ALT_TRANSFORM) { + if (t->mode == TFM_RESIZE) { + if (tdt->area != TRACK_AREA_PAT) + continue; + } + else if (t->mode == TFM_TRANSLATION) { + if (tdt->area == TRACK_AREA_POINT && tdt->relative) { + float d[2], d2[2]; + + if (!tdt->smarkers) { + tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); + for (a = 0; a < tdt->markersnr; a++) + copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); + } - sub_v2_v2v2(d, td2d->loc, tdt->soffset); - sub_v2_v2(d, tdt->srelative); + sub_v2_v2v2(d, loc2d, tdt->soffset); + sub_v2_v2(d, tdt->srelative); - sub_v2_v2v2(d2, td2d->loc, tdt->srelative); + sub_v2_v2v2(d2, loc2d, tdt->srelative); - for (a= 0; amarkersnr; a++) - add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); + for (a= 0; amarkersnr; a++) + add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); - negate_v2_v2(td2d->loc2d, d); + negate_v2_v2(td2d->loc2d, d); + } } } if (tdt->area!=TRACK_AREA_POINT || tdt->relative==0) { - td2d->loc2d[0] = td2d->loc[0]; - td2d->loc2d[1] = td2d->loc[1]; + td2d->loc2d[0] = loc2d[0]; + td2d->loc2d[1] = loc2d[1]; if (tdt->relative) sub_v2_v2(td2d->loc2d, tdt->relative); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e0920e323aa..1b8cc14ecac 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -643,23 +643,30 @@ static void recalcData_spaceclip(TransInfo *t) MovieClip *clip = ED_space_clip(sc); ListBase *tracksbase = BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; + int framenr = sc->user.framenr; flushTransTracking(t); track = tracksbase->first; while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + if (t->mode == TFM_TRANSLATION) { if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_POS); + BKE_tracking_clamp_marker(marker, CLAMP_PAT_POS); if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS); + BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_POS); } else if (t->mode == TFM_RESIZE) { if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); + BKE_tracking_clamp_marker(marker, CLAMP_PAT_DIM); if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)) - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); + BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_DIM); + } + else if (t->mode == TFM_ROTATION) { + if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) + BKE_tracking_clamp_marker(marker, CLAMP_PAT_POS); } } diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index e4c85309081..52b32ae66fc 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1025,6 +1025,7 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, OP_TRANSLATION, EVT_TWEAK_S, KM_ANY, 0, 0); WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, OP_ROTATION, RKEY, KM_PRESS, 0, 0); break; default: break; diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index fd7046854ff..b9d63167700 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -92,6 +92,9 @@ typedef struct MovieClip { typedef struct MovieClipScopes { int ok; /* 1 means scopes are ok and recalculation is unneeded */ int track_preview_height; /* height of track preview widget */ + int frame_width, frame_height; /* width and height of frame for which scopes are calculated */ + struct MovieTrackingMarker undist_marker; /* undistorted position of marker used for pattern sampling */ + struct ImBuf *track_search; /* search area of a track */ struct ImBuf *track_preview; /* ImBuf displayed in track preview */ float track_pos[2]; /* sub-pizel position of marker in track ImBuf */ short track_disabled; /* active track is disabled, special notifier should be drawn */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 823ecbbbba6..c5b0174a3c9 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -35,6 +35,7 @@ #ifndef __DNA_TRACKING_TYPES_H__ #define __DNA_TRACKING_TYPES_H__ +#include "DNA_defs.h" #include "DNA_listBase.h" /* match-moving data */ @@ -69,6 +70,27 @@ typedef struct MovieTrackingCamera { typedef struct MovieTrackingMarker { float pos[2]; /* 2d position of marker on frame (in unified 0..1 space) */ + + /* corners of pattern in the following order: + * + * Y + * ^ + * | (3) --- (2) + * | | | + * | | | + * | | | + * | (0) --- (1) + * +-------------> X + * + * the coordinates are stored relative to pos. + */ + float pattern_corners[4][2]; + + /* positions of left-bottom and right-top corners of search area (in unified 0..1 units, + * relative to marker->pos + */ + float search_min[2], search_max[2]; + int framenr; /* number of frame marker is associated with */ int flag; /* Marker's flag (alive, ...) */ } MovieTrackingMarker; @@ -79,8 +101,19 @@ typedef struct MovieTrackingTrack { char name[64]; /* MAX_NAME */ /* ** setings ** */ - float pat_min[2], pat_max[2]; /* positions of left-bottom and right-top corners of pattern (in unified 0..1 space) */ - float search_min[2], search_max[2]; /* positions of left-bottom and right-top corners of search area (in unified 0..1 space) */ + + /* positions of left-bottom and right-top corners of pattern (in unified 0..1 units, + * relative to marker->pos) + * moved to marker's corners since planar tracking implementation + */ + float pat_min[2] DNA_DEPRECATED, pat_max[2] DNA_DEPRECATED; + + /* positions of left-bottom and right-top corners of search area (in unified 0..1 units, + * relative to marker->pos + * moved to marker since affine tracking implementation + */ + float search_min[2] DNA_DEPRECATED, search_max[2] DNA_DEPRECATED; + float offset[2]; /* offset to "parenting" point */ /* ** track ** */ @@ -96,35 +129,32 @@ typedef struct MovieTrackingTrack { int flag, pat_flag, search_flag; /* flags (selection, ...) */ float color[3]; /* custom color for track */ - /* tracking algorithm to use; can be KLT or SAD */ + /* ** control how tracking happens */ short frames_limit; /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */ short margin; /* margin from frame boundaries */ short pattern_match; /* re-adjust every N frames */ - short tracker; /* tracking algorithm used for this track */ - - /* ** KLT tracker settings ** */ - short pyramid_levels, pad2; /* number of pyramid levels to use for KLT tracking */ - - /* ** SAD tracker settings ** */ + /* tracking parameters */ + short motion_model; /* model of the motion for this track */ + int algorithm_flag; /* flags for the tracking algorithm (use brute, use esm, use pyramid, etc */ float minimum_correlation; /* minimal correlation which is still treated as successful tracking */ - struct bGPdata *gpd; /* grease-pencil data */ + struct bGPdata *gpd; /* grease-pencil data */ } MovieTrackingTrack; typedef struct MovieTrackingSettings { int flag; /* ** default tracker settings */ - short default_tracker; /* tracking algorithm used by default */ - short default_pyramid_levels; /* number of pyramid levels to use for KLT tracking */ - float default_minimum_correlation; /* minimal correlation which is still treated as successful tracking */ - short default_pattern_size; /* size of pattern area for new tracks */ - short default_search_size; /* size of search area for new tracks */ - short default_frames_limit; /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */ - short default_margin; /* margin from frame boundaries */ - short default_pattern_match; /* re-adjust every N frames */ - short default_flag; /* default flags like color channels used by default */ + short default_motion_model; /* model of the motion for this track */ + short default_algorithm_flag; /* flags for the tracking algorithm (use brute, use esm, use pyramid, etc */ + float default_minimum_correlation; /* minimal correlation which is still treated as successful tracking */ + short default_pattern_size; /* size of pattern area for new tracks */ + short default_search_size; /* size of search area for new tracks */ + short default_frames_limit; /* number of frames to be tarcked during single tracking session (if TRACKING_FRAMES_LIMIT is set) */ + short default_margin; /* margin from frame boundaries */ + short default_pattern_match; /* re-adjust every N frames */ + short default_flag; /* default flags like color channels used by default */ short motion_flag; /* flags describes motion type */ @@ -258,10 +288,17 @@ enum { #define TRACK_PREVIEW_GRAYSCALE (1<<9) #define TRACK_DOPE_SEL (1<<10) -/* MovieTrackingTrack->tracker */ -#define TRACKER_KLT 0 -#define TRACKER_SAD 1 -#define TRACKER_HYBRID 2 +/* MovieTrackingTrack->motion_model */ +#define TRACK_MOTION_MODEL_TRANSLATION 0 +#define TRACK_MOTION_MODEL_TRANSLATION_ROTATION 1 +#define TRACK_MOTION_MODEL_TRANSLATION_SCALE 2 +#define TRACK_MOTION_MODEL_TRANSLATION_ROTATION_SCALE 3 +#define TRACK_MOTION_MODEL_AFFINE 4 +#define TRACK_MOTION_MODEL_HOMOGRAPHY 5 + +/* MovieTrackingTrack->algorithm_flag */ +#define TRACK_ALGORITHM_FLAG_USE_BRUTE 1 +#define TRACK_ALGORITHM_FLAG_USE_NORMALIZATION 2 /* MovieTrackingTrack->adjframes */ #define TRACK_MATCH_KEYFRAME 0 diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8fc39c95d81..bf02ae50a94 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -343,8 +343,10 @@ extern StructRNA RNA_MotionPathVert; extern StructRNA RNA_MouseSensor; extern StructRNA RNA_MovieSequence; extern StructRNA RNA_MovieClipSequence; +extern StructRNA RNA_MovieTracking; extern StructRNA RNA_MovieTrackingTrack; extern StructRNA RNA_MovieTrackingObject; +extern StructRNA RNA_MovieTrackingTrack; extern StructRNA RNA_MulticamSequence; extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 17940dfca92..aaa96fc4d95 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -59,20 +59,6 @@ static char *rna_tracking_path(PointerRNA *UNUSED(ptr)) return BLI_sprintfN("tracking"); } -static void rna_tracking_defaultSettings_levelsUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieClip *clip = (MovieClip*)ptr->id.data; - MovieTracking *tracking = &clip->tracking; - MovieTrackingSettings *settings = &tracking->settings; - - if (settings->default_tracker == TRACKER_KLT) { - int max_pyramid_level_factor = 1 << (settings->default_pyramid_levels - 1); - float search_ratio = 2.3f * max_pyramid_level_factor; - - settings->default_search_size = settings->default_pattern_size*search_ratio; - } -} - static void rna_tracking_defaultSettings_patternUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { MovieClip *clip = (MovieClip*)ptr->id.data; @@ -209,37 +195,6 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, int value) } } -static void rna_tracking_trackerPattern_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - BKE_tracking_clamp_track(track, CLAMP_PAT_DIM); -} - -static void rna_tracking_trackerSearch_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); -} - -static void rna_tracking_trackerAlgorithm_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - if (track->tracker == TRACKER_KLT) - BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); - else - BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM); -} - -static void rna_tracking_trackerPyramid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data; - - BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); -} - static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr)) { return BLI_sprintfN("tracking.camera"); @@ -413,6 +368,20 @@ static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value) } } +static void rna_tracking_markerPattern_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + MovieTrackingMarker *marker = (MovieTrackingMarker *)ptr->data; + + BKE_tracking_clamp_marker(marker, CLAMP_PAT_DIM); +} + +static void rna_tracking_markerSearch_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + MovieTrackingMarker *marker = (MovieTrackingMarker *)ptr->data; + + BKE_tracking_clamp_marker(marker, CLAMP_SEARCH_DIM); +} + /* API */ static void add_tracks_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, int frame, int number) @@ -498,11 +467,19 @@ void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int framenr) #else -static EnumPropertyItem tracker_items[] = { - {TRACKER_KLT, "KLT", 0, "KLT", - "Kanade–Lucas–Tomasi tracker which works with most of video clips, a bit slower than SAD"}, - {TRACKER_SAD, "SAD", 0, "SAD", "Sum of Absolute Differences tracker which can be used when KLT tracker fails"}, - {TRACKER_HYBRID, "Hybrid", 0, "Hybrid", "A hybrid tracker that uses SAD for rough tracking, KLT for refinement."}, +static EnumPropertyItem tracker_motion_model[] = { + {TRACK_MOTION_MODEL_HOMOGRAPHY, "Perspective", 0, "Perspective", + "Search for markers that are perspectively deformed (homography) between frames."}, + {TRACK_MOTION_MODEL_AFFINE, "Affine", 0, "Affine", + "Search for markers that are affine-deformed (t, r, k, and skew) between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION_ROTATION_SCALE, "LocRotScale", 0, "LocRotScale", + "Search for markers that are translated, rotated, and scaled between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION_SCALE, "LocScale", 0, "LocScale", + "Search for markers that are translated and scaled between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION_ROTATION, "LocRot", 0, "LocRot", + "Search for markers that are translated and rotated between frames."}, + {TRACK_MOTION_MODEL_TRANSLATION, "Loc", 0, "Loc", + "Search for markers that are translated between frames."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem pattern_match_items[] = { @@ -511,6 +488,7 @@ static EnumPropertyItem pattern_match_items[] = { {0, NULL, 0, NULL, NULL}}; static int rna_matrix_dimsize_4x4[] = {4, 4}; +static int rna_matrix_dimsize_4x2[] = {4, 2}; static void rna_def_trackingSettings(BlenderRNA *brna) { @@ -627,14 +605,14 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "motion_flag", TRACKING_MOTION_TRIPOD); RNA_def_property_ui_text(prop, "Tripod Motion", "Use special solver to track a stable camera position, such as a tripod"); - /* limit frames */ + /* default_limit_frames */ prop = RNA_def_property(srna, "default_frames_limit", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "default_frames_limit"); RNA_def_property_range(prop, 0, SHRT_MAX); RNA_def_property_ui_text(prop, "Frames Limit", "Every tracking cycle, this number of frames are tracked"); - /* pattern match */ + /* default_pattern_match */ prop = RNA_def_property(srna, "default_pattern_match", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_sdna(prop, NULL, "default_pattern_match"); @@ -642,40 +620,42 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pattern Match", "Track pattern from given frame when tracking marker to next frame"); - /* margin */ + /* default_margin */ prop = RNA_def_property(srna, "default_margin", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "default_margin"); RNA_def_property_range(prop, 0, 300); RNA_def_property_ui_text(prop, "Margin", "Default distance from image boudary at which marker stops tracking"); - /* tracking algorithm */ - prop = RNA_def_property(srna, "default_tracker", PROP_ENUM, PROP_NONE); + /* default_tracking_motion_model */ + prop = RNA_def_property(srna, "default_motion_model", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_enum_items(prop, tracker_items); - RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_levelsUpdate"); - RNA_def_property_ui_text(prop, "Tracker", "Default tracking algorithm to use"); + RNA_def_property_enum_items(prop, tracker_motion_model); + RNA_def_property_ui_text(prop, "Motion model", "Default motion model to use for tracking"); - /* pyramid level for pyramid klt tracking */ - prop = RNA_def_property(srna, "default_pyramid_levels", PROP_INT, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "default_pyramid_levels"); - RNA_def_property_range(prop, 1, 16); - RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_levelsUpdate"); - RNA_def_property_ui_text(prop, "Pyramid levels", "Default number of pyramid levels (increase on blurry footage)"); + /* use_brute */ + prop = RNA_def_property(srna, "default_use_brute", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); + RNA_def_property_ui_text(prop, "Prepass", "Use a brute-force translation-only initialization when tracking"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* minmal correlation - only used for SAD tracker */ + /* default use_normalization */ + prop = RNA_def_property(srna, "default_use_normalization", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); + RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); + + /* default minmal correlation */ prop = RNA_def_property(srna, "default_correlation_min", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_sdna(prop, NULL, "default_minimum_correlation"); - RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 3); RNA_def_property_ui_text(prop, "Correlation", - "Default minimal value of correlation between matched pattern and reference " - "which is still treated as successful tracking"); + "Default minimum value of correlation between matched pattern and reference " + "that is still treated as successful tracking"); /* default pattern size */ prop = RNA_def_property(srna, "default_pattern_size", PROP_INT, PROP_NONE); @@ -693,19 +673,19 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_searchUpdate"); RNA_def_property_ui_text(prop, "Search Size", "Size of search area for newly created tracks"); - /* use_red_channel */ + /* default use_red_channel */ prop = RNA_def_property(srna, "use_default_red_channel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_flag", TRACK_DISABLE_RED); RNA_def_property_ui_text(prop, "Use Red Channel", "Use red channel from footage for tracking"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* use_green_channel */ + /* default_use_green_channel */ prop = RNA_def_property(srna, "use_default_green_channel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_flag", TRACK_DISABLE_GREEN); RNA_def_property_ui_text(prop, "Use Green Channel", "Use green channel from footage for tracking"); RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); - /* use_blue_channel */ + /* default_use_blue_channel */ prop = RNA_def_property(srna, "use_default_blue_channel", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "default_flag", TRACK_DISABLE_BLUE); RNA_def_property_ui_text(prop, "Use Blue Channel", "Use blue channel from footage for tracking"); @@ -839,6 +819,38 @@ static void rna_def_trackingMarker(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MARKER_DISABLED); RNA_def_property_ui_text(prop, "Mode", "Is marker muted for current frame"); RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); + + /* pattern */ + prop = RNA_def_property(srna, "pattern_corners", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "pattern_corners"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_ui_text(prop, "Pattern Corners", + "Array of coordinates which represents patter's corners in " + " normalized coordinates relative to marker position"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_markerPattern_update"); + + /* search */ + prop = RNA_def_property(srna, "search_min", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_float_sdna(prop, NULL, "search_min"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Search Min", + "Left-bottom corner of search area in normalized coordinates relative " + "to marker position"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_markerSearch_update"); + + prop = RNA_def_property(srna, "search_max", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_float_sdna(prop, NULL, "search_max"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Search Max", + "Right-bottom corner of search area in normalized coordinates relative " + "to marker position"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_markerSearch_update"); } static void rna_def_trackingMarkers(BlenderRNA *brna, PropertyRNA *cprop) @@ -899,48 +911,6 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); RNA_def_struct_name_property(srna, prop); - /* Pattern */ - prop = RNA_def_property(srna, "pattern_min", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "pat_min"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Pattern Min", - "Left-bottom corner of pattern area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPattern_update"); - - prop = RNA_def_property(srna, "pattern_max", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "pat_max"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Pattern Max", - "Right-bottom corner of pattern area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPattern_update"); - - /* Search */ - prop = RNA_def_property(srna, "search_min", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "search_min"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Search Min", - "Left-bottom corner of search area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerSearch_update"); - - prop = RNA_def_property(srna, "search_max", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_array(prop, 2); - RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - RNA_def_property_float_sdna(prop, NULL, "search_max"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Search Max", - "Right-bottom corner of search area in normalized coordinates relative " - "to marker position"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerSearch_update"); - /* limit frames */ prop = RNA_def_property(srna, "frames_limit", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -966,32 +936,36 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_range(prop, 0, 300); RNA_def_property_ui_text(prop, "Margin", "Distance from image boudary at which marker stops tracking"); - /* tracking algorithm */ - prop = RNA_def_property(srna, "tracker", PROP_ENUM, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_enum_items(prop, tracker_items); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Tracker", "Tracking algorithm to use"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerAlgorithm_update"); - - /* pyramid level for pyramid klt tracking */ - prop = RNA_def_property(srna, "pyramid_levels", PROP_INT, PROP_NONE); + /* tracking motion model */ + prop = RNA_def_property(srna, "motion_model", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "pyramid_levels"); + RNA_def_property_enum_items(prop, tracker_motion_model); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_range(prop, 1, 16); - RNA_def_property_ui_text(prop, "Pyramid levels", "Number of pyramid levels (increase on blurry footage)"); - RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_tracking_trackerPyramid_update"); + RNA_def_property_ui_text(prop, "Motion model", "Default motion model to use for tracking"); - /* minmal correlation - only used for SAD tracker */ + /* minimum correlation */ prop = RNA_def_property(srna, "correlation_min", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_sdna(prop, NULL, "minimum_correlation"); - RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 3); RNA_def_property_ui_text(prop, "Correlation", "Minimal value of correlation between matched pattern and reference " - "which is still treated as successful tracking"); + "that is still treated as successful tracking"); + + /* use_brute */ + prop = RNA_def_property(srna, "use_brute", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_BRUTE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Prepass", "Use a brute-force translation only pre-track before refinement"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); + + /* use_brute */ + prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_NORMALIZATION); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Normalize", "Normalize light intensities while tracking. Slower"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); /* markers */ prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE); -- cgit v1.2.3 From 84b734a4df84afdc8702872f00dd89244815623e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 15:28:29 +0000 Subject: Commit patch from Stephan Kassemeyer sent to ML This patch aims to solve unaligned operation assert happens in Eigen library. This is short-term solution which in fact shall be reverted as soon as real solution would be added to Ceres. Meanwhile this should be acceptable to have for a while. --- extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h index 30cc5fc4a6c..84617c4fa06 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h @@ -136,6 +136,7 @@ class FixedArray { // and T must be the same, otherwise callers' assumptions about use // of this code will be broken. struct InnerContainer { + EIGEN_MAKE_ALIGNED_OPERATOR_NEW T element; }; -- cgit v1.2.3 From ff5875f1c19fad95349c8821a8fe5d02d111408c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 15:28:37 +0000 Subject: Bump subversion so iteration through all markers would happen only for old files which actually needs to be ported to 4 corners representation. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenloader/intern/readfile.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index db8fcd4a0d3..b833bc44201 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 263 -#define BLENDER_SUBVERSION 10 +#define BLENDER_SUBVERSION 11 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cd0bbb314eb..c727717dac8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7700,7 +7700,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - { + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 11)) { MovieClip *clip; for (clip = main->movieclip.first; clip; clip = clip->id.next) { -- cgit v1.2.3 From bd81afdd5e668578cf25abf3680c691c4191ad06 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 16:16:02 +0000 Subject: Fix compilation without libmv --- source/blender/blenkernel/intern/tracking.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 938bff81470..bbb70bb77ff 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1248,6 +1248,7 @@ ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, ImBuf *search_ibuf, MovieTrackingMarker *marker, int num_samples_x, int num_samples_y, float pos[2]) { +#ifdef WITH_LIBMV ImBuf *pattern_ibuf; double src_pixel_x[5], src_pixel_y[5]; double warped_position_x, warped_position_y; @@ -1272,6 +1273,27 @@ ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, } return pattern_ibuf; +#else + ImBuf *pattern_ibuf; + + /* real sampling requires libmv, but areas are supposing pattern would be + * sampled if search area does exists, so we'll need to create empty + * pattern area here to prevent adding NULL-checks all over just to deal + * with situation when lubmv is disabled + */ + + (void) frame_width; + (void) frame_height; + (void) search_ibuf; + (void) marker; + + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + + pos[0] = num_samples_x / 2.0f; + pos[1] = num_samples_y / 2.0f; + + return pattern_ibuf; +#endif } ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, -- cgit v1.2.3 From dc3645df1abab8c9d1fd93cfbab9688f2baf6ebc Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 10 Jun 2012 16:22:58 +0000 Subject: Bugfix for autosmooth in sculpt mode. This option was broken for non-multires meshes (not sure for how long), as the pmap was not getting calculated. Added a more general check for whether the pmap is needed, also added an assert to warn about this in future. --- source/blender/editors/sculpt_paint/sculpt.c | 48 ++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 6a9257ecb6a..66ad05aec7e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1413,6 +1413,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, SculptSession *ss = ob->sculpt; const int max_iterations = 4; const float fract = 1.0f / max_iterations; + PBVHType type = BLI_pbvh_type(ss->pbvh); int iteration, n, count; float last; @@ -1421,16 +1422,25 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, count = (int)(bstrength * max_iterations); last = max_iterations * (bstrength - count * fract); + if (type == PBVH_FACES && !ss->pmap) { + BLI_assert(!"sculpt smooth: pmap missing"); + return; + } + for (iteration = 0; iteration <= count; ++iteration) { + float strength = (iteration != count) ? 1.0f : last; + #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (n = 0; n < totnode; n++) { - if (ss->multires) { - do_multires_smooth_brush(sd, ss, nodes[n], - iteration != count ? 1.0f : last, smooth_mask); - } - else if (ss->pmap) { - do_mesh_smooth_brush(sd, ss, nodes[n], - iteration != count ? 1.0f : last, smooth_mask); + switch(type) { + case PBVH_GRIDS: + do_multires_smooth_brush(sd, ss, nodes[n], strength, + smooth_mask); + break; + case PBVH_FACES: + do_mesh_smooth_brush(sd, ss, nodes[n], strength, + smooth_mask); + break; } } @@ -3571,6 +3581,21 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, sd->special_rotation = cache->special_rotation; } +/* Returns true iff any of the smoothing modes are active (currently + one of smooth brush, autosmooth, mask smooth, or shift-key + smooth) */ +static int sculpt_any_smooth_mode(const Brush *brush, + StrokeCache *cache, + int stroke_mode) +{ + return ((stroke_mode == BRUSH_STROKE_SMOOTH) || + (cache && cache->alt_smooth) || + (brush->sculpt_tool == SCULPT_TOOL_SMOOTH) || + (brush->autosmooth_factor > 0) || + ((brush->sculpt_tool == SCULPT_TOOL_MASK) && + (brush->mask_tool == BRUSH_MASK_SMOOTH))); +} + static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob) { SculptSession *ss = ob->sculpt; @@ -3579,7 +3604,8 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob) Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = paint_brush(&sd->paint); - sculpt_update_mesh_elements(CTX_data_scene(C), sd, ob, brush->sculpt_tool == SCULPT_TOOL_SMOOTH); + sculpt_update_mesh_elements(CTX_data_scene(C), sd, ob, + sculpt_any_smooth_mode(brush, ss->cache, 0)); } } @@ -3689,11 +3715,7 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op) view3d_operator_needs_opengl(C); sculpt_brush_init_tex(scene, sd, ss); - is_smooth |= mode == BRUSH_STROKE_SMOOTH; - is_smooth |= brush->sculpt_tool == SCULPT_TOOL_SMOOTH; - is_smooth |= ((brush->sculpt_tool == SCULPT_TOOL_MASK) && - (brush->mask_tool == BRUSH_MASK_SMOOTH)); - + is_smooth = sculpt_any_smooth_mode(brush, NULL, mode); sculpt_update_mesh_elements(scene, sd, ob, is_smooth); return 1; -- cgit v1.2.3 From fa1d458b19a077eff5a258d6933d5f1eb801e019 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 10 Jun 2012 16:37:22 +0000 Subject: Code cleanups for the PBVH, no functional changes. * Use the PBVHType consistently in pbvh_update_draw_buffers(). * Split the raycast function up, mesh and grid raycast get their own functions now. * Replace duplicated code in BLI_pbvh_node_add_proxy() with call to BLI_pbvh_node_num_verts(). --- source/blender/blenlib/BLI_pbvh.h | 7 +- source/blender/blenlib/intern/pbvh.c | 202 ++++++++++++++++++++--------------- 2 files changed, 119 insertions(+), 90 deletions(-) diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h index 8806721c044..dbfa08219bd 100644 --- a/source/blender/blenlib/BLI_pbvh.h +++ b/source/blender/blenlib/BLI_pbvh.h @@ -83,9 +83,12 @@ void BLI_pbvh_search_gather(PBVH *bvh, * hit first */ void BLI_pbvh_raycast(PBVH * bvh, BLI_pbvh_HitOccludedCallback cb, void *data, - float ray_start[3], float ray_normal[3], int original); + const float ray_start[3], const float ray_normal[3], + int original); + int BLI_pbvh_node_raycast(PBVH * bvh, PBVHNode * node, float (*origco)[3], - float ray_start[3], float ray_normal[3], float *dist); + const float ray_start[3], const float ray_normal[3], + float *dist); /* Drawing */ diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index f4b57857173..5361682caa4 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -1137,17 +1137,21 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) if (node->flag & PBVH_RebuildDrawBuffers) { GPU_free_buffers(node->draw_buffers); - if (bvh->grids) { - node->draw_buffers = - GPU_build_grid_buffers(node->prim_indices, - node->totprim, bvh->grid_hidden, bvh->gridkey.grid_size); - } - else { - node->draw_buffers = - GPU_build_mesh_buffers(node->face_vert_indices, - bvh->faces, bvh->verts, - node->prim_indices, - node->totprim); + switch (bvh->type) { + case PBVH_GRIDS: + node->draw_buffers = + GPU_build_grid_buffers(node->prim_indices, + node->totprim, + bvh->grid_hidden, + bvh->gridkey.grid_size); + break; + case PBVH_FACES: + node->draw_buffers = + GPU_build_mesh_buffers(node->face_vert_indices, + bvh->faces, bvh->verts, + node->prim_indices, + node->totprim); + break; } node->flag &= ~PBVH_RebuildDrawBuffers; @@ -1473,7 +1477,8 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v) } void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, - float ray_start[3], float ray_normal[3], int original) + const float ray_start[3], const float ray_normal[3], + int original) { RaycastData rcd; @@ -1489,8 +1494,10 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data); } -static int ray_face_intersection(float ray_start[3], float ray_normal[3], - float *t0, float *t1, float *t2, float *t3, +static int ray_face_intersection(const float ray_start[3], + const float ray_normal[3], + const float *t0, const float *t1, + const float *t2, const float *t3, float *fdist) { float dist; @@ -1506,91 +1513,114 @@ static int ray_face_intersection(float ray_start[3], float ray_normal[3], } } -int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], - float ray_start[3], float ray_normal[3], float *dist) +static int pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node, + float (*origco)[3], + const float ray_start[3], + const float ray_normal[3], float *dist) { - MVert *vert; - BLI_bitmap gh; - int *faces, totface, gridsize, totgrid; + const MVert *vert = bvh->verts; + const int *faces = node->prim_indices; + int i, hit = 0, totface = node->totprim; + + for (i = 0; i < totface; ++i) { + const MFace *f = bvh->faces + faces[i]; + const int *face_verts = node->face_vert_indices[i]; + + if (paint_is_face_hidden(f, vert)) + continue; + + if (origco) { + /* intersect with backuped original coordinates */ + hit |= ray_face_intersection(ray_start, ray_normal, + origco[face_verts[0]], + origco[face_verts[1]], + origco[face_verts[2]], + f->v4 ? origco[face_verts[3]] : NULL, + dist); + } + else { + /* intersect with current coordinates */ + hit |= ray_face_intersection(ray_start, ray_normal, + vert[f->v1].co, + vert[f->v2].co, + vert[f->v3].co, + f->v4 ? vert[f->v4].co : NULL, + dist); + } + } + + return hit; +} + +static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node, + float (*origco)[3], + const float ray_start[3], + const float ray_normal[3], float *dist) +{ + int totgrid = node->totprim; + int gridsize = bvh->gridkey.grid_size; int i, x, y, hit = 0; - if (node->flag & PBVH_FullyHidden) - return 0; + for (i = 0; i < totgrid; ++i) { + CCGElem *grid = bvh->grids[node->prim_indices[i]]; + BLI_bitmap gh; - switch (bvh->type) { - case PBVH_FACES: - vert = bvh->verts; - faces = node->prim_indices; - totface = node->totprim; + if (!grid) + continue; - for (i = 0; i < totface; ++i) { - const MFace *f = bvh->faces + faces[i]; - int *face_verts = node->face_vert_indices[i]; + gh = bvh->grid_hidden[node->prim_indices[i]]; - if (paint_is_face_hidden(f, vert)) - continue; + for (y = 0; y < gridsize - 1; ++y) { + for (x = 0; x < gridsize - 1; ++x) { + /* check if grid face is hidden */ + if (gh) { + if (paint_is_grid_face_hidden(gh, gridsize, x, y)) + continue; + } if (origco) { - /* intersect with backuped original coordinates */ hit |= ray_face_intersection(ray_start, ray_normal, - origco[face_verts[0]], - origco[face_verts[1]], - origco[face_verts[2]], - f->v4 ? origco[face_verts[3]] : NULL, - dist); + origco[y * gridsize + x], + origco[y * gridsize + x + 1], + origco[(y + 1) * gridsize + x + 1], + origco[(y + 1) * gridsize + x], + dist); } else { - /* intersect with current coordinates */ hit |= ray_face_intersection(ray_start, ray_normal, - vert[f->v1].co, - vert[f->v2].co, - vert[f->v3].co, - f->v4 ? vert[f->v4].co : NULL, - dist); + CCG_grid_elem_co(&bvh->gridkey, grid, x, y), + CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y), + CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1), + CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1), + dist); } } + } + + if (origco) + origco += gridsize * gridsize; + } + + return hit; +} + +int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], + const float ray_start[3], const float ray_normal[3], + float *dist) +{ + int hit = 0; + + if (node->flag & PBVH_FullyHidden) + return 0; + + switch (bvh->type) { + case PBVH_FACES: + hit |= pbvh_faces_node_raycast(bvh, node, origco, + ray_start, ray_normal, dist); break; case PBVH_GRIDS: - totgrid = node->totprim; - gridsize = bvh->gridkey.grid_size; - - for (i = 0; i < totgrid; ++i) { - CCGElem *grid = bvh->grids[node->prim_indices[i]]; - if (!grid) - continue; - - gh = bvh->grid_hidden[node->prim_indices[i]]; - - for (y = 0; y < gridsize - 1; ++y) { - for (x = 0; x < gridsize - 1; ++x) { - /* check if grid face is hidden */ - if (gh) { - if (paint_is_grid_face_hidden(gh, gridsize, x, y)) - continue; - } - - if (origco) { - hit |= ray_face_intersection(ray_start, ray_normal, - origco[y * gridsize + x], - origco[y * gridsize + x + 1], - origco[(y + 1) * gridsize + x + 1], - origco[(y + 1) * gridsize + x], - dist); - } - else { - hit |= ray_face_intersection(ray_start, ray_normal, - CCG_grid_elem_co(&bvh->gridkey, grid, x, y), - CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y), - CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1), - CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1), - dist); - } - } - } - - if (origco) - origco += gridsize * gridsize; - } + hit |= pbvh_grids_node_raycast(bvh, node, origco, + ray_start, ray_normal, dist); break; } @@ -1787,11 +1817,7 @@ PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node) else node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy"); - if (bvh->grids) - totverts = node->totprim * bvh->gridkey.grid_area; - else - totverts = node->uniq_verts; - + BLI_pbvh_node_num_verts(bvh, node, &totverts, NULL); node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co"); } -- cgit v1.2.3 From b38e4506a6bdd7d9b842f5afd264b9d850703ede Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 10 Jun 2012 17:06:26 +0000 Subject: Force multires update when changing subdivision type. Fixes bug [#31050] Changing multires subdivision algorithm can ruin mesh --- source/blender/makesrna/intern/rna_modifier.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 21a01cf43a8..eb31d83fce8 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -477,6 +477,15 @@ static void rna_WeightVGModifier_mask_uvlayer_set(PointerRNA *ptr, const char *v } } +static void rna_MultiresModifier_type_set(PointerRNA *ptr, int value) +{ + Object *ob = (Object *)ptr->id.data; + MultiresModifierData *mmd = (MultiresModifierData *)ptr->data; + + multires_force_update(ob); + mmd->simple = value; +} + static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { MultiresModifierData *mmd = (MultiresModifierData *)ptr->data; @@ -739,7 +748,7 @@ static void rna_BevelModifier_angle_limit_set(PointerRNA *ptr, float value) #else -static void rna_def_property_subdivision_common(StructRNA *srna, const char type[]) +static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[]) { static EnumPropertyItem prop_subdivision_type_items[] = { {0, "CATMULL_CLARK", 0, "Catmull-Clark", ""}, @@ -752,6 +761,8 @@ static void rna_def_property_subdivision_common(StructRNA *srna, const char type RNA_def_property_enum_items(prop, prop_subdivision_type_items); RNA_def_property_ui_text(prop, "Subdivision Type", "Select type of subdivision algorithm"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + return prop; } static void rna_def_modifier_subsurf(BlenderRNA *brna) @@ -901,7 +912,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MultiresModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MULTIRES); - rna_def_property_subdivision_common(srna, "simple"); + prop = rna_def_property_subdivision_common(srna, "simple"); + RNA_def_property_enum_funcs(prop, NULL, "rna_MultiresModifier_type_set", NULL); prop = RNA_def_property(srna, "levels", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "lvl"); -- cgit v1.2.3 From 4e3a5663c54b56e847e1ccea3f4d9aab5d7e1b7a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 17:09:35 +0000 Subject: Fixed curves and dopeseet views of motion tracking data not taking clip's start frame into account. --- source/blender/editors/space_clip/clip_dopesheet_draw.c | 11 +++++++---- source/blender/editors/space_clip/clip_graph_draw.c | 8 ++++---- source/blender/editors/space_clip/clip_graph_ops.c | 17 +++++++++-------- source/blender/editors/space_clip/clip_intern.h | 4 ++-- source/blender/editors/space_clip/clip_utils.c | 11 +++++++---- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 63148c2b69d..67609fee653 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -200,8 +200,8 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) /* tracked segments */ for (i = 0; i < channel->tot_segment; i++) { - int start_frame = channel->segments[2 * i]; - int end_frame = channel->segments[2 * i + 1]; + int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]); + int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]); if (sel) glColor4fv(selected_strip); @@ -224,8 +224,11 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) while (i < track->markersnr) { MovieTrackingMarker *marker = &track->markers[i]; - if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) - draw_keyframe_shape(marker->framenr, y, xscale, yscale, sel, alpha); + if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) { + int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); + + draw_keyframe_shape(framenr, y, xscale, yscale, sel, alpha); + } i++; } diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 853a7d7cad1..8d30242c128 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -88,9 +88,9 @@ static void draw_curve_knot(float x, float y, float xscale, float yscale, float } static void tracking_segment_point_cb(void *UNUSED(userdata), MovieTrackingTrack *UNUSED(track), - MovieTrackingMarker *marker, int UNUSED(coord), float val) + MovieTrackingMarker *UNUSED(marker), int UNUSED(coord), int scene_framenr, float val) { - glVertex2f(marker->framenr, val); + glVertex2f(scene_framenr, val); } void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord) @@ -123,7 +123,7 @@ void tracking_segment_end_cb(void *UNUSED(userdata)) } static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, - MovieTrackingMarker *marker, int coord, float val) + MovieTrackingMarker *marker, int coord, int scene_framenr, float val) { struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } *data = userdata; int sel = 0, sel_flag; @@ -140,7 +140,7 @@ static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, else UI_ThemeColor(TH_HANDLE_VERTEX); - draw_curve_knot(marker->framenr, val, data->xscale, data->yscale, data->hsize); + draw_curve_knot(scene_framenr, val, data->xscale, data->yscale, data->hsize); } } diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 10692ada5d9..79e199a8f06 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -109,10 +109,11 @@ typedef struct { } MouseSelectUserData; static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack *track, - MovieTrackingMarker *marker, int coord, float val) + MovieTrackingMarker *UNUSED(marker), + int coord, int scene_framenr, float val) { MouseSelectUserData *data = userdata; - float co[2] = {marker->framenr, val}; + float co[2] = {scene_framenr, val}; if (data->has_prev) { float d = dist_to_line_segment_v2(data->mouse_co, data->prev_co, co); @@ -137,14 +138,14 @@ void find_nearest_tracking_segment_end_cb(void *userdata) } static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track, - MovieTrackingMarker *marker, int coord, float val) + MovieTrackingMarker *marker, int coord, int scene_framenr, float val) { MouseSelectUserData *data = userdata; - float dx = marker->framenr - data->mouse_co[0], dy = val - data->mouse_co[1]; + float dx = scene_framenr - data->mouse_co[0], dy = val - data->mouse_co[1]; float d = dx * dx + dy * dy; if (data->marker == NULL || d < data->min_dist) { - float co[2] = {marker->framenr, val}; + float co[2] = {scene_framenr, val}; data->track = track; data->marker = marker; @@ -308,11 +309,11 @@ typedef struct BorderSelectuserData { } BorderSelectuserData; static void border_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track), - MovieTrackingMarker *marker, int coord, float val) + MovieTrackingMarker *marker, int coord, int scene_framenr, float val) { BorderSelectuserData *data = (BorderSelectuserData *) userdata; - if (BLI_in_rctf(&data->rect, marker->framenr, val)) { + if (BLI_in_rctf(&data->rect, scene_framenr, val)) { int flag = 0; if (coord == 0) @@ -532,7 +533,7 @@ typedef struct { } ViewAllUserData; static void view_all_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *UNUSED(marker), - int UNUSED(coord), float val) + int UNUSED(coord), int UNUSED(scene_framenr), float val) { ViewAllUserData *data = (ViewAllUserData *) userdata; diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 00105fb8561..6908e488157 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -110,12 +110,12 @@ void ED_clip_tool_props_register(struct ARegionType *art); /* clip_utils.c */ void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, struct MovieTrackingTrack *track, void *userdata, - void (*func) (void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, float val), + void (*func) (void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val), void (*segment_start) (void *userdata, struct MovieTrackingTrack *track, int coord), void (*segment_end) (void *userdata)); void clip_graph_tracking_values_iterate(struct SpaceClip *sc, void *userdata, - void (*func) (void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, float val), + void (*func) (void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val), void (*segment_start) (void *userdata, struct MovieTrackingTrack *track, int coord), void (*segment_end) (void *userdata)); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 4142c30d825..6b69f316880 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -64,7 +64,7 @@ #include "clip_intern.h" // own include void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack *track, void *userdata, - void (*func) (void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, float val), + void (*func) (void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val), void (*segment_start) (void *userdata, MovieTrackingTrack *track, int coord), void (*segment_end) (void *userdata)) { @@ -104,8 +104,11 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack val = (marker->pos[coord] - prevval) * ((coord == 0) ? (width) : (height)); val /= marker->framenr - prevfra; - if (func) - func(userdata, track, marker, coord, val); + if (func) { + int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); + + func(userdata, track, marker, coord, scene_framenr, val); + } prevval = marker->pos[coord]; prevfra = marker->framenr; @@ -119,7 +122,7 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack } void clip_graph_tracking_values_iterate(SpaceClip *sc, void *userdata, - void (*func) (void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, float val), + void (*func) (void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val), void (*segment_start) (void *userdata, MovieTrackingTrack *track, int coord), void (*segment_end) (void *userdata)) { -- cgit v1.2.3 From 88748904c68e88a2c5864a248419f7fad960695d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 10 Jun 2012 17:24:05 +0000 Subject: Also fix cache line in clip editor which didn't take start frame into account. --- source/blender/editors/space_clip/clip_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 9332413b33b..2e16a9095f0 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -126,7 +126,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc if (act_track) { MovieTrackingTrack *track = act_track; - for (i = sfra, a = 0; i <= efra; i++) { + for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) { int framenr; MovieTrackingMarker *marker; -- cgit v1.2.3 From 298feff39006c14aa28b5e0232aa7ed70a83a496 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Sun, 10 Jun 2012 19:32:57 +0000 Subject: Committing patch [#31704] "Patch to fix keyboard sensor from blocking quit game key binding" by Jay Parker. This patch fixes [#31671] "Keyboard Sensor blocks Quit Game Key Binding" --- source/gameengine/Converter/KX_ConvertSensors.cpp | 3 ++- source/gameengine/GameLogic/SCA_KeyboardSensor.cpp | 5 +++-- source/gameengine/GameLogic/SCA_KeyboardSensor.h | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index fa9eb5317b9..2bd1688ca6d 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -302,7 +302,8 @@ void BL_ConvertSensors(struct Object* blenderobject, (blenderkeybdsensor->type == SENS_ALL_KEYS), blenderkeybdsensor->targetName, blenderkeybdsensor->toggleName, - gameobj); // blenderkeybdsensor->pad); + gameobj, + KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index b39ae209d67..5bdf2e96e93 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -54,7 +54,8 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr, bool bAllKeys, const STR_String& targetProp, const STR_String& toggleProp, - SCA_IObject* gameobj) + SCA_IObject* gameobj, + short int exitKey) :SCA_ISensor(gameobj,keybdmgr), m_hotkey(hotkey), m_qual(qual), @@ -63,7 +64,7 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr, m_targetprop(targetProp), m_toggleprop(toggleProp) { - if (hotkey == SCA_IInputDevice::KX_ESCKEY) + if (hotkey == exitKey) keybdmgr->GetInputDevice()->HookEscape(); // SetDrawColor(0xff0000ff); Init(); diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index 8e21d6bfde1..778929a2551 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -94,7 +94,8 @@ public: bool bAllKeys, const STR_String& targetProp, const STR_String& toggleProp, - SCA_IObject* gameobj); + SCA_IObject* gameobj, + short int exitKey); virtual ~SCA_KeyboardSensor(); virtual CValue* GetReplica(); virtual void Init(); -- cgit v1.2.3