Camera tracking integration
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 7 Nov 2011 12:56:05 +0000 (12:56 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 7 Nov 2011 12:56:05 +0000 (12:56 +0000)
===========================

Rest of changes from camera tracking gsoc project.

This commit includes:

- New compositor nodes:
  * Movie Clip input node
  * Movie Undistortion node
  * Transformation node
  * 2D stabilization node

- Slight changes in existing node to prevent code duplication

18 files changed:
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_edit.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_nodetree_types.h
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_composite.h
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/composite/node_composite_util.h
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/nodes/composite/nodes/node_composite_movieclip.c [new file with mode: 0644]
source/blender/nodes/composite/nodes/node_composite_moviedistortion.c [new file with mode: 0644]
source/blender/nodes/composite/nodes/node_composite_scale.c
source/blender/nodes/composite/nodes/node_composite_stabilize2d.c [new file with mode: 0644]
source/blender/nodes/composite/nodes/node_composite_transform.c [new file with mode: 0644]

index 7509205e9687152fbf002aeeb00b13eff078b557..278e57125c5be0910fd09f761f864285f681f3e3 100644 (file)
@@ -567,6 +567,10 @@ void                       ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
 #define CMP_NODE_COLOR_MATTE 259
 #define CMP_NODE_COLORBALANCE 260
 #define CMP_NODE_HUECORRECT 261
+#define CMP_NODE_MOVIECLIP     262
+#define CMP_NODE_STABILIZE2D   263
+#define CMP_NODE_TRANSFORM     264
+#define CMP_NODE_MOVIEDISTORTION       265
 
 #define CMP_NODE_GLARE         301
 #define CMP_NODE_TONEMAP       302
index a9b2ffe7529c3fade47d5bd0131dc74d7c51cfe1..115591863cca656832833ac599978e7c290a6ab4 100644 (file)
@@ -1790,6 +1790,7 @@ static void registerCompositNodes(ListBase *ntypelist)
        register_node_type_cmp_value(ntypelist);
        register_node_type_cmp_rgb(ntypelist);
        register_node_type_cmp_curve_time(ntypelist);
+       register_node_type_cmp_movieclip(ntypelist);
        
        register_node_type_cmp_composite(ntypelist);
        register_node_type_cmp_viewer(ntypelist);
@@ -1854,6 +1855,9 @@ static void registerCompositNodes(ListBase *ntypelist)
        register_node_type_cmp_glare(ntypelist);
        register_node_type_cmp_tonemap(ntypelist);
        register_node_type_cmp_lensdist(ntypelist);
+       register_node_type_cmp_transform(ntypelist);
+       register_node_type_cmp_stabilize2d(ntypelist);
+       register_node_type_cmp_moviedistortion(ntypelist);
 }
 
 static void registerShaderNodes(ListBase *ntypelist) 
index ce7ff48946570183ac95f935c17304d0b41f0156..9f6ce4eb79b36bbab3c693b06b1ff11176b644b5 100644 (file)
@@ -1254,6 +1254,7 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
 void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain)
 {
        MovieClip *clip= oldmain->movieclip.first;
+       Scene *sce= oldmain->scene.first;
 
        fd->movieclipmap= oldnewmap_new();
 
@@ -1264,6 +1265,15 @@ void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain)
                if(clip->tracking.camera.intrinsics)
                        oldnewmap_insert(fd->movieclipmap, clip->tracking.camera.intrinsics, clip->tracking.camera.intrinsics, 0);
        }
+
+       for(; sce; sce= sce->id.next) {
+               if(sce->nodetree) {
+                       bNode *node;
+                       for(node= sce->nodetree->nodes.first; node; node= node->next)
+                               if(node->type==CMP_NODE_MOVIEDISTORTION)
+                                       oldnewmap_insert(fd->movieclipmap, node->storage, node->storage, 0);
+               }
+       }
 }
 
 /* set old main movie clips caches to zero if it has been restored */
