/* get memory buffer for first uncached frame within prefetch frame range */ static unsigned char *prefetch_thread_next_frame( PrefetchQueue *queue, MovieClip *clip, size_t *r_size, int *r_current_frame) { unsigned char *mem = NULL; BLI_spin_lock(&queue->spin); if (!*queue->stop && !check_prefetch_break() && IN_RANGE_INCL(queue->current_frame, queue->start_frame, queue->end_frame)) { int current_frame; if (queue->forward) { current_frame = prefetch_find_uncached_frame(clip, queue->current_frame + 1, queue->end_frame, queue->render_size, queue->render_flag, 1); /* switch direction if read frames from current up to scene end frames */ if (current_frame > queue->end_frame) { queue->current_frame = queue->initial_frame; queue->forward = false; } } if (!queue->forward) { current_frame = prefetch_find_uncached_frame(clip, queue->current_frame - 1, queue->start_frame, queue->render_size, queue->render_flag, -1); } if (IN_RANGE_INCL(current_frame, queue->start_frame, queue->end_frame)) { int frames_processed; mem = prefetch_read_file_to_memory(clip, current_frame, queue->render_size, queue->render_flag, r_size); *r_current_frame = current_frame; queue->current_frame = current_frame; if (queue->forward) { frames_processed = queue->current_frame - queue->initial_frame; } else { frames_processed = (queue->end_frame - queue->initial_frame) + (queue->initial_frame - queue->current_frame); } *queue->do_update = 1; *queue->progress = (float)frames_processed / (queue->end_frame - queue->start_frame); } } BLI_spin_unlock(&queue->spin); return mem; }
static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, short channelLocked) { ActKeyColumn *ak; ActKeyBlock *ab; float alpha; float xscale; float iconsize = U.widget_unit / 4.0f; glEnable(GL_BLEND); /* get View2D scaling factor */ UI_view2d_scale_get(v2d, &xscale, NULL); /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */ /* TODO: allow this opacity factor to be themed? */ alpha = (channelLocked) ? 0.25f : 1.0f; /* draw keyblocks */ if (blocks) { float sel_color[4], unsel_color[4]; /* cache colours first */ UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color); UI_GetThemeColor4fv(TH_STRIP, unsel_color); sel_color[3] *= alpha; unsel_color[3] *= alpha; /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */ for (ab = blocks->first; ab; ab = ab->next) { if (actkeyblock_is_valid(ab, keys)) { /* draw block */ if (ab->sel) glColor4fv(sel_color); else glColor4fv(unsel_color); glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize); } } } /* draw keys */ if (keys) { for (ak = keys->first; ak; ak = ak->next) { /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw * - this might give some improvements, since we current have to flip between view/region matrices */ if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0) continue; /* draw using OpenGL - uglier but faster */ /* NOTE1: a previous version of this didn't work nice for some intel cards * NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */ draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha); } } glDisable(GL_BLEND); }
static void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_coord) { const float corners[4][2] = { {0.0f, 0.0f}, {width - 1, 0.0f}, {width - 1, height - 1}, {0.0f, height - 1}}; int i; if (IN_RANGE_INCL(coord[0], 0, width - 1) && IN_RANGE_INCL(coord[1], 0, height - 1)) { return; } for (i = 0; i < 4; i++) { float v1[2], v2[2]; float p[2]; copy_v2_v2(v1, corners[i]); if (i == 3) { copy_v2_v2(v2, corners[0]); } else { copy_v2_v2(v2, corners[i + 1]); } if (isect_seg_seg_v2_point(v1, v2, coord, other_coord, p) == 1) { if (i == 0 && coord[1] > p[1]) { continue; } if (i == 1 && coord[0] < p[0]) { continue; } if (i == 2 && coord[1] < p[1]) { continue; } if (i == 3 && coord[0] > p[0]) { continue; } copy_v2_v2(coord, p); } } }
void KeyingScreenOperation::executePixel(float output[4], int x, int y, void *data) { output[0] = 0.0f; output[1] = 0.0f; output[2] = 0.0f; output[3] = 1.0f; if (this->m_movieClip && data) { TriangulationData *triangulation = this->m_cachedTriangulation; TileData *tile_data = (TileData *) data; int i; 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)) { output[0] = a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2]; output[1] = a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2]; output[2] = a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2]; break; } } } } } }
/* Try to find NLA Strip to use for action layer up/down tool */ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) { NlaStrip *strip; for (strip = strips->first; strip; strip = strip->next) { /* Can we use this? */ if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { /* in range - use this one */ return strip; } else if ((ctime < strip->start) && (strip->prev == NULL)) { /* before first - use this one */ return strip; } else if ((ctime > strip->end) && (strip->next == NULL)) { /* after last - use this one */ return strip; } } /* nothing suitable found... */ return NULL; }
static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset) { float factor = 1.0f, offset = 0.0f; if (flag & ANIM_UNITCONV_RESTORE) { if (r_offset) *r_offset = fcu->prev_offset; return 1.0f / fcu->prev_norm_factor; } if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) { if (r_offset) *r_offset = fcu->prev_offset; if (fcu->prev_norm_factor == 0.0f) { /* Happens when Auto Normalize was disabled before * any curves were displayed. */ return 1.0f; } return fcu->prev_norm_factor; } if (G.moving & G_TRANSFORM_FCURVES) { if (r_offset) *r_offset = fcu->prev_offset; if (fcu->prev_norm_factor == 0.0f) { /* Same as above. */ return 1.0f; } return fcu->prev_norm_factor; } fcu->prev_norm_factor = 1.0f; if (fcu->bezt) { BezTriple *bezt; int i; float max_coord = -FLT_MAX; float min_coord = FLT_MAX; float range; if (fcu->totvert < 1) { return 1.0f; } if (PRVRANGEON) { for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { max_coord = max_ff(max_coord, bezt->vec[0][1]); max_coord = max_ff(max_coord, bezt->vec[1][1]); max_coord = max_ff(max_coord, bezt->vec[2][1]); min_coord = min_ff(min_coord, bezt->vec[0][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); min_coord = min_ff(min_coord, bezt->vec[2][1]); } } } else { for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { max_coord = max_ff(max_coord, bezt->vec[0][1]); max_coord = max_ff(max_coord, bezt->vec[1][1]); max_coord = max_ff(max_coord, bezt->vec[2][1]); min_coord = min_ff(min_coord, bezt->vec[0][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); min_coord = min_ff(min_coord, bezt->vec[2][1]); } } range = max_coord - min_coord; if (range > FLT_EPSILON) { factor = 2.0f / range; } offset = -min_coord - range / 2.0f; } BLI_assert(factor != 0.0f); if (r_offset) { *r_offset = offset; } fcu->prev_norm_factor = factor; fcu->prev_offset = offset; return factor; }
KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTriangulation() { MovieClipUser user = {0}; TriangulationData *triangulation; MovieTracking *tracking = &this->m_movieClip->tracking; MovieTrackingTrack *track; VoronoiSite *sites, *site; ImBuf *ibuf; ListBase *tracksbase; ListBase edges = {NULL, NULL}; int sites_total; 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->m_trackingObject[0]) { MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->m_trackingObject); if (!object) return NULL; tracksbase = BKE_tracking_object_get_tracks(tracking, object); } else 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); 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, clip_frame); ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, &user); if (!ibuf) return NULL; triangulation = (TriangulationData *) MEM_callocN(sizeof(TriangulationData), "keying screen triangulation data"); sites = (VoronoiSite *) MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites"); track = (MovieTrackingTrack *) tracksbase->first; for (track = (MovieTrackingTrack *) tracksbase->first, site = sites; track; track = track->next) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); 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; } pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); zero_v3(site->color); if (pattern_ibuf) { for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { if (pattern_ibuf->rect_float) { add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); } else { unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); } } mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); IMB_freeImBuf(pattern_ibuf); } site->co[0] = pos[0] * width; site->co[1] = pos[1] * height; site++; } IMB_freeImBuf(ibuf); BLI_voronoi_compute(sites, sites_total, width, height, &edges); BLI_voronoi_triangulate(sites, sites_total, &edges, width, height, &triangulation->triangulated_points, &triangulation->triangulated_points_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); minmax_v2v2_v2(min, max, a->co); minmax_v2v2_v2(min, max, b->co); minmax_v2v2_v2(min, max, c->co); rect->xmin = min[0]; rect->ymin = min[1]; rect->xmax = max[0]; rect->ymax = max[1]; } } return triangulation; }
static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset) { float factor = 1.0f, offset = 0.0f; if (flag & ANIM_UNITCONV_RESTORE) { if (r_offset) *r_offset = fcu->prev_offset; return 1.0f / fcu->prev_norm_factor; } if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) { if (r_offset) *r_offset = fcu->prev_offset; if (fcu->prev_norm_factor == 0.0f) { /* Happens when Auto Normalize was disabled before * any curves were displayed. */ return 1.0f; } return fcu->prev_norm_factor; } if (G.moving & G_TRANSFORM_FCURVES) { if (r_offset) *r_offset = fcu->prev_offset; if (fcu->prev_norm_factor == 0.0f) { /* Same as above. */ return 1.0f; } return fcu->prev_norm_factor; } fcu->prev_norm_factor = 1.0f; if (fcu->bezt) { const bool use_preview_only = PRVRANGEON; const BezTriple *bezt; int i; float max_coord = -FLT_MAX; float min_coord = FLT_MAX; float range; if (fcu->totvert < 1) { return 1.0f; } for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { continue; } if (i == 0) { /* We ignore extrapolation flags and handle here, and use the * control point position only. so we normalize "interesting" * part of the curve. * * Here we handle left extrapolation. */ max_coord = max_ff(max_coord, bezt->vec[1][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); } else { const BezTriple *prev_bezt = bezt - 1; if (prev_bezt->ipo == BEZT_IPO_CONST) { /* Constant interpolation: previous CV value is used up * to the current keyframe. */ max_coord = max_ff(max_coord, bezt->vec[1][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); } else if (prev_bezt->ipo == BEZT_IPO_LIN) { /* Linear interpolation: min/max using both previous and * and current CV. */ max_coord = max_ff(max_coord, bezt->vec[1][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); } else if (prev_bezt->ipo == BEZT_IPO_BEZ) { const int resol = fcu->driver ? 32 : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32); if (resol < 2) { max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); } else { float data[120]; float v1[2], v2[2], v3[2], v4[2]; v1[0] = prev_bezt->vec[1][0]; v1[1] = prev_bezt->vec[1][1]; v2[0] = prev_bezt->vec[2][0]; v2[1] = prev_bezt->vec[2][1]; v3[0] = bezt->vec[0][0]; v3[1] = bezt->vec[0][1]; v4[0] = bezt->vec[1][0]; v4[1] = bezt->vec[1][1]; correct_bezpart(v1, v2, v3, v4); BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); for (int j = 0; j <= resol; ++j) { const float *fp = &data[j * 3]; max_coord = max_ff(max_coord, fp[1]); min_coord = min_ff(min_coord, fp[1]); } } } } } if (max_coord > min_coord) { range = max_coord - min_coord; if (range > FLT_EPSILON) { factor = 2.0f / range; } offset = -min_coord - range / 2.0f; } else if (max_coord == min_coord) { factor = 1.0f; offset = -min_coord; } } BLI_assert(factor != 0.0f); if (r_offset) { *r_offset = offset; } fcu->prev_norm_factor = factor; fcu->prev_offset = offset; return factor; }