Blender V5.0
transform_convert_tracking.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_space_types.h"
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_listbase.h"
14#include "BLI_math_matrix.h"
15#include "BLI_math_vector.h"
16
17#include "BKE_context.hh"
18#include "BKE_movieclip.h"
20#include "BKE_tracking.h"
21
22#include "ED_clip.hh"
23
24#include "WM_api.hh"
25
26#include "transform.hh"
27#include "transform_convert.hh"
28
29namespace blender::ed::transform {
30
32 int mode;
33 int flag;
34
35 /* Tracks transformation from main window. */
36 int area;
37 const float *relative, *loc;
38 float soffset[2], srelative[2];
39 float offset[2];
40
45
48};
49
54
55/* -------------------------------------------------------------------- */
58
61
64
65 /* NOTE: These pointers will be `nullptr` during counting step.
66 * This means, that the transformation data initialization functions are to increment
67 * `tc->data_len` instead of filling in the transformation data when these pointers are
68 * `nullptr`. For simplicity, check the `current.td` against `nullptr`.
69 * Do not `tc->data_len` when filling in the transformation data. */
70 struct {
75};
76
78 MovieTrackingTrack *track,
79 MovieTrackingMarker *marker,
80 int area,
81 float loc[2],
82 const float rel[2],
83 const float off[2],
84 const float aspect[2])
85{
86 TransData *td = init_context->current.td;
87 TransData2D *td2d = init_context->current.td2d;
88 TransDataTracking *tdt = init_context->current.tdt;
89
90 if (td == nullptr) {
91 init_context->tc->data_len++;
92 return;
93 }
94
95 int anchor = area == TRACK_AREA_POINT && off;
96
97 tdt->flag = marker->flag;
98 tdt->framenr = marker->framenr;
100
101 if (anchor) {
102 td2d->loc[0] = rel[0] * aspect[0]; /* Hold original location. */
103 td2d->loc[1] = rel[1] * aspect[1];
104
105 tdt->loc = loc;
106 td2d->loc2d = loc; /* Current location. */
107 }
108 else {
109 td2d->loc[0] = loc[0] * aspect[0]; /* Hold original location. */
110 td2d->loc[1] = loc[1] * aspect[1];
111
112 td2d->loc2d = loc; /* Current location. */
113 }
114 td2d->loc[2] = 0.0f;
115
116 tdt->relative = rel;
117 tdt->area = area;
118
119 tdt->markersnr = track->markersnr;
120 tdt->markers = track->markers;
121 tdt->track = track;
122
123 if (rel) {
124 if (!anchor) {
125 td2d->loc[0] += rel[0] * aspect[0];
126 td2d->loc[1] += rel[1] * aspect[1];
127 }
128
129 copy_v2_v2(tdt->srelative, rel);
130 }
131
132 if (off) {
133 copy_v2_v2(tdt->soffset, off);
134 }
135
136 td->flag = 0;
137 td->loc = td2d->loc;
138 copy_v3_v3(td->iloc, td->loc);
139
140 // copy_v3_v3(td->center, td->loc);
142 td->center[0] = marker->pos[0] * aspect[0];
143 td->center[1] = marker->pos[1] * aspect[1];
144
145 memset(td->axismtx, 0, sizeof(td->axismtx));
146 td->axismtx[2][2] = 1.0f;
147
148 td->val = nullptr;
149
150 td->flag |= TD_SELECTED;
151 td->dist = 0.0;
152
153 unit_m3(td->mtx);
154 unit_m3(td->smtx);
155
156 init_context->current.td++;
157 init_context->current.td2d++;
158 init_context->current.tdt++;
159}
160
162 const int framenr,
163 MovieTrackingTrack *track,
164 const float aspect[2])
165{
166 MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
167
169 track,
170 marker,
172 track->offset,
173 marker->pos,
174 track->offset,
175 aspect);
176
177 if (track->flag & SELECT) {
179 init_context, track, marker, TRACK_AREA_POINT, marker->pos, nullptr, nullptr, aspect);
180 }
181
182 if (track->pat_flag & SELECT) {
183 int a;
184
185 for (a = 0; a < 4; a++) {
187 track,
188 marker,
190 marker->pattern_corners[a],
191 marker->pos,
192 nullptr,
193 aspect);
194 }
195 }
196
197 if (track->search_flag & SELECT) {
199 track,
200 marker,
202 marker->search_min,
203 marker->pos,
204 nullptr,
205 aspect);
206
208 track,
209 marker,
211 marker->search_max,
212 marker->pos,
213 nullptr,
214 aspect);
215 }
216
217 if (init_context->current.td != nullptr) {
218 marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
219 }
220}
221
223 const int framenr,
224 MovieTrackingTrack *track,
225 const float aspect[2])
226{
227 if (!TRACK_VIEW_SELECTED(init_context->space_clip, track)) {
228 return;
229 }
230 if (track->flag & TRACK_LOCKED) {
231 return;
232 }
233 trackToTransData(init_context, framenr, track, aspect);
234}
235
237 MovieTrackingPlaneTrack *plane_track,
238 MovieTrackingPlaneMarker *plane_marker,
239 float corner[2],
240 const float aspect[2])
241{
242 TransData *td = init_context->current.td;
243 TransData2D *td2d = init_context->current.td2d;
244 TransDataTracking *tdt = init_context->current.tdt;
245
246 if (td == nullptr) {
247 init_context->tc->data_len++;
248 return;
249 }
250
251 tdt->flag = plane_marker->flag;
252 tdt->framenr = plane_marker->framenr;
254 tdt->plane_track = plane_track;
255
256 td2d->loc[0] = corner[0] * aspect[0]; /* Hold original location. */
257 td2d->loc[1] = corner[1] * aspect[1];
258
259 td2d->loc2d = corner; /* Current location. */
260 td2d->loc[2] = 0.0f;
261
262 td->flag = 0;
263 td->loc = td2d->loc;
264 copy_v3_v3(td->iloc, td->loc);
265 copy_v3_v3(td->center, td->loc);
266
267 memset(td->axismtx, 0, sizeof(td->axismtx));
268 td->axismtx[2][2] = 1.0f;
269
270 td->val = nullptr;
271
272 td->flag |= TD_SELECTED;
273 td->dist = 0.0;
274
275 unit_m3(td->mtx);
276 unit_m3(td->smtx);
277
278 init_context->current.td++;
279 init_context->current.td2d++;
280 init_context->current.tdt++;
281}
282
284 const int framenr,
285 MovieTrackingPlaneTrack *plane_track,
286 const float aspect[2])
287{
288 MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
289
290 for (int i = 0; i < 4; i++) {
292 init_context, plane_track, plane_marker, plane_marker->corners[i], aspect);
293 }
294
295 if (init_context->current.td != nullptr) {
296 plane_marker->flag &= ~PLANE_MARKER_TRACKED;
297 }
298}
299
301 const int framenr,
302 MovieTrackingPlaneTrack *plane_track,
303 const float aspect[2])
304{
305 if (!PLANE_TRACK_VIEW_SELECTED(plane_track)) {
306 return;
307 }
308 planeTrackToTransData(init_context, framenr, plane_track, aspect);
309}
310
312 TransDataContainer * /*tc*/,
313 TransCustomData *custom_data)
314{
315 if (custom_data->data) {
316 TransDataTracking *tdt = static_cast<TransDataTracking *>(custom_data->data);
317 if (tdt->smarkers) {
318 MEM_freeN(tdt->smarkers);
319 }
320
321 MEM_freeN(tdt);
322 custom_data->data = nullptr;
323 }
324}
325
327{
328 SpaceClip *space_clip = CTX_wm_space_clip(C);
329 MovieClip *clip = ED_space_clip_get_clip(space_clip);
330 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
331 const int framenr = ED_space_clip_get_clip_frame_number(space_clip);
332
334
336 init_context.space_clip = space_clip;
337 init_context.t = t;
338 init_context.tc = tc;
339
340 /* Count required transformation data. */
341
342 tc->data_len = 0;
343
344 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
345 trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect);
346 }
347
348 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
349 planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect);
350 }
351
352 if (tc->data_len == 0) {
353 return;
354 }
355
356 tc->data = MEM_calloc_arrayN<TransData>(tc->data_len, "TransTracking TransData");
357 tc->data_2d = MEM_calloc_arrayN<TransData2D>(tc->data_len, "TransTracking TransData2D");
359 "TransTracking TransDataTracking");
361
362 init_context.current.td = tc->data;
363 init_context.current.td2d = tc->data_2d;
364 init_context.current.tdt = static_cast<TransDataTracking *>(tc->custom.type.data);
365
366 /* Create actual transformation data. */
367
368 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
369 trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect);
370 }
371
372 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
373 planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect);
374 }
375}
376
378{
381 int width, height;
382
384
385 tc->data_len = 0;
386
387 if (!clip) {
388 return;
389 }
390
391 BKE_movieclip_get_size(clip, &sc->user, &width, &height);
392
393 if (width == 0 || height == 0) {
394 return;
395 }
396
398}
399
401
402/* -------------------------------------------------------------------- */
405
407{
409 TransDataTracking *tdt_array = static_cast<TransDataTracking *>(tc->custom.type.data);
410
411 int i = 0;
412 while (i < tc->data_len) {
413 TransDataTracking *tdt = &tdt_array[i];
414
416 MovieTrackingTrack *track = tdt->track;
418
419 BLI_assert(marker != nullptr);
420
421 marker->flag = tdt->flag;
422
423 if (track->flag & SELECT) {
424 i++;
425 }
426
427 if (track->pat_flag & SELECT) {
428 i += 4;
429 }
430
431 if (track->search_flag & SELECT) {
432 i += 2;
433 }
434 }
435 else if (tdt->mode == transDataTracking_ModePlaneTracks) {
436 MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
438 tdt->framenr);
439
440 BLI_assert(plane_marker != nullptr);
441
442 plane_marker->flag = tdt->flag;
443 i += 3;
444 }
445
446 i++;
447 }
448}
449
451{
452 TransData *td;
453 TransData2D *td2d;
455 int td_index;
456
457 if (t->state == TRANS_CANCEL) {
459 }
460
462
463 /* Flush to 2d vector from internally used 3d vector. */
464 for (td_index = 0,
465 td = tc->data,
466 td2d = tc->data_2d,
467 tdt = static_cast<TransDataTracking *>(tc->custom.type.data);
468 td_index < tc->data_len;
469 td_index++, td2d++, td++, tdt++)
470 {
472 float loc2d[2];
473
474 if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) {
475 continue;
476 }
477
478 loc2d[0] = td2d->loc[0] / t->aspect[0];
479 loc2d[1] = td2d->loc[1] / t->aspect[1];
480
481 if (t->flag & T_ALT_TRANSFORM) {
482 if (t->mode == TFM_RESIZE) {
483 if (tdt->area != TRACK_AREA_PAT && !(t->state == TRANS_CANCEL)) {
484 continue;
485 }
486 }
487 else if (t->mode == TFM_TRANSLATION) {
488 if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
489 float d[2], d2[2];
490
491 if (!tdt->smarkers) {
492 tdt->smarkers = static_cast<float (*)[2]>(MEM_callocN(
493 sizeof(*tdt->smarkers) * tdt->markersnr, "flushTransTracking markers"));
494 for (int a = 0; a < tdt->markersnr; a++) {
495 copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
496 }
497 }
498
499 sub_v2_v2v2(d, loc2d, tdt->soffset);
500 sub_v2_v2(d, tdt->srelative);
501
502 sub_v2_v2v2(d2, loc2d, tdt->srelative);
503
504 for (int a = 0; a < tdt->markersnr; a++) {
505 add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
506 }
507
508 negate_v2_v2(td2d->loc2d, d);
509 }
510 }
511 }
512
513 if (tdt->area != TRACK_AREA_POINT || tdt->relative == nullptr) {
514 td2d->loc2d[0] = loc2d[0];
515 td2d->loc2d[1] = loc2d[1];
516
517 if (tdt->relative) {
518 sub_v2_v2(td2d->loc2d, tdt->relative);
519 }
520 }
521 }
522 else if (tdt->mode == transDataTracking_ModePlaneTracks) {
523 td2d->loc2d[0] = td2d->loc[0] / t->aspect[0];
524 td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
525 }
526 }
527}
528
530{
531 SpaceClip *sc = static_cast<SpaceClip *>(t->area->spacedata.first);
532
535 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
536 const int framenr = ED_space_clip_get_clip_frame_number(sc);
537
539
540 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
541 if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
542 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
543
544 if (t->mode == TFM_TRANSLATION) {
547 }
550 }
551 }
552 else if (t->mode == TFM_RESIZE) {
555 }
558 }
559 }
560 else if (t->mode == TFM_ROTATION) {
563 }
564 }
565 }
566 }
567
568 DEG_id_tag_update(&clip->id, 0);
569 }
570}
571
573
574/* -------------------------------------------------------------------- */
577
579{
580 SpaceClip *sc = static_cast<SpaceClip *>(t->area->spacedata.first);
582 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
583 const int framenr = ED_space_clip_get_clip_frame_number(sc);
584 /* Update coordinates of modified plane tracks. */
585 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
586 bool do_update = false;
587 if (plane_track->flag & PLANE_TRACK_HIDDEN) {
588 continue;
589 }
590 do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
591 if (do_update == false) {
592 if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
593 int i;
594 for (i = 0; i < plane_track->point_tracksnr; i++) {
595 MovieTrackingTrack *track = plane_track->point_tracks[i];
596 if (TRACK_VIEW_SELECTED(sc, track)) {
597 do_update = true;
598 break;
599 }
600 }
601 }
602 }
603 if (do_update) {
605 }
606 }
607 if (t->scene->compositing_node_group != nullptr) {
608 /* Tracks can be used for stabilization nodes,
609 * flush update for such nodes.
610 */
611 if (t->context != nullptr) {
612 Main *bmain = CTX_data_main(C);
613 BKE_ntree_update_tag_id_changed(bmain, &clip->id);
614 BKE_ntree_update(*bmain);
616 }
617 }
618}
619
621
623 /*flags*/ (T_POINTS | T_2D_EDIT),
624 /*create_trans_data*/ createTransTrackingData,
625 /*recalc_data*/ recalcData_tracking,
626 /*special_aftertrans_update*/ special_aftertrans_update__movieclip,
627};
628
629} // namespace blender::ed::transform
Main * CTX_data_main(const bContext *C)
SpaceClip * CTX_wm_space_clip(const bContext *C)
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
void BKE_ntree_update(Main &bmain, std::optional< blender::Span< bNodeTree * > > modified_trees=std::nullopt, const NodeTreeUpdateExtraParams &params={})
void BKE_ntree_update_tag_id_changed(Main *bmain, ID *id)
void BKE_tracking_marker_clamp_pattern_position(struct MovieTrackingMarker *marker)
Definition tracking.cc:1308
struct MovieTrackingPlaneMarker * BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr)
Definition tracking.cc:1837
struct MovieTrackingMarker * BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1402
#define PLANE_TRACK_VIEW_SELECTED(plane_track)
@ TRACK_AREA_POINT
@ TRACK_AREA_PAT
@ TRACK_AREA_SEARCH
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1358
void BKE_tracking_marker_clamp_search_position(struct MovieTrackingMarker *marker)
Definition tracking.cc:1338
struct MovieTrackingObject * BKE_tracking_object_get_active(const struct MovieTracking *tracking)
struct MovieTrackingMarker * BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1391
void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame)
struct MovieTrackingPlaneMarker * BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr)
Definition tracking.cc:1849
void BKE_tracking_marker_clamp_search_size(struct MovieTrackingMarker *marker)
Definition tracking.cc:1327
#define TRACK_VIEW_SELECTED(sc, track)
#define TRACK_AREA_SELECTED(track, area)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void unit_m3(float m[3][3])
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v2_v2(float r[2], const float a[2])
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void DEG_id_tag_update(ID *id, unsigned int flags)
@ TRACK_LOCKED
@ MARKER_TRACKED
@ MARKER_DISABLED
@ PLANE_MARKER_TRACKED
@ PLANE_TRACK_HIDDEN
@ PLANE_TRACK_AUTOKEY
MovieClip * ED_space_clip_get_clip(const SpaceClip *sc)
bool ED_space_clip_check_show_trackedit(const SpaceClip *sc)
int ED_space_clip_get_clip_frame_number(const SpaceClip *sc)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define NC_SCENE
Definition WM_types.hh:378
#define ND_NODES
Definition WM_types.hh:436
nullptr float
#define SELECT
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static void transDataTrackingFree(TransInfo *, TransDataContainer *, TransCustomData *custom_data)
static void recalcData_tracking(TransInfo *t)
static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
static void cancelTransTracking(TransInfo *t)
static void markerToTransDataInit(TransformInitContext *init_context, MovieTrackingTrack *track, MovieTrackingMarker *marker, int area, float loc[2], const float rel[2], const float off[2], const float aspect[2])
static void trackToTransData(TransformInitContext *init_context, const int framenr, MovieTrackingTrack *track, const float aspect[2])
static void flushTransTracking(TransInfo *t)
static void createTransTrackingTracksData(bContext *C, TransInfo *t)
static void createTransTrackingData(bContext *C, TransInfo *t)
static void trackToTransDataIfNeeded(TransformInitContext *init_context, const int framenr, MovieTrackingTrack *track, const float aspect[2])
static void planeTrackToTransData(TransformInitContext *init_context, const int framenr, MovieTrackingPlaneTrack *plane_track, const float aspect[2])
TransConvertTypeInfo TransConvertType_Tracking
static void planeMarkerToTransDataInit(TransformInitContext *init_context, MovieTrackingPlaneTrack *plane_track, MovieTrackingPlaneMarker *plane_marker, float corner[2], const float aspect[2])
static void planeTrackToTransDataIfNeeded(TransformInitContext *init_context, const int framenr, MovieTrackingPlaneTrack *plane_track, const float aspect[2])
static void init_context(DupliContext *r_ctx, Depsgraph *depsgraph, Scene *scene, Object *ob, const float space_mat[4][4], blender::Set< const Object * > *include_objects, Vector< Object * > &instance_stack, Vector< short > &dupli_gen_type_stack, DupliList &duplilist)
void * first
struct MovieTracking tracking
MovieTrackingMarker * markers
struct bNodeTree * compositing_node_group
ListBase spacedata
struct MovieClipUser user
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
Definition transform.hh:633
struct blender::ed::transform::TransformInitContext::@260346027371202033346237127361277203140043200222 current
i
Definition text_draw.cc:230
#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t)
Definition transform.hh:39
conversion and adaptation of different datablocks to a common struct.
void WM_event_add_notifier(const bContext *C, uint type, void *reference)