@@ -1272,6 +1282,7 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
 {
        OldNew *entry= fd->movieclipmap->entries;
        MovieClip *clip= oldmain->movieclip.first;
+       Scene *sce= oldmain->scene.first;
        int i;
 
        /* used entries were restored, so we put them to zero */
@@ -1284,6 +1295,15 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
                clip->cache= newmclipadr(fd, clip->cache);
                clip->tracking.camera.intrinsics= newmclipadr(fd, clip->tracking.camera.intrinsics);
        }
+
+       for(; sce; sce= sce->id.next) {
+               if(sce->nodetree) {
+                       bNode *node;
+                       for(node= sce->nodetree->nodes.first; node; node= node->next)
+                               if(node->type==CMP_NODE_MOVIEDISTORTION)
+                                       node->storage= newmclipadr(fd, node->storage);
+               }
+       }
 }
 
 
@@ -2273,7 +2293,11 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                link_list(fd, &node->inputs);
                link_list(fd, &node->outputs);
                
-               node->storage= newdataadr(fd, node->storage);
+               if(node->type == CMP_NODE_MOVIEDISTORTION) {
+                       node->storage= newmclipadr(fd, node->storage);
+               } else
+                       node->storage= newdataadr(fd, node->storage);
+
                if(node->storage) {
                        /* could be handlerized at some point */
                        if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
index f49148342eca7a39c4361e674ddad5e8d671b6eb..021aa6a8a921d4c6f5f00fff61afb6554f8acb5f 100644 (file)
@@ -711,6 +711,8 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
                                write_curvemapping(wd, node->storage);
                        else if(ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
                                write_curvemapping(wd, node->storage);
+                       else if(ntree->type==NTREE_COMPOSIT && node->type==CMP_NODE_MOVIEDISTORTION)
+                               /* pass */ ;
                        else
                                writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
                }
index 24ea51567ad10e0d964155e6806dbed717a6ab64..b4d89e1365dcf28e73f438da90486ef9fd7c44cb 100644 (file)
@@ -1679,6 +1679,40 @@ static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), Pointe
        uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
 }
 
+static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
+}
+
+static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       bNode *node= ptr->data;
+
+       uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
+
+       if(!node->id)
+               return;
+
+       uiItemR(layout, ptr, "filter_type", 0, "", 0);
+}
+
+static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiItemR(layout, ptr, "filter_type", 0, "", 0);
+}
+
+static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       bNode *node= ptr->data;
+
+       uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
+
+       if(!node->id)
+               return;
+
+       uiItemR(layout, ptr, "distortion_type", 0, "", 0);
+}
+
 /* only once called */
 static void node_composit_set_butfunc(bNodeType *ntype)
 {
@@ -1829,6 +1863,20 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_SEPYCCA:
                        ntype->uifunc=node_composit_buts_ycc;
                        break;
+               case CMP_NODE_MOVIECLIP:
+                       ntype->uifunc= node_composit_buts_movieclip;
+                       break;
+               case CMP_NODE_STABILIZE2D:
+                       ntype->uifunc= node_composit_buts_stabilize2d;
+                       break;
+               case CMP_NODE_TRANSFORM:
+                       ntype->uifunc= node_composit_buts_transform;
+                       break;
+               case CMP_NODE_MOVIEDISTORTION:
+                       ntype->uifunc= node_composit_buts_moviedistortion;
+                       break;
+               default:
+                       ntype->uifunc= NULL;
        }
        if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
 
index c1e50c112fae58dbaa5e2eceec160b664d8235f5..745611c6251e26d5ca7dafc873fe7298a0434fbf 100644 (file)
@@ -2207,8 +2207,14 @@ bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate
                ED_node_set_active(bmain, snode->edittree, node);
                
                if(snode->nodetree->type==NTREE_COMPOSIT) {
-                       if(ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE))
+                       if(ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
                                node->id = &scene->id;
+                       }
+                       else if(ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
+                               if(G.main->movieclip.first == G.main->movieclip.last) {
+                                       node->id= G.main->movieclip.first;
+                               }
+                       }
                        
                        ntreeCompositForceHidden(snode->edittree, scene);
                }
