minor refactor for rect functions. more consistent naming.
[blender.git] / source / blender / compositor / operations / COM_KeyingScreenOperation.cpp
index 757afe7b39439fb1caadcf2a7d0ccffb61b2f559..87a8fd2275837bfe17086011f185d9b7b1133263 100644 (file)
@@ -39,25 +39,25 @@ extern "C" {
        #include "IMB_imbuf_types.h"
 }
 
-KeyingScreenOperation::KeyingScreenOperation(): NodeOperation()
+KeyingScreenOperation::KeyingScreenOperation() : NodeOperation()
 {
        this->addOutputSocket(COM_DT_COLOR);
-       this->movieClip = NULL;
-       this->framenumber = 0;
-       this->trackingObject[0] = 0;
+       this->m_movieClip = NULL;
+       this->m_framenumber = 0;
+       this->m_trackingObject[0] = 0;
        setComplex(true);
 }
 
 void KeyingScreenOperation::initExecution()
 {
        initMutex();
-       this->cachedTriangulation = NULL;
+       this->m_cachedTriangulation = NULL;
 }
 
 void KeyingScreenOperation::deinitExecution()
 {
-       if (this->cachedTriangulation) {
-               TriangulationData *triangulation = cachedTriangulation;
+       if (this->m_cachedTriangulation) {
+               TriangulationData *triangulation = this->m_cachedTriangulation;
 
                if (triangulation->triangulated_points)
                        MEM_freeN(triangulation->triangulated_points);
@@ -65,9 +65,12 @@ void KeyingScreenOperation::deinitExecution()
                if (triangulation->triangles)
                        MEM_freeN(triangulation->triangles);
 
-               MEM_freeN(this->cachedTriangulation);
+               if (triangulation->triangles_AABB)
+                       MEM_freeN(triangulation->triangles_AABB);
 
-               this->cachedTriangulation = NULL;
+               MEM_freeN(this->m_cachedTriangulation);
+
+               this->m_cachedTriangulation = NULL;
        }
 }
 
@@ -75,7 +78,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
 {
        MovieClipUser user = {0};
        TriangulationData *triangulation;
-       MovieTracking *tracking = &movieClip->tracking;
+       MovieTracking *tracking = &this->m_movieClip->tracking;
        MovieTrackingTrack *track;
        VoronoiSite *sites;
        ImBuf *ibuf;
@@ -85,25 +88,43 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
        int i;
        int width = this->getWidth();
        int height = this->getHeight();
+       int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
 
-       if (this->trackingObject[0]) {
-               MovieTrackingObject *object = BKE_tracking_named_object(tracking, this->trackingObject);
+       if (this->m_trackingObject[0]) {
+               MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->m_trackingObject);
 
                if (!object)
                        return NULL;
 
-               tracksbase = BKE_tracking_object_tracks(tracking, object);
+               tracksbase = BKE_tracking_object_get_tracks(tracking, object);
        }
        else
-               tracksbase = BKE_tracking_get_tracks(tracking);
+               tracksbase = BKE_tracking_get_active_tracks(tracking);
+
+       /* count sites */
+       for (track = (MovieTrackingTrack *) tracksbase->first, sites_total = 0; track; track = track->next) {
+               MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame);
+               float pos[2];
+
+               if (marker->flag & MARKER_DISABLED)
+                       continue;
+
+               add_v2_v2v2(pos, marker->pos, track->offset);
 
-       sites_total = BLI_countlist(tracksbase);
+               if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) ||
+                   !IN_RANGE_INCL(pos[1], 0.0f, 1.0f))
+               {
+                       continue;
+               }
+
+               sites_total++;
+       }
 
        if (!sites_total)
                return NULL;
 
-       BKE_movieclip_user_set_frame(&user, framenumber);
-       ibuf = BKE_movieclip_get_ibuf(movieClip, &user);
+       BKE_movieclip_user_set_frame(&user, clip_frame);
+       ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, &user);
 
        if (!ibuf)
                return NULL;
