Compositor: Implement sampled motion blur for plane track deform node
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 3 Feb 2015 20:16:28 +0000 (01:16 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 3 Feb 2015 20:17:59 +0000 (01:17 +0500)
Quite striaghtforward change, and in theory we can even try supporting motion
blur for the corner pin node (which is tricky because coordinates actually
coming from sockets, but with some black magic should be doable).

source/blender/blenloader/intern/versioning_270.c
source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
source/blender/compositor/operations/COM_PlaneTrackOperation.h
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c

index a6320ed597bf6a095d96c70d619bc658550dd25a..096fc315f39f2317a4ae029146e8da2672ba153a 100644 (file)
@@ -542,4 +542,21 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                                part->child_flag |= PART_CHILD_USE_ROUGH_CURVE;
                }
        }
+
+       if (!DNA_struct_elem_find(fd->filesdna, "NodePlaneTrackDeformData", "char", "flag")) {
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (ELEM(node->type, CMP_NODE_PLANETRACKDEFORM)) {
+                                               NodePlaneTrackDeformData *data = node->storage;
+                                               data->flag = 0;
+                                               data->motion_blur_samples = 16;
+                                               data->motion_blur_shutter = 0.5f;
+                                       }
+                               }
+                       }
+               }
+               FOREACH_NODETREE_END
+       }
 }
index 9b69bc5a46ea8f60e01114aa59907b7fb6f1d7bd..379b9f193e82c8e49721d96e2c7fa069a9d69ad1 100644 (file)
@@ -54,6 +54,10 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter, const C
        warp_image_operation->setTrackingObject(data->tracking_object);
        warp_image_operation->setPlaneTrackName(data->plane_track_name);
        warp_image_operation->setFramenumber(frame_number);
+       if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+               warp_image_operation->setMotionBlurSamples(data->motion_blur_samples);
+               warp_image_operation->setMotionBlurShutter(data->motion_blur_shutter);
+       }
        converter.addOperation(warp_image_operation);
        
        converter.mapInputSocket(input_image, warp_image_operation->getInputSocket(0));
@@ -64,6 +68,10 @@ void PlaneTrackDeformNode::convertToOperations(NodeConverter &converter, const C
        plane_mask_operation->setTrackingObject(data->tracking_object);
        plane_mask_operation->setPlaneTrackName(data->plane_track_name);
        plane_mask_operation->setFramenumber(frame_number);
+       if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+               plane_mask_operation->setMotionBlurSamples(data->motion_blur_samples);
+               plane_mask_operation->setMotionBlurShutter(data->motion_blur_shutter);
+       }
        converter.addOperation(plane_mask_operation);
        
        converter.mapOutputSocket(output_plane, plane_mask_operation->getOutputSocket());
index fe272000b6e44695d31d86b27a54e2a44ab11a38..fb8730c9fa0ee312931c1f74ac1cb421fe28d773 100644 (file)
@@ -135,7 +135,7 @@ void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect)
                                             getInputSocketReader(3) };
                float corners[4][2];
                readCornersFromSockets(rect, readers, corners);
-               calculateCorners(corners, true);
+               calculateCorners(corners, true, 0);
                
                m_corners_ready = true;
        }
@@ -194,8 +194,7 @@ void *PlaneCornerPinWarpImageOperation::initializeTileData(rcti *rect)
                                             getInputSocketReader(4) };
                float corners[4][2];
                readCornersFromSockets(rect, readers, corners);
-               calculateCorners(corners, true);
-               calculatePerspectiveMatrix();
+               calculateCorners(corners, true, 0);
                
                m_corners_ready = true;
        }
index c507b4cfa98aa22d25ca9684372e6c3f04b1b3ea..e3095f74b99fd6505f76e7149dc716a71d05f175 100644 (file)
@@ -56,36 +56,38 @@ PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation() :
        this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
        this->addOutputSocket(COM_DT_COLOR);
        this->m_pixelReader = NULL;
+       this->m_motion_blur_samples = 1;
+       this->m_motion_blur_shutter = 0.5f;
        this->setComplex(true);
 }
 