index 1445cf3b537773315b1b7ac1b8964a1f59a046d7..f024ad3addd154bd89c0f6be5f9f946dea953030 100644 (file)
@@ -2414,6 +2414,84 @@ static void def_cmp_ycc(StructRNA *srna)
        RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
 }
 
+static void def_cmp_movieclip(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "id");
+       RNA_def_property_struct_type(prop, "MovieClip");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Movie Clip", "");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+
+       RNA_def_struct_sdna_from(srna, "MovieClipUser", "storage");
+}
+
+static void def_cmp_stabilize2d(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       static EnumPropertyItem filter_type_items[] = {
+               {0, "NEAREST",   0, "Nearest",   ""},
+               {1, "BILINEAR",   0, "Bilinear",   ""},
+               {2, "BICUBIC", 0, "Bicubic", ""},
+               {0, NULL, 0, NULL, NULL}};
+
+       prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "id");
+       RNA_def_property_struct_type(prop, "MovieClip");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Movie Clip", "");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "custom1");
+       RNA_def_property_enum_items(prop, filter_type_items);
+       RNA_def_property_ui_text(prop, "Filter", "Method to use to filter stabilization");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+}
+
+static void def_cmp_moviedistortion(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       static EnumPropertyItem distortion_type_items[] = {
+               {0, "UNDISTORT",   0, "Undistort",   ""},
+               {1, "DISTORT", 0, "Distort", ""},
+               {0, NULL, 0, NULL, NULL}};
+
+       prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "id");
+       RNA_def_property_struct_type(prop, "MovieClip");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Movie Clip", "");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "distortion_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "custom1");
+       RNA_def_property_enum_items(prop, distortion_type_items);
+       RNA_def_property_ui_text(prop, "Distortion", "Distortion to use to filter image");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+}
+
+static void dev_cmd_transform(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       static EnumPropertyItem filter_type_items[] = {
+               {0, "NEAREST",   0, "Nearest",   ""},
+               {1, "BILINEAR",   0, "Bilinear",   ""},
+               {2, "BICUBIC", 0, "Bicubic", ""},
+               {0, NULL, 0, NULL, NULL}};
+
+       prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "custom1");
+       RNA_def_property_enum_items(prop, filter_type_items);
+       RNA_def_property_ui_text(prop, "Filter", "Method to use to filter transform");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+}
+
 
 /* -- Texture Nodes --------------------------------------------------------- */
 