@@ -112,12 +133,27 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
 
        sites = (VoronoiSite *) MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites");
        track = (MovieTrackingTrack *) tracksbase->first;
-       i = 0;
-       while (track) {
-               VoronoiSite *site = &sites[i];
-               MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenumber);
-               ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE);
+       for (track = (MovieTrackingTrack *) tracksbase->first, i = 0; track; track = track->next, i++) {
+               MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame);
+               VoronoiSite *site;
+               ImBuf *pattern_ibuf;
                int j;
+               float pos[2];
+
+               if (marker->flag & MARKER_DISABLED)
+                       continue;
+
+               add_v2_v2v2(pos, marker->pos, track->offset);
+
+               if (!IN_RANGE_INCL(pos[0], 0.0f, 1.0f) ||
+                   !IN_RANGE_INCL(pos[1], 0.0f, 1.0f))
+               {
+                       continue;
+               }
+
+               site = &sites[i];
+
+               pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE);
 
                zero_v3(site->color);
                for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) {
@@ -136,11 +172,8 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
                mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y));
                IMB_freeImBuf(pattern_ibuf);
 
-               site->co[0] = marker->pos[0] * width;
-               site->co[1] = marker->pos[1] * height;
-
-               track = track->next;
-               i++;
+               site->co[0] = pos[0] * width;
+               site->co[1] = pos[1] * height;
        }
 
        IMB_freeImBuf(ibuf);
@@ -149,29 +182,105 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri
 
        BLI_voronoi_triangulate(sites, sites_total, &edges, width, height,
                                &triangulation->triangulated_points, &triangulation->triangulated_points_total,
-                            &triangulation->triangles, &triangulation->triangles_total);
+                               &triangulation->triangles, &triangulation->triangles_total);
 
        MEM_freeN(sites);
        BLI_freelistN(&edges);
 
+       if (triangulation->triangles_total) {
+               rctf *rect;
+               rect = triangulation->triangles_AABB =
+                       (rctf *) MEM_callocN(sizeof(rctf) * triangulation->triangles_total, "voronoi triangulation AABB");
+
+               for (i = 0; i < triangulation->triangles_total; i++, rect++) {
+                       int *triangle = triangulation->triangles[i];
+                       VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]],
+                                                 *b = &triangulation->triangulated_points[triangle[1]],
+                                                 *c = &triangulation->triangulated_points[triangle[2]];
+
+                       float min[2], max[2];
+
+                       INIT_MINMAX2(min, max);
+
+                       DO_MINMAX2(a->co, min, max);
+                       DO_MINMAX2(b->co, min, max);
+                       DO_MINMAX2(c->co, min, max);
+
+                       rect->xmin = min[0];
+                       rect->ymin = min[1];
+
+                       rect->xmax = max[0];
+                       rect->ymax = max[1];
+               }
+       }
+
        return triangulation;
 }
 