-void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2], bool normalized)
+void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
+                                                      bool normalized,
+                                                      int sample)
 {
+       BLI_assert(sample < this->m_motion_blur_samples);
+       const int width = this->m_pixelReader->getWidth();
+       const int height = this->m_pixelReader->getHeight();
+       float frame_corners[4][2] = {{0.0f, 0.0f},
+                                    {(float) width, 0.0f},
+                                    {(float) width, (float) height},
+                                    {0.0f, (float) height}};
+       MotionSample *sample_data = &this->m_samples[sample];
        if (normalized) {
                for (int i = 0; i < 4; i++) {
-                       this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
-                       this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
+                       sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
+                       sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
                }
        }
        else {
                for (int i = 0; i < 4; i++) {
-                       this->m_frameSpaceCorners[i][0] = corners[i][0];
-                       this->m_frameSpaceCorners[i][1] = corners[i][1];
+                       sample_data->frameSpaceCorners[i][0] = corners[i][0];
+                       sample_data->frameSpaceCorners[i][1] = corners[i][1];
                }
        }
-}
-
-void PlaneDistortWarpImageOperation::calculatePerspectiveMatrix()
-{
-       const int width = this->m_pixelReader->getWidth();
-       const int height = this->m_pixelReader->getHeight();
-       float frame_corners[4][2] = {{0.0f, 0.0f},
-                                    {(float) width, 0.0f},
-                                    {(float) width, (float) height},
-                                    {0.0f, (float) height}};
-       BKE_tracking_homography_between_two_quads(this->m_frameSpaceCorners,
+       BKE_tracking_homography_between_two_quads(sample_data->frameSpaceCorners,
                                                  frame_corners,
-                                                 this->m_perspectiveMatrix);
+                                                 sample_data->perspectiveMatrix);
 }
 
 void PlaneDistortWarpImageOperation::initExecution()
@@ -100,35 +102,47 @@ void PlaneDistortWarpImageOperation::deinitExecution()
 
 void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
 {
-       float xy[2] = {x, y};
        float uv[2];
        float deriv[2][2];
-
-       pixelTransform(xy, uv, deriv);
-
-       m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
-}
-
-void PlaneDistortWarpImageOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2])
-{
-       warpCoord(xy[0], xy[1], m_perspectiveMatrix, r_uv, r_deriv);
+       if (this->m_motion_blur_samples == 1) {
+               warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv);
+               m_pixelReader->readFiltered(output,
+                                           uv[0], uv[1],
+                                           deriv[0], deriv[1],
+                                           COM_PS_BILINEAR);
+       }
+       else {
+               zero_v4(output);
+               for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+                       float color[4];
+                       warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
+                       m_pixelReader->readFiltered(color,
+                                                   uv[0], uv[1],
+                                                   deriv[0], deriv[1],
+                                                   COM_PS_BILINEAR);
+                       add_v4_v4(output, color);
+               }
+               mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples);
+       }
 }
 
 bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
 {
-       float UVs[4][2];
-       float deriv[2][2];
-
-       /* TODO(sergey): figure out proper way to do this. */
-       warpCoord(input->xmin - 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[0], deriv);
-       warpCoord(input->xmax + 2, input->ymin - 2, this->m_perspectiveMatrix, UVs[1], deriv);
-       warpCoord(input->xmax + 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[2], deriv);
-       warpCoord(input->xmin - 2, input->ymax + 2, this->m_perspectiveMatrix, UVs[3], deriv);
-
        float min[2], max[2];
        INIT_MINMAX2(min, max);
-       for (int i = 0; i < 4; i++) {
-               minmax_v2v2_v2(min, max, UVs[i]);
+
+       for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+               float UVs[4][2];
+               float deriv[2][2];
+               MotionSample *sample_data = &this->m_samples[sample];
+               /* TODO(sergey): figure out proper way to do this. */
+               warpCoord(input->xmin - 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv);
+               warpCoord(input->xmax + 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv);
+               warpCoord(input->xmax + 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv);
+               warpCoord(input->xmin - 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv);
+               for (int i = 0; i < 4; i++) {
+                       minmax_v2v2_v2(min, max, UVs[i]);
+               }
        }
 
        rcti newInput;
@@ -151,20 +165,26 @@ PlaneDistortMaskOperation::PlaneDistortMaskOperation() :
 
        /* Currently hardcoded to 8 samples. */
        m_osa = 8;
+       this->m_motion_blur_samples = 1;
+       this->m_motion_blur_shutter = 0.5f;
 }
 