index 1bbf47db094f8928722e3bcae3a90c12926f3121..2545826cd462ab037b8da60db5e716502b4484cb 100644 (file)
@@ -117,6 +117,10 @@ DefNode( CompositorNode, CMP_NODE_COLOR_MATTE,    def_cmp_color_matte,    "COLOR
 DefNode( CompositorNode, CMP_NODE_DIST_MATTE,     def_cmp_distance_matte, "DISTANCE_MATTE", DistanceMatte,    "Distance Matte",    ""              )
 DefNode( CompositorNode, CMP_NODE_COLORBALANCE,   def_cmp_colorbalance,   "COLORBALANCE",   ColorBalance,     "Color Balance",     ""              )
 DefNode( CompositorNode, CMP_NODE_HUECORRECT,     def_cmp_huecorrect,     "HUECORRECT",     HueCorrect,       "Hue Correct",       ""              )
+DefNode( CompositorNode, CMP_NODE_MOVIECLIP,      def_cmp_movieclip,      "MOVIECLIP",      MovieClip,        "MovieClip",         ""              )
+DefNode( CompositorNode, CMP_NODE_TRANSFORM,      dev_cmd_transform,      "TRANSFORM",      Transform,        "Transform",         ""              )
+DefNode( CompositorNode, CMP_NODE_STABILIZE2D,    def_cmp_stabilize2d,    "STABILIZE2D",    Stabilize,        "Stabilize 2D",      ""              )
+DefNode( CompositorNode, CMP_NODE_MOVIEDISTORTION,def_cmp_moviedistortion,"MOVIEDISTORTION",MovieDistortion,  "Movie Distortion",  ""              )
                                                                                                                                                    
 DefNode( TextureNode,    TEX_NODE_OUTPUT,         def_tex_output,         "OUTPUT",         Output,           "Output",            ""              )
 DefNode( TextureNode,    TEX_NODE_CHECKER,        0,                      "CHECKER",        Checker,          "Checker",           ""              )
index 82848c6a5d79978355648cb9ee093d105d4a5e6f..69e7f9cac6b941ad4519a3a2124582d081f8fbb5 100644 (file)
@@ -80,6 +80,8 @@ set(SRC
        composite/nodes/node_composite_mapValue.c
        composite/nodes/node_composite_math.c
        composite/nodes/node_composite_mixrgb.c
+       composite/nodes/node_composite_movieclip.c
+       composite/nodes/node_composite_moviedistortion.c
        composite/nodes/node_composite_normal.c
        composite/nodes/node_composite_normalize.c
        composite/nodes/node_composite_outputFile.c
@@ -93,8 +95,10 @@ set(SRC
        composite/nodes/node_composite_sepcombYUVA.c
        composite/nodes/node_composite_setalpha.c
        composite/nodes/node_composite_splitViewer.c
+       composite/nodes/node_composite_stabilize2d.c
        composite/nodes/node_composite_texture.c
        composite/nodes/node_composite_tonemap.c
+       composite/nodes/node_composite_transform.c
        composite/nodes/node_composite_translate.c
        composite/nodes/node_composite_valToRgb.c
        composite/nodes/node_composite_value.c
index d768a5d794f1cf393d2ef558acc3d0ee5d45c925..f1415a8c8f049badec996a0284a950b0ad67ebba 100644 (file)
@@ -52,6 +52,7 @@ void register_node_type_cmp_texture(ListBase *lb);
 void register_node_type_cmp_value(ListBase *lb);
 void register_node_type_cmp_rgb(ListBase *lb);
 void register_node_type_cmp_curve_time(ListBase *lb);
+void register_node_type_cmp_movieclip(ListBase *lb);
 
 void register_node_type_cmp_composite(ListBase *lb);
 void register_node_type_cmp_viewer(ListBase *lb);
@@ -113,6 +114,9 @@ void register_node_type_cmp_flip(ListBase *lb);
 void register_node_type_cmp_crop(ListBase *lb);
 void register_node_type_cmp_displace(ListBase *lb);
 void register_node_type_cmp_mapuv(ListBase *lb);
+void register_node_type_cmp_transform(ListBase *lb);
+void register_node_type_cmp_stabilize2d(ListBase *lb);
+void register_node_type_cmp_moviedistortion(ListBase *lb);
 
 void register_node_type_cmp_glare(ListBase *lb);
 void register_node_type_cmp_tonemap(ListBase *lb);
index 2151176f907c1372fd05c4efc383faff86e469b3..d3f4a5b29991b6ab72fa38b6c10c49323bffd9f9 100644 (file)
@@ -45,6 +45,7 @@
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
+#include "BKE_tracking.h"
 #include "BKE_utildefines.h"
 
 #include "node_exec.h"
@@ -168,6 +169,17 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
                                        BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id);
                                }
                        }
+                       else if(lnode->type==CMP_NODE_MOVIEDISTORTION) {
+                               /* special case for distortion node: distortion context is allocating in exec function
+                                  and to achive much better performance on further calls this context should be
+                                  copied back to original node */
+                               if(lnode->storage) {
+                                       if(lnode->new_node->storage)
+                                               BKE_tracking_distortion_destroy(lnode->new_node->storage);
+
+                                       lnode->new_node->storage= BKE_tracking_distortion_copy(lnode->storage);
+                               }
+                       }
                        
                        for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
                                if(ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
@@ -806,6 +818,10 @@ int ntreeCompositTagAnimated(bNodeTree *ntree)
                                nodeUpdate(ntree, node);
                        }
                }
+               else if(ELEM(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_TRANSFORM)) {
+                       nodeUpdate(ntree, node);
+                       tagged= 1;
+               }
        }
        
        return tagged;