-void *KeyingScreenOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
+void *KeyingScreenOperation::initializeTileData(rcti *rect)
 {
-       if (this->movieClip == NULL)
+       TileData *tile_data;
+       TriangulationData *triangulation;
+       int triangles_allocated = 0;
+       int chunk_size = 20;
+       int i;
+       rctf rect_float;
+
+       if (this->m_movieClip == NULL)
+               return NULL;
+
+       if (!this->m_cachedTriangulation) {
+               lockMutex();
+               if (this->m_cachedTriangulation == NULL) {
+                       this->m_cachedTriangulation = buildVoronoiTriangulation();
+               }
+               unlockMutex();
+       }
+
+       triangulation = this->m_cachedTriangulation;
+
+       if (!triangulation)
                return NULL;
 
-       if (this->cachedTriangulation)
-               return this->cachedTriangulation;
+       BLI_rctf_init(&rect_float, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+
+       tile_data = (TileData *) MEM_callocN(sizeof(TileData), "keying screen tile data");
+
+       for (i = 0; i < triangulation->triangles_total; i++) {
+               bool ok = BLI_rctf_isect(&rect_float, &triangulation->triangles_AABB[i], NULL);
+
+               if (ok) {
+                       tile_data->triangles_total++;
+
+                       if (tile_data->triangles_total > triangles_allocated) {
+                               if (!tile_data->triangles) {
+                                       tile_data->triangles = (int *) MEM_mallocN(sizeof(int) * chunk_size,
+                                                                                  "keying screen tile triangles chunk");
+                               }
+                               else {
+                                       tile_data->triangles = (int *) MEM_reallocN(tile_data->triangles,
+                                                                                   sizeof(int) * (triangles_allocated + chunk_size));
+                               }
+
+                               triangles_allocated += chunk_size;
+                       }
+
+                       tile_data->triangles[tile_data->triangles_total - 1] = i;
+               }
+       }
+
+       return tile_data;
+}
+
+void KeyingScreenOperation::deinitializeTileData(rcti *rect, void *data)
+{
+       TileData *tile_data = (TileData *) data;
 
-       lockMutex();
-       if (this->cachedTriangulation == NULL) {
-               this->cachedTriangulation = buildVoronoiTriangulation();
+       if (tile_data->triangles) {
+               MEM_freeN(tile_data->triangles);
        }
-       unlockMutex();
 
-       return this->cachedTriangulation;
+       MEM_freeN(tile_data);
 }
 
 void KeyingScreenOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[])
@@ -179,40 +288,51 @@ void KeyingScreenOperation::determineResolution(unsigned int resolution[], unsig
        resolution[0] = 0;
        resolution[1] = 0;
 
-       if (this->movieClip) {
+       if (this->m_movieClip) {
                MovieClipUser user = {0};
                int width, height;
+               int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
 
-               BKE_movieclip_user_set_frame(&user, framenumber);
-               BKE_movieclip_get_size(this->movieClip, &user, &width, &height);
+               BKE_movieclip_user_set_frame(&user, clip_frame);
+               BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height);
 
                resolution[0] = width;
                resolution[1] = height;
        }
 }
 
-void KeyingScreenOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data)
+void KeyingScreenOperation::executePixel(float *color, int x, int y, void *data)
 {
        color[0] = 0.0f;
        color[1] = 0.0f;
        color[2] = 0.0f;
        color[3] = 1.0f;
 
-       if (this->movieClip && data) {
-               TriangulationData *triangulation = (TriangulationData *) data;
+       if (this->m_movieClip && data) {
+               TriangulationData *triangulation = this->m_cachedTriangulation;
+               TileData *tile_data = (TileData *) data;
                int i;
-               for (i = 0; i < triangulation->triangles_total; i++) {
-                       int *triangle = triangulation->triangles[i];
-                       VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]],
-                                                 *b = &triangulation->triangulated_points[triangle[1]],
-                                                 *c = &triangulation->triangulated_points[triangle[2]];
-                       float co[2] = {(float) x, (float) y}, w[3];
-
-                       if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) {
-                               if (barycentric_inside_triangle_v2(w)) {
-                                       color[0] += a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2];
-                                       color[1] += a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2];
-                                       color[2] += a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2];
+               float co[2] = {(float) x, (float) y};
+
+               for (i = 0; i < tile_data->triangles_total; i++) {
+                       int triangle_idx = tile_data->triangles[i];
+                       rctf *rect = &triangulation->triangles_AABB[triangle_idx];
+
+                       if (IN_RANGE_INCL(x, rect->xmin, rect->xmax) && IN_RANGE_INCL(y, rect->ymin, rect->ymax)) {
+                               int *triangle = triangulation->triangles[triangle_idx];
+                               VoronoiTriangulationPoint *a = &triangulation->triangulated_points[triangle[0]],
+                                                         *b = &triangulation->triangulated_points[triangle[1]],
+                                                         *c = &triangulation->triangulated_points[triangle[2]];
+                               float w[3];
+
+                               if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) {
+                                       if (barycentric_inside_triangle_v2(w)) {
+                                               color[0] = a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2];
+                                               color[1] = a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2];
+                                               color[2] = a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2];
+
+                                               break;
+                                       }
                                }
                        }
                }