-void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2], bool normalized)
+void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2],
+                                                 bool normalized,
+                                                 int sample)
 {
+       BLI_assert(sample < this->m_motion_blur_samples);
+       MotionSample *sample_data = &this->m_samples[sample];
        if (normalized) {
                for (int i = 0; i < 4; i++) {
-                       this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
-                       this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
+                       sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
+                       sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
                }
        }
        else {
                for (int i = 0; i < 4; i++) {
-                       this->m_frameSpaceCorners[i][0] = corners[i][0];
-                       this->m_frameSpaceCorners[i][1] = corners[i][1];
+                       sample_data->frameSpaceCorners[i][0] = corners[i][0];
+                       sample_data->frameSpaceCorners[i][1] = corners[i][1];
                }
        }
 }
@@ -177,18 +197,44 @@ void PlaneDistortMaskOperation::initExecution()
 void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
 {
        float point[2];
-
        int inside_counter = 0;
-       for (int sample = 0; sample < this->m_osa; sample++) {
-               point[0] = x + this->m_jitter[sample][0];
-               point[1] = y + this->m_jitter[sample][1];
-
-               if (isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) ||
-                   isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3]))
+       if (this->m_motion_blur_samples == 1) {
+               MotionSample *sample_data = &this->m_samples[0];
+               for (int sample = 0; sample < this->m_osa; sample++) {
+                       point[0] = x + this->m_jitter[sample][0];
+                       point[1] = y + this->m_jitter[sample][1];
+                       if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+                                                     sample_data->frameSpaceCorners[1],
+                                                     sample_data->frameSpaceCorners[2]) ||
+                           isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+                                                     sample_data->frameSpaceCorners[2],
+                                                     sample_data->frameSpaceCorners[3]))
+                       {
+                               inside_counter++;
+                       }
+               }
+               output[0] = (float)inside_counter / this->m_osa;
+       }
+       else {
+               for (int motion_sample = 0;
+                    motion_sample < this->m_motion_blur_samples;
+                    ++motion_sample)
                {
-                       inside_counter++;
+                       MotionSample *sample_data = &this->m_samples[motion_sample];
+                       for (int osa_sample = 0; osa_sample < this->m_osa; ++osa_sample) {
+                               point[0] = x + this->m_jitter[osa_sample][0];
+                               point[1] = y + this->m_jitter[osa_sample][1];
+                               if (isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+                                                             sample_data->frameSpaceCorners[1],
+                                                             sample_data->frameSpaceCorners[2]) ||
+                                   isect_point_tri_v2(point, sample_data->frameSpaceCorners[0],
+                                                             sample_data->frameSpaceCorners[2],
+                                                         sample_data->frameSpaceCorners[3]))
+                               {
+                                       inside_counter++;
+                               }
+                       }
                }
+               output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples);
        }
-
-       output[0] = (float) inside_counter / this->m_osa;
 }
index ee2874c6b46bc0dfb1844075d1c2af6829346cad..6ceb476f5f915981b265ab5e6194d7fe51cec73d 100644 (file)
 #include "BLI_listbase.h"
 #include "BLI_string.h"
 
+#define PLANE_DISTORT_MAX_SAMPLES 64
 
 class PlaneDistortWarpImageOperation : public NodeOperation {
 protected:
+       struct MotionSample {
+               float frameSpaceCorners[4][2];  /* Corners coordinates in pixel space. */
+               float perspectiveMatrix[3][3];
+       };
        SocketReader *m_pixelReader;
-       float m_frameSpaceCorners[4][2];  /* Corners coordinates in pixel space. */
-       float m_perspectiveMatrix[3][3];
+       MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES];
+       int m_motion_blur_samples;
+       float m_motion_blur_shutter;
 
 public:
        PlaneDistortWarpImageOperation();
 