index 6da9b901e76201f84dca12ae5b5d445e9b53e2e7..9cac4c477eb49c7aebf244c401b20fde8de36b82 100644 (file)
@@ -44,6 +44,7 @@
 #include "DNA_ID.h"
 #include "DNA_image_types.h"
 #include "DNA_material_types.h"
+#include "DNA_movieclip_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_movieclip.h"
 #include "BKE_node.h"
 #include "BKE_texture.h"
+#include "BKE_tracking.h"
 
 #include "BKE_library.h"
 #include "BKE_object.h"
@@ -210,4 +213,11 @@ CompBuf* qd_downScaledCopy(CompBuf* src, int scale);
 void IIR_gauss(CompBuf* src, float sigma, int chan, int xy);
 /* end utility funcs */
 
+/* transformations */
+
+#define CMP_SCALE_MAX  12000
+
+CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type);
+float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc);
+
 #endif
index c1e9d28bb4dc3ed4bed4c126cf99e7518747d657..41427c422867571dbaf7a826d46e0d234192cbbb 100644 (file)
@@ -58,6 +58,36 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= {
        {       -1, 0, ""       }
 };
 
+/* float buffer from the image with matching color management */
+float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
+{
+       float *rect;
+
+       *alloc= FALSE;
+
+       if(rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
+               if(ibuf->profile != IB_PROFILE_NONE) {
+                       rect= ibuf->rect_float;
+               }
+               else {
+                       rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
+                       srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
+                       *alloc= TRUE;
+               }
+       }
+       else {
+               if(ibuf->profile == IB_PROFILE_NONE) {
+                       rect= ibuf->rect_float;
+               }
+               else {
+                       rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
+                       linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
+                       *alloc= TRUE;
+               }
+       }
+
+       return rect;
+}
 
 /* note: this function is used for multilayer too, to ensure uniform 
    handling with BKE_image_get_ibuf() */
