diff options
Diffstat (limited to 'source/blender/compositor/operations/COM_KeyingScreenOperation.cpp')
-rw-r--r-- | source/blender/compositor/operations/COM_KeyingScreenOperation.cpp | 189 |
1 files changed, 143 insertions, 46 deletions
diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 9f7b69636ab..53572162b9e 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -42,22 +42,22 @@ extern "C" { 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,10 +88,10 @@ 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->movieClip, framenumber); + int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); - if (this->trackingObject[0]) { - MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->trackingObject); + if (this->m_trackingObject[0]) { + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->m_trackingObject); if (!object) return NULL; @@ -98,13 +101,20 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri else tracksbase = BKE_tracking_get_active_tracks(tracking); - sites_total = BLI_countlist(tracksbase); + /* count sites */ + for (track = (MovieTrackingTrack *) tracksbase->first, sites_total = 0; track; track = track->next) { + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); + + if ((marker->flag & MARKER_DISABLED) == 0) { + sites_total++; + } + } if (!sites_total) return NULL; BKE_movieclip_user_set_frame(&user, clip_frame); - ibuf = BKE_movieclip_get_ibuf(movieClip, &user); + ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, &user); if (!ibuf) return NULL; @@ -113,13 +123,19 @@ 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]; + for (track = (MovieTrackingTrack *) tracksbase->first, i = 0; track; track = track->next, i++) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); - ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); + VoronoiSite *site; + ImBuf *pattern_ibuf; int j; + if (marker->flag & MARKER_DISABLED) + 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++) { if (pattern_ibuf->rect_float) { @@ -139,9 +155,6 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri site->co[0] = marker->pos[0] * width; site->co[1] = marker->pos[1] * height; - - track = track->next; - i++; } IMB_freeImBuf(ibuf); @@ -155,24 +168,100 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri 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) { - 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->cachedTriangulation) - return this->cachedTriangulation; + if (!this->m_cachedTriangulation) { + lockMutex(); + if (this->m_cachedTriangulation == NULL) { + this->m_cachedTriangulation = buildVoronoiTriangulation(); + } + unlockMutex(); + } + + triangulation = this->m_cachedTriangulation; + + if (!triangulation) + return NULL; + + BLI_init_rctf(&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_isect_rctf(&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)); + } - lockMutex(); - if (this->cachedTriangulation == NULL) { - this->cachedTriangulation = buildVoronoiTriangulation(); + triangles_allocated += chunk_size; + } + + tile_data->triangles[tile_data->triangles_total - 1] = i; + } } - unlockMutex(); - return this->cachedTriangulation; + return tile_data; +} + +void KeyingScreenOperation::deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data) +{ + TileData *tile_data = (TileData *) data; + + if (tile_data->triangles) { + MEM_freeN(tile_data->triangles); + } + + MEM_freeN(tile_data); } void KeyingScreenOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[]) @@ -180,13 +269,13 @@ 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->movieClip, framenumber); + int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); BKE_movieclip_user_set_frame(&user, clip_frame); - BKE_movieclip_get_size(this->movieClip, &user, &width, &height); + BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); resolution[0] = width; resolution[1] = height; @@ -200,21 +289,29 @@ void KeyingScreenOperation::executePixel(float *color, int x, int y, MemoryBuffe 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]; + } } } } |