-       void calculateCorners(const float corners[4][2], bool normalized);
-       void calculatePerspectiveMatrix();
+       void calculateCorners(const float corners[4][2],
+                             bool normalized,
+                             int sample);
 
        void initExecution();
        void deinitExecution();
 
        void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
-       void pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]);
 
        bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+
+       void setMotionBlurSamples(int samples) {
+               BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES);
+               this->m_motion_blur_samples = samples;
+       }
+       void setMotionBlurShutter(float shutter) { this->m_motion_blur_shutter = shutter; }
 };
 
 
 class PlaneDistortMaskOperation : public NodeOperation {
 protected:
+       struct MotionSample {
+               float frameSpaceCorners[4][2];  /* Corners coordinates in pixel space. */
+       };
        int m_osa;
+       MotionSample m_samples[PLANE_DISTORT_MAX_SAMPLES];
        float m_jitter[32][2];
-       float m_frameSpaceCorners[4][2];  /* Corners coordinates in pixel space. */
+       int m_motion_blur_samples;
+       float m_motion_blur_shutter;
 
 public:
        PlaneDistortMaskOperation();
        
-       void calculateCorners(const float corners[4][2], bool normalized);
+       void calculateCorners(const float corners[4][2],
+                             bool normalized,
+                             int sample);
        
        void initExecution();
        
        void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+
+       void setMotionBlurSamples(int samples) {
+               BLI_assert(samples <= PLANE_DISTORT_MAX_SAMPLES);
+               this->m_motion_blur_samples = samples;
+       }
+       void setMotionBlurShutter(float shutter) { this->m_motion_blur_shutter = shutter; }
 };
 
 #endif
index fec39cbfde02dbe0d16fe6d518f8086811993e43..f6152981ee7f52ff2ca2aad0543c83283bc7a340 100644 (file)
@@ -46,7 +46,7 @@ PlaneTrackCommon::PlaneTrackCommon()
        this->m_planeTrackName[0] = '\0';
 }
 
-void PlaneTrackCommon::readCornersFromTrack(float corners[4][2])
+void PlaneTrackCommon::readCornersFromTrack(float corners[4][2], float frame)
 {
        MovieTracking *tracking;
        MovieTrackingObject *object;
@@ -64,13 +64,13 @@ void PlaneTrackCommon::readCornersFromTrack(float corners[4][2])
                
                if (plane_track) {
                        MovieTrackingPlaneMarker *plane_marker;
-                       int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
-                       
+                       float clip_framenr =
+                               BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip,
+                                                                       frame);
                        plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
-                       copy_v2_v2(corners[0], plane_marker->corners[0]);
-                       copy_v2_v2(corners[1], plane_marker->corners[1]);
-                       copy_v2_v2(corners[2], plane_marker->corners[2]);
-                       copy_v2_v2(corners[3], plane_marker->corners[3]);
+                       BKE_tracking_plane_marker_get_subframe_corners(plane_track,
+                                                                      clip_framenr,
+                                                                      corners);
                }
        }
 }
@@ -98,10 +98,21 @@ void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned
 void PlaneTrackMaskOperation::initExecution()
 {
        PlaneDistortMaskOperation::initExecution();
-       
        float corners[4][2];
-       readCornersFromTrack(corners);
-       calculateCorners(corners, true);
+       if (this->m_motion_blur_samples == 1) {
+               readCornersFromTrack(corners, this->m_framenumber);
+               calculateCorners(corners, true, 0);
+       }
+       else {
+               const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter;
+               const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples;
+               float frame_iter = frame;
+               for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+                       readCornersFromTrack(corners, frame_iter);
+                       calculateCorners(corners, true, sample);
+                       frame_iter += frame_step;
+               }
+       }
 }
 
 /* ******** PlaneTrackWarpImageOperation ******** */