@@ -82,26 +112,7 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
        /* now we need a float buffer from the image with matching color management */
        /* XXX weak code, multilayer is excluded from this */
        if(ibuf->channels == 4 && ima->rr==NULL) {
-               if(rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
-                       if(ibuf->profile != IB_PROFILE_NONE) {
-                               rect= ibuf->rect_float;
-                       }
-                       else {
-                               rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
-                               srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
-                               alloc= TRUE;
-                       }
-               }
-               else {
-                       if(ibuf->profile == IB_PROFILE_NONE) {
-                               rect= ibuf->rect_float;
-                       }
-                       else {
-                               rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
-                               linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
-                               alloc= TRUE;
-                       }
-               }
+               rect= node_composit_get_float_buffer(rd, ibuf, &alloc);
        }
        else {
                /* non-rgba passes can't use color profiles */
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
new file mode 100644 (file)
index 0000000..8931b89
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * ***** 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.
+ *
+ * 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_movieclip.c
+ *  \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+static bNodeSocketTemplate cmp_node_movieclip_out[]= {
+       {       SOCK_RGBA,              0,      "Image"},
+       {       SOCK_FLOAT,             1,      "Offset X"},
+       {       SOCK_FLOAT,             1,      "Offset Y"},
+       {       SOCK_FLOAT,             1,      "Scale"},
+       {       SOCK_FLOAT,             1,      "Angle"},
+       {       -1, 0, ""       }
+};
+
+static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, MovieClipUser *user)
+{
+       ImBuf *ibuf;
+       CompBuf *stackbuf;
+       int type;
+
+       float *rect;
+       int alloc= FALSE;
+
+       ibuf= BKE_movieclip_get_ibuf(clip, user);
+
+       if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
+               IMB_freeImBuf(ibuf);
+               return NULL;
+       }
+
+       if (ibuf->rect_float == NULL || ibuf->userflags&IB_RECT_INVALID) {
+               IMB_float_from_rect(ibuf);
+               ibuf->userflags&= ~IB_RECT_INVALID;
+       }
+
+       /* now we need a float buffer from the image with matching color management */
+       if(ibuf->channels == 4) {
+               rect= node_composit_get_float_buffer(rd, ibuf, &alloc);
+       }
+       else {
+               /* non-rgba passes can't use color profiles */
+               rect= ibuf->rect_float;
+       }
+       /* done coercing into the correct color management */
+
+       if(!alloc) {
+               rect= MEM_dupallocN(rect);
+               alloc= 1;
+       }
+
+       type= ibuf->channels;
+
+       if(rd->scemode & R_COMP_CROP) {
+               stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
+               if(alloc)
+                       MEM_freeN(rect);
+       }
+       else {
+               /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
+               stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
+               stackbuf->rect= rect;
+               stackbuf->malloc= alloc;
+       }
+
+       IMB_freeImBuf(ibuf);
+
+       return stackbuf;
+}
+
+static void node_composit_exec_movieclip(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
+{
+       if(node->id) {
+               RenderData *rd= data;
+               MovieClip *clip= (MovieClip *)node->id;
+               MovieClipUser *user= (MovieClipUser *)node->storage;
+               CompBuf *stackbuf= NULL;
+
+               BKE_movieclip_user_set_frame(user, rd->cfra);
+
+               stackbuf= node_composit_get_movieclip(rd, clip, user);
+
+               if (stackbuf) {
+                       MovieTrackingStabilization *stab= &clip->tracking.stabilization;
+
+                       /* put image on stack */
+                       out[0]->data= stackbuf;
+
+                       if(stab->flag&TRACKING_2D_STABILIZATION) {
+                               float loc[2], scale, angle;
+
+                               BKE_tracking_stabilization_data(&clip->tracking, rd->cfra, stackbuf->x, stackbuf->y,
+                                                       loc, &scale, &angle);
+
+                               out[1]->vec[0]= loc[0];
+                               out[2]->vec[0]= loc[1];
+
+                               out[3]->vec[0]= scale;
+                               out[4]->vec[0]= angle;
+                       }
+
+                       /* generate preview */
+                       generate_preview(data, node, stackbuf);
+               }
+       }
+}
+
+static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+{
+       MovieClipUser *user= MEM_callocN(sizeof(MovieClipUser), "node movie clip user");
+
+       node->storage= user;
+       user->framenr= 1;
+}
+
+void register_node_type_cmp_movieclip(ListBase *lb)
+{
+       static bNodeType ntype;
+
+       node_type_base(&ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+       node_type_socket_templates(&ntype, NULL, cmp_node_movieclip_out);
+       node_type_size(&ntype, 120, 80, 300);
+       node_type_init(&ntype, init);
+       node_type_storage(&ntype, "MovieClipUser", node_free_standard_storage, node_copy_standard_storage);
+       node_type_exec(&ntype, node_composit_exec_movieclip);
+
+       nodeRegisterType(lb, &ntype);
+}
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
new file mode 100644 (file)
index 0000000..4396163
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * ***** 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.
+ *
+ * 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_moviedistortion.c
+ *  \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+/* **************** Translate  ******************** */
+
+static bNodeSocketTemplate cmp_node_moviedistortion_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketTemplate cmp_node_moviedistortion_out[]= {
+       {       SOCK_RGBA, 0, "Image"},
+       {       -1, 0, ""       }
+};
+
+static void exec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(in[0]->data) {
+               if(node->id) {
+                       MovieClip *clip= (MovieClip *)node->id;
+                       CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+                       CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 0);
+                       ImBuf *ibuf;
+
+                       ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
+
+                       if(ibuf) {
+                               ImBuf *obuf;
+                               MovieTracking *tracking= &clip->tracking;
+                               int width, height;
+                               float overscan= 0.0f;
+
+                               ibuf->rect_float= cbuf->rect;
+
+                               BKE_movieclip_get_size(clip, NULL, &width, &height);
+
+                               if(!node->storage)
+                                       node->storage= BKE_tracking_distortion_create();
+
+                               if(node->custom1==0)
+                                       obuf= BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 1);
+                               else
+                                       obuf= BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 0);
+
+                               stackbuf->rect= obuf->rect_float;
+                               stackbuf->malloc= 1;
+
+                               obuf->mall&= ~IB_rectfloat;
+                               obuf->rect_float= NULL;
+
+                               IMB_freeImBuf(ibuf);
+                               IMB_freeImBuf(obuf);
+                       }
+
+                       /* pass on output and free */
+                       out[0]->data= stackbuf;
+
+                       if(cbuf!=in[0]->data)
+                               free_compbuf(cbuf);
+               } else {
+                       CompBuf *cbuf= in[0]->data;
+                       CompBuf *stackbuf= pass_on_compbuf(cbuf);
+
+                       out[0]->data= stackbuf;
+               }
+       }
+}
+
+static const char *label(bNode *node)
+{
+       if(node->custom1==0)
+               return "Undistortion";
+       else
+               return "Distortion";
+}
+
+static void storage_free(bNode *node)
+{
+       if(node->storage)
+               BKE_tracking_distortion_destroy(node->storage);
+
+       node->storage= NULL;
+}
+
+void storage_copy(bNode *orig_node, bNode *new_node)
+{
+       if(orig_node->storage)
+               new_node->storage= BKE_tracking_distortion_copy(orig_node->storage);
+}
+
+void register_node_type_cmp_moviedistortion(ListBase *lb)
+{
+       static bNodeType ntype;
+
+       node_type_base(&ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
+       node_type_socket_templates(&ntype, cmp_node_moviedistortion_in, cmp_node_moviedistortion_out);
+       node_type_size(&ntype, 140, 100, 320);
+       node_type_label(&ntype, label);
+       node_type_exec(&ntype, exec);
+       node_type_storage(&ntype, NULL, storage_free, storage_copy);
+
+       nodeRegisterType(lb, &ntype);
+}
index 5eb789ae0c92a2b8c00dcb7935151efe38ae1ddb..37332c9bd7ecd2e5584a250637dbbd90a3b79ecf 100644 (file)
@@ -34,8 +34,6 @@
 
 /* **************** Scale  ******************** */
 
-#define CMP_SCALE_MAX  12000
-
 static bNodeSocketTemplate cmp_node_scale_in[]= {
        {       SOCK_RGBA, 1, "Image",                  1.0f, 1.0f, 1.0f, 1.0f},
        {       SOCK_FLOAT, 1, "X",                             1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, CMP_SCALE_MAX, PROP_FACTOR},
@@ -110,6 +108,25 @@ static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, b
                if(cbuf!=in[0]->data)
                        free_compbuf(cbuf);
        }
+       else if (node->custom1==CMP_SCALE_ABSOLUTE) {
+               CompBuf *stackbuf;
+               int a, x, y;
+               float *fp;
+
+               x = MAX2((int)in[1]->vec[0], 1);
+               y = MAX2((int)in[2]->vec[0], 1);
+
+               stackbuf = alloc_compbuf(x, y, CB_RGBA, 1);
+               fp = stackbuf->rect;
+
+               a = stackbuf->x * stackbuf->y;
+               while(a--) {
+                       copy_v4_v4(fp, in[0]->vec);
+                       fp += 4;
+               }
+
+               out[0]->data= stackbuf;
+       }
 }
 
 void register_node_type_cmp_scale(ListBase *lb)
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
new file mode 100644 (file)
index 0000000..c5d60e6
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * ***** 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.
+ *
+ * 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_stabilize2d.c
+ *  \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+/* **************** Translate  ******************** */
+
+static bNodeSocketTemplate cmp_node_stabilize2d_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketTemplate cmp_node_stabilize2d_out[]= {
+       {       SOCK_RGBA, 0, "Image"},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_stabilize2d(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(in[0]->data && node->id) {
+               RenderData *rd= data;
+               MovieClip *clip= (MovieClip *)node->id;
+               CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+               CompBuf *stackbuf;
+               float loc[2], scale, angle;
+
+               BKE_tracking_stabilization_data(&clip->tracking, rd->cfra, cbuf->x, cbuf->y, loc, &scale, &angle);
+
+               stackbuf= node_composit_transform(cbuf, loc[0], loc[1], angle, scale, node->custom1);
+
+               /* pass on output and free */
+               out[0]->data= stackbuf;
+
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+       }
+}
+
+void register_node_type_cmp_stabilize2d(ListBase *lb)
+{
+       static bNodeType ntype;
+
+       node_type_base(&ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS);
+       node_type_socket_templates(&ntype, cmp_node_stabilize2d_in, cmp_node_stabilize2d_out);
+       node_type_size(&ntype, 140, 100, 320);
+       node_type_exec(&ntype, node_composit_exec_stabilize2d);
+
+       nodeRegisterType(lb, &ntype);
+}
diff --git a/source/blender/nodes/composite/nodes/node_composite_transform.c b/source/blender/nodes/composite/nodes/node_composite_transform.c
new file mode 100644 (file)
index 0000000..de9b8fc
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * ***** 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.
+ *
+ * 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_transform.c
+ *  \ingroup cmpnodes
+ */
+
+#include "node_composite_util.h"
+
+/* **************** Transform  ******************** */
+
+static bNodeSocketTemplate cmp_node_transform_in[]= {
+       {       SOCK_RGBA,              1,      "Image",                        0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_FLOAT,             1,      "X",                            0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+       {       SOCK_FLOAT,             1,      "Y",                            0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+       {       SOCK_FLOAT,             1,      "Angle",                        0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_ANGLE},
+       {       SOCK_FLOAT,             1,      "Scale",                        1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, CMP_SCALE_MAX},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketTemplate cmp_node_transform_out[]= {
+       {       SOCK_RGBA, 0, "Image"},
+       {       -1, 0, ""       }
+};
+
+CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type)
+{
+       CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1);
+       ImBuf *ibuf, *obuf;
+       float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
+       float svec[3]= {scale, scale, scale}, loc[2]= {x, y};
+
+       unit_m4(rmat);
+       unit_m4(lmat);
+       unit_m4(smat);
+       unit_m4(cmat);
+
+       /* image center as rotation center */
+       cmat[3][0]= (float)cbuf->x/2.0f;
+       cmat[3][1]= (float)cbuf->y/2.0f;
+       invert_m4_m4(icmat, cmat);
+
+       size_to_mat4(smat, svec);               /* scale matrix */
+       add_v2_v2(lmat[3], loc);                /* tranlation matrix */
+       rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
+
+       /* compose transformation matrix */
+       mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
+
+       invert_m4(mat);
+
+       ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
+       obuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0);
+
+       if(ibuf && obuf) {
+               int i, j;
+
+               ibuf->rect_float= cbuf->rect;
+               obuf->rect_float= stackbuf->rect;
+
+               for(j=0; j<cbuf->y; j++) {
+                       for(i=0; i<cbuf->x;i++) {
+                               float vec[3]= {i, j, 0};
+
+                               mul_v3_m4v3(vec, mat, vec);
+
+                               switch(filter_type) {
+                                       case 0:
+                                               neareast_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
+                                               break ;
+                                       case 1:
+                                               bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
+                                               break;
+                                       case 2:
+                                               bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
+                                               break;
+                               }
+                       }
+               }
+
+               IMB_freeImBuf(ibuf);
+               IMB_freeImBuf(obuf);
+       }
+
+       /* pass on output and free */
+       return stackbuf;
+}
+
+static void node_composit_exec_transform(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(in[0]->data) {
+               CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+               CompBuf *stackbuf;
+
+               stackbuf= node_composit_transform(cbuf, in[1]->vec[0], in[2]->vec[0], in[3]->vec[0], in[4]->vec[0], node->custom1);
+
+               /* pass on output and free */
+               out[0]->data= stackbuf;
+
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+       }
+}
+
+void register_node_type_cmp_transform(ListBase *lb)
+{
+       static bNodeType ntype;
+
+       node_type_base(&ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS);
+       node_type_socket_templates(&ntype, cmp_node_transform_in, cmp_node_transform_out);
+       node_type_size(&ntype, 140, 100, 320);
+       node_type_exec(&ntype, node_composit_exec_transform);
+
+       nodeRegisterType(lb, &ntype);
+}
+
+