/** * \note use #ED_view3d_ob_project_mat_get to get the projection matrix */ void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r_co[2], float mat[4][4]) { float vec4[4]; copy_v3_v3(vec4, co); vec4[3] = 1.0; /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ mul_m4_v4(mat, vec4); if (vec4[3] > FLT_EPSILON) { r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; } else { zero_v2(r_co); } }
ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]) { ScanFillVert *sf_v; sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert)); BLI_addtail(&sf_ctx->fillvertbase, sf_v); sf_v->tmp.p = NULL; copy_v3_v3(sf_v->co, vec); /* just zero out the rest */ zero_v2(sf_v->xy); sf_v->keyindex = 0; sf_v->poly_nr = sf_ctx->poly_nr; sf_v->edge_tot = 0; sf_v->f = SF_VERT_NEW; sf_v->user_flag = 0; return sf_v; }
static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; /* parent info */ SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking; MovieTrackingTrack *track; MovieTrackingPlaneTrack *plane_track; MovieTrackingObject *tracking_object; /* done */ int framenr, parent_type; float parmask_pos[2], orig_corners[4][2]; char *sub_parent_name; if (ELEM(NULL, sc, clip)) { return OPERATOR_CANCELLED; } framenr = ED_space_clip_get_clip_frame_number(sc); tracking = &clip->tracking; tracking_object = BKE_tracking_object_get_active(&clip->tracking); if (tracking_object == NULL) { return OPERATOR_CANCELLED; } if ((track = BKE_tracking_track_get_active(tracking)) != NULL) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); float marker_pos_ofs[2]; add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs); sub_parent_name = track->name; parent_type = MASK_PARENT_POINT_TRACK; memset(orig_corners, 0, sizeof(orig_corners)); } else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) { MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr); zero_v2(parmask_pos); sub_parent_name = plane_track->name; parent_type = MASK_PARENT_PLANE_TRACK; memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners)); } else { return OPERATOR_CANCELLED; } for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } for (spline = masklay->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(point)) { point->parent.id_type = ID_MC; point->parent.id = &clip->id; point->parent.type = parent_type; BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent)); BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent)); copy_v2_v2(point->parent.parent_orig, parmask_pos); memcpy(point->parent.parent_corners_orig, orig_corners, sizeof(point->parent.parent_corners_orig)); } } } } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; }
void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) { MovieClip *clip = ED_space_clip_get_clip(sc); Scene *scene = CTX_data_scene(C); ImBuf *ibuf = NULL; int width, height; float zoomx, zoomy; ED_space_clip_get_size(sc, &width, &height); ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy); /* if no clip, nothing to do */ if (!clip) { ED_region_grid_draw(ar, zoomx, zoomy); return; } if (sc->flag & SC_SHOW_STABLE) { float smat[4][4], ismat[4][4]; ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle); if (ibuf) { float translation[2]; float aspect = clip->tracking.camera.pixel_aspect; if (width != ibuf->x) mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x); else copy_v2_v2(translation, sc->loc); BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, sc->scale, sc->angle, sc->stabmat); unit_m4(smat); smat[0][0] = 1.0f / width; smat[1][1] = 1.0f / height; invert_m4_m4(ismat, smat); mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL); } } else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) { ibuf = ED_space_clip_get_buffer(sc); zero_v2(sc->loc); sc->scale = 1.0f; unit_m4(sc->stabmat); unit_m4(sc->unistabmat); } if (ibuf) { draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy); IMB_freeImBuf(ibuf); } else if (sc->flag & SC_MUTE_FOOTAGE) { draw_movieclip_muted(ar, width, height, zoomx, zoomy); } else { ED_region_grid_draw(ar, zoomx, zoomy); } if (width && height) { draw_stabilization_border(sc, ar, width, height, zoomx, zoomy); draw_tracking_tracks(sc, scene, ar, clip, width, height, zoomx, zoomy); draw_distortion(sc, ar, clip, width, height, zoomx, zoomy); } }
static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, int width, int height, float zoomx, float zoomy) { float x, y; const int n = 10; int i, j, a; float pos[2], tpos[2], grid[11][11][2]; MovieTracking *tracking = &clip->tracking; bGPdata *gpd = NULL; float aspy = 1.0f / tracking->camera.pixel_aspect; float dx = (float)width / n, dy = (float)height / n * aspy; float offsx = 0.0f, offsy = 0.0f; if (!tracking->camera.focal) return; if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0) return; UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y); glPushMatrix(); glTranslatef(x, y, 0); glScalef(zoomx, zoomy, 0); glMultMatrixf(sc->stabmat); glScalef(width, height, 0); /* grid */ if (sc->flag & SC_SHOW_GRID) { float val[4][2], idx[4][2]; float min[2], max[2]; for (a = 0; a < 4; a++) { if (a < 2) val[a][a % 2] = FLT_MAX; else val[a][a % 2] = -FLT_MAX; } zero_v2(pos); for (i = 0; i <= n; i++) { for (j = 0; j <= n; j++) { if (i == 0 || j == 0 || i == n || j == n) { BKE_tracking_distort_v2(tracking, pos, tpos); for (a = 0; a < 4; a++) { int ok; if (a < 2) ok = tpos[a % 2] < val[a][a % 2]; else ok = tpos[a % 2] > val[a][a % 2]; if (ok) { copy_v2_v2(val[a], tpos); idx[a][0] = j; idx[a][1] = i; } } } pos[0] += dx; } pos[0] = 0.0f; pos[1] += dy; } INIT_MINMAX2(min, max); for (a = 0; a < 4; a++) { pos[0] = idx[a][0] * dx; pos[1] = idx[a][1] * dy; BKE_tracking_undistort_v2(tracking, pos, tpos); minmax_v2v2_v2(min, max, tpos); } copy_v2_v2(pos, min); dx = (max[0] - min[0]) / n; dy = (max[1] - min[1]) / n; for (i = 0; i <= n; i++) { for (j = 0; j <= n; j++) { BKE_tracking_distort_v2(tracking, pos, grid[i][j]); grid[i][j][0] /= width; grid[i][j][1] /= height * aspy; pos[0] += dx; } pos[0] = min[0]; pos[1] += dy; } glColor3f(1.0f, 0.0f, 0.0f); for (i = 0; i <= n; i++) { glBegin(GL_LINE_STRIP); for (j = 0; j <= n; j++) { glVertex2fv(grid[i][j]); } glEnd(); } for (j = 0; j <= n; j++) { glBegin(GL_LINE_STRIP); for (i = 0; i <= n; i++) { glVertex2fv(grid[i][j]); } glEnd(); } } if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking); if (track) { int framenr = ED_space_clip_get_clip_frame_number(sc); MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); offsx = marker->pos[0]; offsy = marker->pos[1]; gpd = track->gpd; } } else { gpd = clip->gpd; } if (sc->flag & SC_MANUAL_CALIBRATION && gpd) { bGPDlayer *layer = gpd->layers.first; while (layer) { bGPDframe *frame = layer->frames.first; if (layer->flag & GP_LAYER_HIDE) { layer = layer->next; continue; } glColor4fv(layer->color); glLineWidth(layer->thickness); glPointSize((float)(layer->thickness + 2)); while (frame) { bGPDstroke *stroke = frame->strokes.first; while (stroke) { if (stroke->flag & GP_STROKE_2DSPACE) { if (stroke->totpoints > 1) { glBegin(GL_LINE_STRIP); for (i = 0; i < stroke->totpoints - 1; i++) { float npos[2], dpos[2], len; int steps; pos[0] = (stroke->points[i].x + offsx) * width; pos[1] = (stroke->points[i].y + offsy) * height * aspy; npos[0] = (stroke->points[i + 1].x + offsx) * width; npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy; len = len_v2v2(pos, npos); steps = ceil(len / 5.0f); /* we want to distort only long straight lines */ if (stroke->totpoints == 2) { BKE_tracking_undistort_v2(tracking, pos, pos); BKE_tracking_undistort_v2(tracking, npos, npos); } sub_v2_v2v2(dpos, npos, pos); mul_v2_fl(dpos, 1.0f / steps); for (j = 0; j <= steps; j++) { BKE_tracking_distort_v2(tracking, pos, tpos); glVertex2f(tpos[0] / width, tpos[1] / (height * aspy)); add_v2_v2(pos, dpos); } } glEnd(); } else if (stroke->totpoints == 1) { glBegin(GL_POINTS); glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy); glEnd(); } } stroke = stroke->next; } frame = frame->next; } layer = layer->next; } glLineWidth(1.0f); glPointSize(1.0f); } glPopMatrix(); }
static void object_warp_transverts(TransVertStore *tvs, float mat_view[4][4], const float center_view[3], const float angle_, const float min, const float max) { TransVert *tv; int i; const float angle = -angle_; /* cache vars for tiny speedup */ #if 1 const float range = max - min; const float range_inv = 1.0f / range; const float min_ofs = min + (0.5f * range); #endif float dir_min[2], dir_max[2]; float imat_view[4][4]; invert_m4_m4(imat_view, mat_view); /* calculate the direction vectors outside min/max range */ { const float phi = angle * 0.5f; dir_max[0] = cosf(phi); dir_max[1] = sinf(phi); dir_min[0] = -dir_max[0]; dir_min[1] = dir_max[1]; } tv = tvs->transverts; for (i = 0; i < tvs->transverts_tot; i++, tv++) { float co[3], co_add[2]; float val, phi; /* convert objectspace->viewspace */ mul_v3_m4v3(co, mat_view, tv->loc); sub_v2_v2(co, center_view); val = co[0]; /* is overwritten later anyway */ // co[0] = 0.0f; if (val < min) { mul_v2_v2fl(co_add, dir_min, min - val); val = min; } else if (val > max) { mul_v2_v2fl(co_add, dir_max, val - max); val = max; } else { zero_v2(co_add); } /* map from x axis to (-0.5 - 0.5) */ #if 0 val = ((val - min) / (max - min)) - 0.5f; #else val = (val - min_ofs) * range_inv; #endif /* convert the x axis into a rotation */ phi = val * angle; co[0] = -sinf(phi) * co[1]; co[1] = cosf(phi) * co[1]; add_v2_v2(co, co_add); /* convert viewspace->objectspace */ add_v2_v2(co, center_view); mul_v3_m4v3(tv->loc, imat_view, co); } }
/* Stabilize given image buffer using stabilization data for * a specified frame number. * * NOTE: frame number should be in clip space, not scene space */ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf *ibuf, float translation[2], float *scale, float *angle) { float tloc[2], tscale, tangle; MovieTrackingStabilization *stab = &tracking->stabilization; ImBuf *tmpibuf; int width = ibuf->x, height = ibuf->y; float aspect = tracking->camera.pixel_aspect; float mat[4][4]; int j, filter = tracking->stabilization.filter; void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; int ibuf_flags; if (translation) copy_v2_v2(tloc, translation); if (scale) tscale = *scale; /* Perform early output if no stabilization is used. */ if ((stab->flag & TRACKING_2D_STABILIZATION) == 0) { if (translation) zero_v2(translation); if (scale) *scale = 1.0f; if (angle) *angle = 0.0f; return ibuf; } /* Allocate frame for stabilization result. */ ibuf_flags = 0; if (ibuf->rect) ibuf_flags |= IB_rect; if (ibuf->rect_float) ibuf_flags |= IB_rectfloat; tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ibuf_flags); /* Calculate stabilization matrix. */ BKE_tracking_stabilization_data_get(tracking, framenr, width, height, tloc, &tscale, &tangle); BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); invert_m4(mat); if (filter == TRACKING_FILTER_NEAREST) interpolation = nearest_interpolation; else if (filter == TRACKING_FILTER_BILINEAR) interpolation = bilinear_interpolation; else if (filter == TRACKING_FILTER_BICUBIC) interpolation = bicubic_interpolation; else /* fallback to default interpolation method */ interpolation = nearest_interpolation; /* This function is only used for display in clip editor and * sequencer only, which would only benefit of using threads * here. * * But need to keep an eye on this if the function will be * used in other cases. */ #pragma omp parallel for if (tmpibuf->y > 128) for (j = 0; j < tmpibuf->y; j++) { int i; for (i = 0; i < tmpibuf->x; i++) { float vec[3] = {i, j, 0.0f}; mul_v3_m4v3(vec, mat, vec); interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j); } } if (tmpibuf->rect_float) tmpibuf->userflags |= IB_RECT_INVALID; if (translation) copy_v2_v2(translation, tloc); if (scale) *scale = tscale; if (angle) *angle = tangle; return tmpibuf; }