@@ -109,9 +120,20 @@ void PlaneTrackMaskOperation::initExecution()
 void PlaneTrackWarpImageOperation::initExecution()
 {
        PlaneDistortWarpImageOperation::initExecution();
-       
+       /* TODO(sergey): De-duplicate with mask operation. */
        float corners[4][2];
-       readCornersFromTrack(corners);
-       calculateCorners(corners, true);
-       calculatePerspectiveMatrix();
+       if (this->m_motion_blur_samples == 1) {
+               readCornersFromTrack(corners, this->m_framenumber);
+               calculateCorners(corners, true, 0);
+       }
+       else {
+               const float frame = (float)this->m_framenumber - this->m_motion_blur_shutter;
+               const float frame_step = (this->m_motion_blur_shutter * 2.0f) / this->m_motion_blur_samples;
+               float frame_iter = frame;
+               for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) {
+                       readCornersFromTrack(corners, frame_iter);
+                       calculateCorners(corners, true, sample);
+                       frame_iter += frame_step;
+               }
+       }
 }
index 3c5dd78354263dc348d97ab0f30995e50eac2ba5..b355c64a1ca65a9f72f328330c009780781feafd 100644 (file)
@@ -43,7 +43,7 @@ protected:
        /* note: this class is not an operation itself (to prevent virtual inheritance issues)
         * implementation classes must make wrappers to use these methods, see below.
         */
-       void readCornersFromTrack(float corners[4][2]);
+       void readCornersFromTrack(float corners[4][2], float frame);
        void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
 
 public:
index 394d148de544500c9d97e4eb370d237abf473e60..c986a249663daaa923cc10026a80dd59d6bee062 100644 (file)
@@ -2314,6 +2314,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
 static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
 {
        bNode *node = ptr->data;
+       NodePlaneTrackDeformData *data = node->storage;
 
        uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
 
@@ -2342,6 +2343,12 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P
                        uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
                }
        }
+
+       uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
+       if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) {
+               uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
+               uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
+       }
 }
 
 static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
index 5d1793e479aef8da412fdb6a45af270bea0f83ac..f08b3ea95907d3d7813e0444f99b7633b9b086d5 100644 (file)
@@ -825,6 +825,10 @@ typedef struct NodeTranslateData {
 typedef struct NodePlaneTrackDeformData {
        char tracking_object[64];
        char plane_track_name[64];
+       char flag;
+       char motion_blur_samples;
+       char pad[2];
+       float motion_blur_shutter;
 } NodePlaneTrackDeformData;
 
 typedef struct NodeShaderScript {
@@ -1080,4 +1084,11 @@ enum {
 /* viewer and cmposite output */
 #define CMP_NODE_OUTPUT_IGNORE_ALPHA           1
 
+/* Plane track deform node */
+enum {
+       CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR = 1,
+};
+
+#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
+
 #endif
index 7f574c41b1f2a9e241190f412e6d6896f44b9646..8d2a44136e81836a962c4187a9f61a055af03001 100644 (file)
@@ -6231,6 +6231,21 @@ static void def_cmp_planetrackdeform(StructRNA *srna)
        RNA_def_property_string_sdna(prop, NULL, "plane_track_name");
        RNA_def_property_ui_text(prop, "Plane Track", "");
        RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR);
+       RNA_def_property_ui_text(prop, "Motion Blur", "Use multi-sampled motion blur of the mask");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "motion_blur_samples", PROP_INT, PROP_NONE);
+       RNA_def_property_range(prop, 1, CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX);
+       RNA_def_property_ui_text(prop, "Samples", "Number of motion blur samples");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_range(prop, 0.0, 1.0f);
+       RNA_def_property_ui_text(prop, "Shutter", "Exposure for motion blur as a factor of FPS");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 }
 
 static void def_cmp_sunbeams(StructRNA *srna)
index 7a15d6364dca4210737722d12c1e8fa9943386ab..415427c360fca5294a83556cd8d5679ba92ad0a9 100644 (file)
@@ -47,7 +47,8 @@ static bNodeSocketTemplate cmp_node_planetrackdeform_out[] = {
 static void init(bNodeTree *UNUSED(ntree), bNode *node)
 {
        NodePlaneTrackDeformData *data = MEM_callocN(sizeof(NodePlaneTrackDeformData), "node plane track deform data");
-
+       data->motion_blur_samples = 16;
+       data->motion_blur_shutter = 0.5f;
        node->storage = data;
 }