ce248f1eb102b4d9c2c113e9838b0080c61fbc0d
[blender.git] / source / blender / editors / space_clip / clip_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_clip/clip_draw.c
29  *  \ingroup spclip
30  */
31
32 #include "DNA_gpencil_types.h"
33 #include "DNA_movieclip_types.h"
34 #include "DNA_scene_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "IMB_colormanagement.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_math.h"
44 #include "BLI_string.h"
45 #include "BLI_math_base.h"
46
47 #include "BKE_context.h"
48 #include "BKE_image.h"
49 #include "BKE_movieclip.h"
50 #include "BKE_tracking.h"
51
52 #include "ED_screen.h"
53 #include "ED_clip.h"
54 #include "ED_mask.h"
55 #include "ED_gpencil.h"
56
57 #include "BIF_gl.h"
58 #include "BIF_glutil.h"
59
60 #include "WM_types.h"
61
62 #include "UI_interface.h"
63 #include "UI_resources.h"
64 #include "UI_view2d.h"
65
66
67 #include "BLF_api.h"
68
69 #include "clip_intern.h"    // own include
70
71 /*********************** main area drawing *************************/
72
73 static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width)
74 {
75         int height = (frame == cfra) ? 22 : 10;
76         int x = (frame - sfra) * framelen;
77
78         if (width == 1) {
79                 glBegin(GL_LINES);
80                 glVertex2i(x, 0);
81                 glVertex2i(x, height * UI_DPI_FAC);
82                 glEnd();
83         }
84         else {
85                 glRecti(x, 0, x + width, height * UI_DPI_FAC);
86         }
87 }
88
89 static int generic_track_get_markersnr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track)
90 {
91         if (track) {
92                 return track->markersnr;
93         }
94         else if (plane_track) {
95                 return plane_track->markersnr;
96         }
97
98         return 0;
99 }
100
101 static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
102                                             int marker_index)
103 {
104         if (track) {
105                 BLI_assert(marker_index < track->markersnr);
106                 return track->markers[marker_index].framenr;
107         }
108         else if (plane_track) {
109                 BLI_assert(marker_index < plane_track->markersnr);
110                 return plane_track->markers[marker_index].framenr;
111         }
112
113         return 0;
114 }
115
116 static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
117                                             int marker_index)
118 {
119         if (track) {
120                 BLI_assert(marker_index < track->markersnr);
121                 return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
122         }
123         else if (plane_track) {
124                 return true;
125         }
126
127         return false;
128 }
129
130 static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
131                                               int marker_index)
132 {
133         if (track) {
134                 BLI_assert(marker_index < track->markersnr);
135                 return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
136         }
137         else if (plane_track) {
138                 BLI_assert(marker_index < plane_track->markersnr);
139                 return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
140         }
141
142         return false;
143 }
144
145 static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
146 {
147         float x;
148         int *points, totseg, i, a;
149         float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1);
150         MovieTracking *tracking = &clip->tracking;
151         MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
152         MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
153         MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
154         MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
155
156         glEnable(GL_BLEND);
157         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
158
159         /* cache background */
160         ED_region_cache_draw_background(ar);
161
162         /* cached segments -- could be usefu lto debug caching strategies */
163         BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
164         ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
165
166         /* track */
167         if (act_track || act_plane_track) {
168                 for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
169                         int framenr;
170                         int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
171
172                         while (a < markersnr) {
173                                 int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
174
175                                 if (marker_framenr >= i)
176                                         break;
177
178                                 if (a < markersnr - 1 && generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
179                                         break;
180
181                                 a++;
182                         }
183
184                         a = min_ii(a, markersnr - 1);
185
186                         if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
187                                 framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
188
189                                 if (framenr != i)
190                                         glColor4ub(128, 128, 0, 96);
191                                 else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
192                                         glColor4ub(255, 255, 0, 196);
193                                 else
194                                         glColor4ub(255, 255, 0, 96);
195
196                                 glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
197                         }
198                 }
199         }
200
201         /* failed frames */
202         if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
203                 int n = reconstruction->camnr;
204                 MovieReconstructedCamera *cameras = reconstruction->cameras;
205
206                 glColor4ub(255, 0, 0, 96);
207
208                 for (i = sfra, a = 0; i <= efra; i++) {
209                         bool ok = false;
210
211                         while (a < n) {
212                                 if (cameras[a].framenr == i) {
213                                         ok = true;
214                                         break;
215                                 }
216                                 else if (cameras[a].framenr > i) {
217                                         break;
218                                 }
219
220                                 a++;
221                         }
222
223                         if (!ok)
224                                 glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
225                 }
226         }
227
228         glDisable(GL_BLEND);
229
230         /* current frame */
231         x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
232
233         UI_ThemeColor(TH_CFRAME);
234         glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
235
236         ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
237
238         /* solver keyframes */
239         glColor4ub(175, 255, 0, 255);
240         draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
241         draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
242
243         /* movie clip animation */
244         if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) {
245                 ED_mask_draw_frames(sc->mask_info.mask, ar, CFRA, sfra, efra);
246         }
247 }
248
249 static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
250 {
251         MovieClip *clip = ED_space_clip_get_clip(sc);
252         MovieTracking *tracking = &clip->tracking;
253         char str[256] = {0};
254         bool block = false;
255
256         if (tracking->stats) {
257                 BLI_strncpy(str, tracking->stats->message, sizeof(str));
258                 block = true;
259         }
260         else {
261                 if (sc->flag & SC_LOCK_SELECTION)
262                         strcpy(str, "Locked");
263         }
264
265         if (str[0]) {
266                 float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.6f};
267                 ED_region_info_draw(ar, str, block, fill_color);
268         }
269 }
270
271 static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx, float zoomy)
272 {
273         int x, y;
274
275         /* find window pixel coordinates of origin */
276         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
277
278         glColor3f(0.0f, 0.0f, 0.0f);
279         glRectf(x, y, x + zoomx * width, y + zoomy * height);
280 }
281
282 static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
283                                   int width, int height, float zoomx, float zoomy)
284 {
285         MovieClip *clip = ED_space_clip_get_clip(sc);
286         int filter = GL_LINEAR;
287         int x, y;
288
289         /* find window pixel coordinates of origin */
290         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
291
292         /* checkerboard for case alpha */
293         if (ibuf->planes == 32) {
294                 glEnable(GL_BLEND);
295                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
296
297                 fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
298         }
299
300         /* non-scaled proxy shouldn't use filtering */
301         if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
302             ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
303         {
304                 filter = GL_NEAREST;
305         }
306
307         /* set zoom */
308         glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
309
310         glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
311
312         /* reset zoom */
313         glPixelZoom(1.0f, 1.0f);
314
315         if (ibuf->planes == 32)
316                 glDisable(GL_BLEND);
317 }
318
319 static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
320 {
321         int x, y;
322         MovieClip *clip = ED_space_clip_get_clip(sc);
323
324         /* find window pixel coordinates of origin */
325         UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
326
327         /* draw boundary border for frame if stabilization is enabled */
328         if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
329                 glColor3f(0.0f, 0.0f, 0.0f);
330                 glLineStipple(3, 0xaaaa);
331                 glEnable(GL_LINE_STIPPLE);
332                 glEnable(GL_COLOR_LOGIC_OP);
333                 glLogicOp(GL_NOR);
334
335                 glPushMatrix();
336                 glTranslatef(x, y, 0.0f);
337
338                 glScalef(zoomx, zoomy, 1.0f);
339                 glMultMatrixf(sc->stabmat);
340
341                 glBegin(GL_LINE_LOOP);
342                 glVertex2f(0.0f, 0.0f);
343                 glVertex2f(width, 0.0f);
344                 glVertex2f(width, height);
345                 glVertex2f(0.0f, height);
346                 glEnd();
347
348                 glPopMatrix();
349
350                 glDisable(GL_COLOR_LOGIC_OP);
351                 glDisable(GL_LINE_STIPPLE);
352         }
353 }
354
355 static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackingTrack *track)
356 {
357         int count = sc->path_length;
358         int i, a, b, curindex = -1;
359         float path[102][2];
360         int tiny = sc->flag & SC_SHOW_TINY_MARKER, framenr, start_frame;
361         MovieTrackingMarker *marker;
362
363         if (count == 0)
364                 return;
365
366         start_frame = framenr = ED_space_clip_get_clip_frame_number(sc);
367
368         marker = BKE_tracking_marker_get(track, framenr);
369         if (marker->framenr != framenr || marker->flag & MARKER_DISABLED)
370                 return;
371
372         a = count;
373         i = framenr - 1;
374         while (i >= framenr - count) {
375                 marker = BKE_tracking_marker_get(track, i);
376
377                 if (!marker || marker->flag & MARKER_DISABLED)
378                         break;
379
380                 if (marker->framenr == i) {
381                         add_v2_v2v2(path[--a], marker->pos, track->offset);
382                         ED_clip_point_undistorted_pos(sc, path[a], path[a]);
383
384                         if (marker->framenr == start_frame)
385                                 curindex = a;
386                 }
387                 else {
388                         break;
389                 }
390
391                 i--;
392         }
393
394         b = count;
395         i = framenr;
396         while (i <= framenr + count) {
397                 marker = BKE_tracking_marker_get(track, i);
398
399                 if (!marker || marker->flag & MARKER_DISABLED)
400                         break;
401
402                 if (marker->framenr == i) {
403                         if (marker->framenr == start_frame)
404                                 curindex = b;
405
406                         add_v2_v2v2(path[b++], marker->pos, track->offset);
407                         ED_clip_point_undistorted_pos(sc, path[b - 1], path[b - 1]);
408                 }
409                 else
410                         break;
411
412                 i++;
413         }
414
415         if (!tiny) {
416                 UI_ThemeColor(TH_MARKER_OUTLINE);
417
418                 if (TRACK_VIEW_SELECTED(sc, track)) {
419                         glPointSize(5.0f);
420                         glBegin(GL_POINTS);
421                         for (i = a; i < b; i++) {
422                                 if (i != curindex)
423                                         glVertex2f(path[i][0], path[i][1]);
424                         }
425                         glEnd();
426                 }
427
428                 glLineWidth(3.0f);
429                 glBegin(GL_LINE_STRIP);
430                 for (i = a; i < b; i++)
431                         glVertex2f(path[i][0], path[i][1]);
432                 glEnd();
433                 glLineWidth(1.0f);
434         }
435
436         UI_ThemeColor(TH_PATH_BEFORE);
437
438         if (TRACK_VIEW_SELECTED(sc, track)) {
439                 glPointSize(3.0f);
440                 glBegin(GL_POINTS);
441                 for (i = a; i < b; i++) {
442                         if (i == count + 1)
443                                 UI_ThemeColor(TH_PATH_AFTER);
444
445                         if (i != curindex)
446                                 glVertex2f(path[i][0], path[i][1]);
447                 }
448                 glEnd();
449         }
450
451         UI_ThemeColor(TH_PATH_BEFORE);
452
453         glBegin(GL_LINE_STRIP);
454         for (i = a; i < b; i++) {
455                 if (i == count + 1)
456                         UI_ThemeColor(TH_PATH_AFTER);
457
458                 glVertex2f(path[i][0], path[i][1]);
459         }
460         glEnd();
461         glPointSize(1.0f);
462 }
463
464 static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
465                                 const float marker_pos[2], int width, int height)
466 {
467         int tiny = sc->flag & SC_SHOW_TINY_MARKER;
468         bool show_search = false;
469         float px[2];
470
471         UI_ThemeColor(TH_MARKER_OUTLINE);
472
473         px[0] = 1.0f / width / sc->zoom;
474         px[1] = 1.0f / height / sc->zoom;
475
476         if ((marker->flag & MARKER_DISABLED) == 0) {
477                 float pos[2];
478                 float p[2];
479
480                 add_v2_v2v2(pos, marker->pos, track->offset);
481
482                 ED_clip_point_undistorted_pos(sc, pos, pos);
483
484                 sub_v2_v2v2(p, pos, marker_pos);
485
486                 if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
487                                         marker->pattern_corners[2], marker->pattern_corners[3]))
488                 {
489                         if (tiny) glPointSize(3.0f);
490                         else glPointSize(4.0f);
491                         glBegin(GL_POINTS);
492                         glVertex2f(pos[0], pos[1]);
493                         glEnd();
494                         glPointSize(1.0f);
495                 }
496                 else {
497                         if (!tiny) glLineWidth(3.0f);
498                         glBegin(GL_LINES);
499                         glVertex2f(pos[0] + px[0] * 2, pos[1]);
500                         glVertex2f(pos[0] + px[0] * 8, pos[1]);
501
502                         glVertex2f(pos[0] - px[0] * 2, pos[1]);
503                         glVertex2f(pos[0] - px[0] * 8, pos[1]);
504
505                         glVertex2f(pos[0], pos[1] - px[1] * 2);
506                         glVertex2f(pos[0], pos[1] - px[1] * 8);
507
508                         glVertex2f(pos[0], pos[1] + px[1] * 2);
509                         glVertex2f(pos[0], pos[1] + px[1] * 8);
510                         glEnd();
511                         if (!tiny) glLineWidth(1.0f);
512                 }
513         }
514
515         /* pattern and search outline */
516         glPushMatrix();
517         glTranslatef(marker_pos[0], marker_pos[1], 0);
518
519         if (!tiny)
520                 glLineWidth(3.0f);
521
522         if (sc->flag & SC_SHOW_MARKER_PATTERN) {
523                 glBegin(GL_LINE_LOOP);
524                 glVertex2fv(marker->pattern_corners[0]);
525                 glVertex2fv(marker->pattern_corners[1]);
526                 glVertex2fv(marker->pattern_corners[2]);
527                 glVertex2fv(marker->pattern_corners[3]);
528                 glEnd();
529         }
530
531         show_search = (TRACK_VIEW_SELECTED(sc, track) &&
532                        ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
533         if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
534                 glBegin(GL_LINE_LOOP);
535                 glVertex2f(marker->search_min[0], marker->search_min[1]);
536                 glVertex2f(marker->search_max[0], marker->search_min[1]);
537                 glVertex2f(marker->search_max[0], marker->search_max[1]);
538                 glVertex2f(marker->search_min[0], marker->search_max[1]);
539                 glEnd();
540         }
541         glPopMatrix();
542
543         if (!tiny)
544                 glLineWidth(1.0f);
545 }
546
547 static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
548 {
549         if (track->flag & TRACK_CUSTOMCOLOR) {
550                 if (act)
551                         UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
552                 else
553                         copy_v3_v3(scol, track->color);
554
555                 mul_v3_v3fl(col, track->color, 0.5f);
556         }
557         else {
558                 UI_GetThemeColor3fv(TH_MARKER, col);
559
560                 if (act)
561                         UI_GetThemeColor3fv(TH_ACT_MARKER, scol);
562                 else
563                         UI_GetThemeColor3fv(TH_SEL_MARKER, scol);
564         }
565 }
566
567 static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
568                               const float marker_pos[2], int width, int height, int act, int sel)
569 {
570         int tiny = sc->flag & SC_SHOW_TINY_MARKER;
571         bool show_search = false;
572         float col[3], scol[3], px[2];
573
574         track_colors(track, act, col, scol);
575
576         px[0] = 1.0f / width / sc->zoom;
577         px[1] = 1.0f / height / sc->zoom;
578
579         /* marker position and offset position */
580         if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
581                 float pos[2], p[2];
582
583                 if (track->flag & TRACK_LOCKED) {
584                         if (act)
585                                 UI_ThemeColor(TH_ACT_MARKER);
586                         else if (track->flag & SELECT)
587                                 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
588                         else
589                                 UI_ThemeColor(TH_LOCK_MARKER);
590                 }
591                 else {
592                         if (track->flag & SELECT)
593                                 glColor3fv(scol);
594                         else
595                                 glColor3fv(col);
596                 }
597
598                 add_v2_v2v2(pos, marker->pos, track->offset);
599                 ED_clip_point_undistorted_pos(sc, pos, pos);
600
601                 sub_v2_v2v2(p, pos, marker_pos);
602
603                 if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1],
604                                         marker->pattern_corners[2], marker->pattern_corners[3]))
605                 {
606                         if (!tiny)
607                                 glPointSize(2.0f);
608
609                         glBegin(GL_POINTS);
610                         glVertex2f(pos[0], pos[1]);
611                         glEnd();
612
613                         if (!tiny)
614                                 glPointSize(1.0f);
615                 }
616                 else {
617                         glBegin(GL_LINES);
618                         glVertex2f(pos[0] + px[0] * 3, pos[1]);
619                         glVertex2f(pos[0] + px[0] * 7, pos[1]);
620
621                         glVertex2f(pos[0] - px[0] * 3, pos[1]);
622                         glVertex2f(pos[0] - px[0] * 7, pos[1]);
623
624                         glVertex2f(pos[0], pos[1] - px[1] * 3);
625                         glVertex2f(pos[0], pos[1] - px[1] * 7);
626
627                         glVertex2f(pos[0], pos[1] + px[1] * 3);
628                         glVertex2f(pos[0], pos[1] + px[1] * 7);
629                         glEnd();
630
631                         glColor3f(0.0f, 0.0f, 0.0f);
632                         glLineStipple(3, 0xaaaa);
633                         glEnable(GL_LINE_STIPPLE);
634                         glEnable(GL_COLOR_LOGIC_OP);
635                         glLogicOp(GL_NOR);
636
637                         glBegin(GL_LINES);
638                         glVertex2fv(pos);
639                         glVertex2fv(marker_pos);
640                         glEnd();
641
642                         glDisable(GL_COLOR_LOGIC_OP);
643                         glDisable(GL_LINE_STIPPLE);
644                 }
645         }
646
647         /* pattern */
648         glPushMatrix();
649         glTranslatef(marker_pos[0], marker_pos[1], 0);
650
651         if (tiny) {
652                 glLineStipple(3, 0xaaaa);
653                 glEnable(GL_LINE_STIPPLE);
654         }
655
656         if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
657                 if (track->flag & TRACK_LOCKED) {
658                         if (act)
659                                 UI_ThemeColor(TH_ACT_MARKER);
660                         else if (track->pat_flag & SELECT)
661                                 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
662                         else UI_ThemeColor(TH_LOCK_MARKER);
663                 }
664                 else if (marker->flag & MARKER_DISABLED) {
665                         if (act)
666                                 UI_ThemeColor(TH_ACT_MARKER);
667                         else if (track->pat_flag & SELECT)
668                                 UI_ThemeColorShade(TH_DIS_MARKER, 128);
669                         else UI_ThemeColor(TH_DIS_MARKER);
670                 }
671                 else {
672                         if (track->pat_flag & SELECT)
673                                 glColor3fv(scol);
674                         else glColor3fv(col);
675                 }
676
677                 glBegin(GL_LINE_LOOP);
678                 glVertex2fv(marker->pattern_corners[0]);
679                 glVertex2fv(marker->pattern_corners[1]);
680                 glVertex2fv(marker->pattern_corners[2]);
681                 glVertex2fv(marker->pattern_corners[3]);
682                 glEnd();
683         }
684
685         /* search */
686         show_search = (TRACK_VIEW_SELECTED(sc, track) &&
687                        ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
688         if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
689                 if (track->flag & TRACK_LOCKED) {
690                         if (act)
691                                 UI_ThemeColor(TH_ACT_MARKER);
692                         else if (track->search_flag & SELECT)
693                                 UI_ThemeColorShade(TH_LOCK_MARKER, 64);
694                         else UI_ThemeColor(TH_LOCK_MARKER);
695                 }
696                 else if (marker->flag & MARKER_DISABLED) {
697                         if (act)
698                                 UI_ThemeColor(TH_ACT_MARKER);
699                         else if (track->search_flag & SELECT)
700                                 UI_ThemeColorShade(TH_DIS_MARKER, 128);
701                         else UI_ThemeColor(TH_DIS_MARKER);
702                 }
703                 else {
704                         if (track->search_flag & SELECT)
705                                 glColor3fv(scol);
706                         else
707                                 glColor3fv(col);
708                 }
709
710                 glBegin(GL_LINE_LOOP);
711                 glVertex2f(marker->search_min[0], marker->search_min[1]);
712                 glVertex2f(marker->search_max[0], marker->search_min[1]);
713                 glVertex2f(marker->search_max[0], marker->search_max[1]);
714                 glVertex2f(marker->search_min[0], marker->search_max[1]);
715                 glEnd();
716         }
717
718         if (tiny)
719                 glDisable(GL_LINE_STIPPLE);
720
721         glPopMatrix();
722 }
723
724 static float get_shortest_pattern_side(MovieTrackingMarker *marker)
725 {
726         int i, next;
727         float len_sq = FLT_MAX;
728
729         for (i = 0; i < 4; i++) {
730                 float cur_len;
731
732                 next = (i + 1) % 4;
733
734                 cur_len = len_squared_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]);
735
736                 len_sq = min_ff(cur_len, len_sq);
737         }
738
739         return sqrtf(len_sq);
740 }
741
742 static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2])
743 {
744         float tdx, tdy;
745
746         tdx = dx;
747         tdy = dy;
748
749         if (outline) {
750                 tdx += px[0];
751                 tdy += px[1];
752         }
753
754         glBegin(GL_QUADS);
755         glVertex3f(x - tdx, y + tdy, 0.0f);
756         glVertex3f(x + tdx, y + tdy, 0.0f);
757         glVertex3f(x + tdx, y - tdy, 0.0f);
758         glVertex3f(x - tdx, y - tdy, 0.0f);
759         glEnd();
760 }
761
762 static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2])
763 {
764         float tdx, tdy;
765
766         tdx = dx * 2.0f;
767         tdy = dy * 2.0f;
768
769         if (outline) {
770                 tdx += px[0];
771                 tdy += px[1];
772         }
773
774         glBegin(GL_TRIANGLES);
775         glVertex3f(x,       y,       0.0f);
776         glVertex3f(x - tdx, y,       0.0f);
777         glVertex3f(x,       y + tdy, 0.0f);
778         glEnd();
779 }
780
781 static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
782                                     const float marker_pos[2], int outline, int sel, int act, int width, int height)
783 {
784         float dx, dy, patdx, patdy, searchdx, searchdy;
785         int tiny = sc->flag & SC_SHOW_TINY_MARKER;
786         float col[3], scol[3], px[2], side;
787
788         if ((tiny && outline) || (marker->flag & MARKER_DISABLED))
789                 return;
790
791         if (!TRACK_VIEW_SELECTED(sc, track) || track->flag & TRACK_LOCKED)
792                 return;
793
794         track_colors(track, act, col, scol);
795
796         if (outline) {
797                 glLineWidth(3.0f);
798                 UI_ThemeColor(TH_MARKER_OUTLINE);
799         }
800
801         glPushMatrix();
802         glTranslatef(marker_pos[0], marker_pos[1], 0);
803
804         dx = 6.0f / width / sc->zoom;
805         dy = 6.0f / height / sc->zoom;
806
807         side = get_shortest_pattern_side(marker);
808         patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC;
809         patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC;
810
811         searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC;
812         searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC;
813
814         px[0] = 1.0f / sc->zoom / width / sc->scale;
815         px[1] = 1.0f / sc->zoom / height / sc->scale;
816
817         if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
818                 if (!outline) {
819                         if (track->search_flag & SELECT)
820                                 glColor3fv(scol);
821                         else
822                                 glColor3fv(col);
823                 }
824
825                 /* search offset square */
826                 draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px);
827
828                 /* search re-sizing triangle */
829                 draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px);
830         }
831
832         if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
833                 int i;
834                 float pat_min[2], pat_max[2];
835 /*              float dx = 12.0f / width, dy = 12.0f / height;*/ /* XXX UNUSED */
836                 float tilt_ctrl[2];
837
838                 if (!outline) {
839                         if (track->pat_flag & SELECT)
840                                 glColor3fv(scol);
841                         else
842                                 glColor3fv(col);
843                 }
844
845                 /* pattern's corners sliding squares */
846                 for (i = 0; i < 4; i++) {
847                         draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
848                                                  patdx / 1.5f, patdy / 1.5f, outline, px);
849                 }
850
851                 /* ** sliders to control overall pattern  ** */
852                 add_v2_v2v2(tilt_ctrl, marker->pattern_corners[1], marker->pattern_corners[2]);
853
854                 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
855
856                 glEnable(GL_LINE_STIPPLE);
857                 glLineStipple(3, 0xaaaa);
858
859 #if 0
860                 /* TODO: disable for now, needs better approach visualizing this */
861
862                 glBegin(GL_LINE_LOOP);
863                 glVertex2f(pat_min[0] - dx, pat_min[1] - dy);
864                 glVertex2f(pat_max[0] + dx, pat_min[1] - dy);
865                 glVertex2f(pat_max[0] + dx, pat_max[1] + dy);
866                 glVertex2f(pat_min[0] - dx, pat_max[1] + dy);
867                 glEnd();
868
869                 /* marker's offset slider */
870                 draw_marker_slide_square(pat_min[0] - dx, pat_max[1] + dy, patdx, patdy, outline, px);
871
872                 /* pattern re-sizing triangle */
873                 draw_marker_slide_triangle(pat_max[0] + dx, pat_min[1] - dy, patdx, patdy, outline, px);
874 #endif
875
876                 glBegin(GL_LINES);
877                 glVertex2f(0.0f, 0.0f);
878                 glVertex2fv(tilt_ctrl);
879                 glEnd();
880
881                 glDisable(GL_LINE_STIPPLE);
882
883
884                 /* slider to control pattern tilt */
885                 draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
886         }
887
888         glPopMatrix();
889
890         if (outline)
891                 glLineWidth(1.0f);
892 }
893
894 static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
895                               const float marker_pos[2], int act, int width, int height, float zoomx, float zoomy)
896 {
897         char str[128] = {0}, state[64] = {0};
898         float dx = 0.0f, dy = 0.0f, fontsize, pos[3];
899         uiStyle *style = U.uistyles.first;
900         int fontid = style->widget.uifont_id;
901
902         if (!TRACK_VIEW_SELECTED(sc, track))
903                 return;
904
905         BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
906         fontsize = BLF_height_max(fontid);
907
908         if (marker->flag & MARKER_DISABLED) {
909                 if (act)
910                         UI_ThemeColor(TH_ACT_MARKER);
911                 else
912                         UI_ThemeColorShade(TH_DIS_MARKER, 128);
913         }
914         else {
915                 if (act)
916                         UI_ThemeColor(TH_ACT_MARKER);
917                 else
918                         UI_ThemeColor(TH_SEL_MARKER);
919         }
920
921         if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
922             ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0))
923         {
924                 dx = marker->search_min[0];
925                 dy = marker->search_min[1];
926         }
927         else if (sc->flag & SC_SHOW_MARKER_PATTERN) {
928                 float pat_min[2], pat_max[2];
929
930                 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
931                 dx = pat_min[0];
932                 dy = pat_min[1];
933         }
934
935         pos[0] = (marker_pos[0] + dx) * width;
936         pos[1] = (marker_pos[1] + dy) * height;
937         pos[2] = 0.0f;
938
939         mul_m4_v3(sc->stabmat, pos);
940
941         pos[0] = pos[0] * zoomx;
942         pos[1] = pos[1] * zoomy - fontsize;
943
944         if (marker->flag & MARKER_DISABLED)
945                 strcpy(state, "disabled");
946         else if (marker->framenr != ED_space_clip_get_clip_frame_number(sc))
947                 strcpy(state, "estimated");
948         else if (marker->flag & MARKER_TRACKED)
949                 strcpy(state, "tracked");
950         else
951                 strcpy(state, "keyframed");
952
953         if (state[0])
954                 BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
955         else
956                 BLI_strncpy(str, track->name, sizeof(str));
957
958         BLF_position(fontid, pos[0], pos[1], 0.0f);
959         BLF_draw(fontid, str, sizeof(str));
960         pos[1] -= fontsize;
961
962         if (track->flag & TRACK_HAS_BUNDLE) {
963                 BLI_snprintf(str, sizeof(str), "Average error: %.3f", track->error);
964                 BLF_position(fontid, pos[0], pos[1], 0.0f);
965                 BLF_draw(fontid, str, sizeof(str));
966                 pos[1] -= fontsize;
967         }
968
969         if (track->flag & TRACK_LOCKED) {
970                 BLF_position(fontid, pos[0], pos[1], 0.0f);
971                 BLF_draw(fontid, "locked", 6);
972         }
973 }
974
975 static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
976 {
977         UI_GetThemeColor3fv(TH_MARKER, color);
978
979         if (is_active)
980                 UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
981         else
982                 UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
983 }
984
985 static void getArrowEndPoint(const int width, const int height, const float zoom,
986                              const float start_corner[2], const float end_corner[2],
987                              float end_point[2])
988 {
989         float direction[2];
990         float max_length;
991
992         sub_v2_v2v2(direction, end_corner, start_corner);
993
994         direction[0] *= width;
995         direction[1] *= height;
996         max_length = normalize_v2(direction);
997         mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
998         direction[0] /= width;
999         direction[1] /= height;
1000
1001         add_v2_v2v2(end_point, start_corner, direction);
1002 }
1003
1004 static void homogeneous_2d_to_gl_matrix(/*const*/ float matrix[3][3],
1005                                         float gl_matrix[4][4])
1006 {
1007         gl_matrix[0][0] = matrix[0][0];
1008         gl_matrix[0][1] = matrix[0][1];
1009         gl_matrix[0][2] = 0.0f;
1010         gl_matrix[0][3] = matrix[0][2];
1011
1012         gl_matrix[1][0] = matrix[1][0];
1013         gl_matrix[1][1] = matrix[1][1];
1014         gl_matrix[1][2] = 0.0f;
1015         gl_matrix[1][3] = matrix[1][2];
1016
1017         gl_matrix[2][0] = 0.0f;
1018         gl_matrix[2][1] = 0.0f;
1019         gl_matrix[2][2] = 1.0f;
1020         gl_matrix[2][3] = 0.0f;
1021
1022         gl_matrix[3][0] = matrix[2][0];
1023         gl_matrix[3][1] = matrix[2][1];
1024         gl_matrix[3][2] = 0.0f;
1025         gl_matrix[3][3] = matrix[2][2];
1026 }
1027
1028 static void draw_plane_marker_image(Scene *scene,
1029                                     MovieTrackingPlaneTrack *plane_track,
1030                                     MovieTrackingPlaneMarker *plane_marker)
1031 {
1032         Image *image = plane_track->image;
1033         ImBuf *ibuf;
1034         void *lock;
1035
1036         if (image == NULL) {
1037                 return;
1038         }
1039
1040         ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
1041
1042         if (ibuf) {
1043                 unsigned char *display_buffer;
1044                 void *cache_handle;
1045
1046                 if (image->flag & IMA_VIEW_AS_RENDER) {
1047                         display_buffer = IMB_display_buffer_acquire(ibuf,
1048                                                                     &scene->view_settings,
1049                                                                     &scene->display_settings,
1050                                                                     &cache_handle);
1051                 }
1052                 else {
1053                         display_buffer = IMB_display_buffer_acquire(ibuf, NULL,
1054                                                                     &scene->display_settings,
1055                                                                     &cache_handle);
1056                 }
1057
1058                 if (display_buffer) {
1059                         GLuint texid, last_texid;
1060                         float frame_corners[4][2] = {{0.0f, 0.0f},
1061                                                      {1.0f, 0.0f},
1062                                                      {1.0f, 1.0f},
1063                                                      {0.0f, 1.0f}};
1064                         float perspective_matrix[3][3];
1065                         float gl_matrix[4][4];
1066                         bool transparent = false;
1067                         BKE_tracking_homography_between_two_quads(frame_corners,
1068                                                                   plane_marker->corners,
1069                                                                   perspective_matrix);
1070
1071                         homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);
1072
1073                         if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
1074                                 transparent = true;
1075                                 glEnable(GL_BLEND);
1076                                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
1077                         }
1078
1079                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1080                         glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);
1081
1082                         last_texid = glaGetOneInteger(GL_TEXTURE_2D);
1083                         glEnable(GL_TEXTURE_2D);
1084                         glGenTextures(1, (GLuint *)&texid);
1085
1086                         glBindTexture(GL_TEXTURE_2D, texid);
1087
1088                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1089                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1090
1091                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
1092                                      GL_UNSIGNED_BYTE, display_buffer);
1093
1094                         glPushMatrix();
1095                         glMultMatrixf(gl_matrix);
1096
1097                         glBegin(GL_QUADS);
1098                         glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
1099                         glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
1100                         glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
1101                         glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
1102                         glEnd();
1103
1104                         glPopMatrix();
1105
1106                         glBindTexture(GL_TEXTURE_2D, last_texid);
1107                         glDisable(GL_TEXTURE_2D);
1108
1109                         if (transparent) {
1110                                 glDisable(GL_BLEND);
1111                         }
1112                 }
1113
1114                 IMB_display_buffer_release(cache_handle);
1115         }
1116
1117         BKE_image_release_ibuf(image, ibuf, lock);
1118 }
1119
1120 static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1121                                  MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
1122                                  bool draw_outline, int width, int height)
1123 {
1124         bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
1125         bool is_selected_track = (plane_track->flag & SELECT) != 0;
1126         const bool has_image = plane_track->image != NULL &&
1127                                BKE_image_has_ibuf(plane_track->image, NULL);
1128         const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
1129         float px[2];
1130
1131         if (draw_outline) {
1132                 UI_ThemeColor(TH_MARKER_OUTLINE);
1133         }
1134         else {
1135                 float color[3], selected_color[3];
1136                 plane_track_colors(is_active_track, color, selected_color);
1137                 if (is_selected_track) {
1138                         glColor3fv(selected_color);
1139                 }
1140                 else {
1141                         glColor3fv(color);
1142                 }
1143         }
1144
1145         px[0] = 1.0f / width / sc->zoom;
1146         px[1] = 1.0f / height / sc->zoom;
1147
1148         /* Draw image */
1149         if (draw_outline == false) {
1150                 draw_plane_marker_image(scene, plane_track, plane_marker);
1151         }
1152
1153         if (draw_outline) {
1154                 if (!tiny) {
1155                         glLineWidth(3.0f);
1156                 }
1157         }
1158         else if (tiny) {
1159                 glLineStipple(3, 0xaaaa);
1160                 glEnable(GL_LINE_STIPPLE);
1161         }
1162
1163         if (draw_plane_quad) {
1164                 /* Draw rectangle itself. */
1165                 glBegin(GL_LINE_LOOP);
1166                 glVertex2fv(plane_marker->corners[0]);
1167                 glVertex2fv(plane_marker->corners[1]);
1168                 glVertex2fv(plane_marker->corners[2]);
1169                 glVertex2fv(plane_marker->corners[3]);
1170                 glEnd();
1171
1172                 /* Draw axis. */
1173                 if (!draw_outline) {
1174                         float end_point[2];
1175                         glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
1176
1177                         getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
1178                         glColor3f(1.0, 0.0, 0.0f);
1179                         glBegin(GL_LINES);
1180                         glVertex2fv(plane_marker->corners[0]);
1181                         glVertex2fv(end_point);
1182                         glEnd();
1183
1184                         getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
1185                         glColor3f(0.0, 1.0, 0.0f);
1186                         glBegin(GL_LINES);
1187                         glVertex2fv(plane_marker->corners[0]);
1188                         glVertex2fv(end_point);
1189                         glEnd();
1190
1191                         glPopAttrib();
1192                 }
1193         }
1194
1195         /* Draw sliders. */
1196         if (is_selected_track) {
1197                 int i;
1198                 for (i = 0; i < 4; i++) {
1199                         draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
1200                                                  3.0f * px[0], 3.0f * px[1], draw_outline, px);
1201                 }
1202         }
1203
1204         if (draw_outline) {
1205                 if (!tiny) {
1206                         glLineWidth(1.0f);
1207                 }
1208         }
1209         else if (tiny) {
1210                 glDisable(GL_LINE_STIPPLE);
1211         }
1212 }
1213
1214 static void draw_plane_marker_outline(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1215                                       MovieTrackingPlaneMarker *plane_marker, int width, int height)
1216 {
1217         draw_plane_marker_ex(sc, scene, plane_track, plane_marker, false, true, width, height);
1218 }
1219
1220 static void draw_plane_marker(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1221                               MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
1222                               int width, int height)
1223 {
1224         draw_plane_marker_ex(sc, scene, plane_track, plane_marker, is_active_track, false, width, height);
1225 }
1226
1227 static void draw_plane_track(SpaceClip *sc, Scene *scene, MovieTrackingPlaneTrack *plane_track,
1228                              int framenr, bool is_active_track, int width, int height)
1229 {
1230         MovieTrackingPlaneMarker *plane_marker;
1231
1232         plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
1233
1234         draw_plane_marker_outline(sc, scene, plane_track, plane_marker, width, height);
1235         draw_plane_marker(sc, scene, plane_track, plane_marker, is_active_track, width, height);
1236 }
1237
1238 /* Draw all kind of tracks. */
1239 static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, MovieClip *clip,
1240                                  int width, int height, float zoomx, float zoomy)
1241 {
1242         float x, y;
1243         MovieTracking *tracking = &clip->tracking;
1244         ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
1245         ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
1246         MovieTrackingTrack *track, *act_track;
1247         MovieTrackingPlaneTrack *plane_track, *active_plane_track;
1248         MovieTrackingMarker *marker;
1249         int framenr = ED_space_clip_get_clip_frame_number(sc);
1250         int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
1251         float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];
1252
1253         /* ** find window pixel coordinates of origin ** */
1254
1255         /* UI_view2d_view_to_region_no_clip return integer values, this could
1256          * lead to 1px flickering when view is locked to selection during playbeck.
1257          * to avoid this flickering, calculate base point in the same way as it happens
1258          * in UI_view2d_view_to_region_no_clip, but do it in floats here */
1259
1260         UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
1261
1262         glPushMatrix();
1263         glTranslatef(x, y, 0);
1264
1265         glPushMatrix();
1266         glScalef(zoomx, zoomy, 0);
1267         glMultMatrixf(sc->stabmat);
1268         glScalef(width, height, 0);
1269
1270         act_track = BKE_tracking_track_get_active(tracking);
1271
1272         /* Draw plane tracks */
1273         active_plane_track = BKE_tracking_plane_track_get_active(tracking);
1274         for (plane_track = plane_tracks_base->first;
1275              plane_track;
1276              plane_track = plane_track->next)
1277         {
1278                 if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
1279                         draw_plane_track(sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
1280                 }
1281         }
1282
1283         if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
1284                 int count = 0;
1285
1286                 /* count */
1287                 track = tracksbase->first;
1288                 while (track) {
1289                         if ((track->flag & TRACK_HIDDEN) == 0) {
1290                                 marker = BKE_tracking_marker_get(track, framenr);
1291
1292                                 if (MARKER_VISIBLE(sc, track, marker))
1293                                         count++;
1294                         }
1295
1296                         track = track->next;
1297                 }
1298
1299                 /* undistort */
1300                 if (count) {
1301                         marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");
1302
1303                         track = tracksbase->first;
1304                         fp = marker_pos;
1305                         while (track) {
1306                                 if ((track->flag & TRACK_HIDDEN) == 0) {
1307                                         marker = BKE_tracking_marker_get(track, framenr);
1308
1309                                         if (MARKER_VISIBLE(sc, track, marker)) {
1310                                                 ED_clip_point_undistorted_pos(sc, marker->pos, fp);
1311
1312                                                 if (track == act_track)
1313                                                         active_pos = fp;
1314
1315                                                 fp += 2;
1316                                         }
1317                                 }
1318
1319                                 track = track->next;
1320                         }
1321                 }
1322         }
1323
1324         if (sc->flag & SC_SHOW_TRACK_PATH) {
1325                 track = tracksbase->first;
1326                 while (track) {
1327                         if ((track->flag & TRACK_HIDDEN) == 0)
1328                                 draw_track_path(sc, clip, track);
1329
1330                         track = track->next;
1331                 }
1332         }
1333
1334         /* markers outline and non-selected areas */
1335         track = tracksbase->first;
1336         fp = marker_pos;
1337         while (track) {
1338                 if ((track->flag & TRACK_HIDDEN) == 0) {
1339                         marker = BKE_tracking_marker_get(track, framenr);
1340
1341                         if (MARKER_VISIBLE(sc, track, marker)) {
1342                                 copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1343
1344                                 draw_marker_outline(sc, track, marker, cur_pos, width, height);
1345                                 draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
1346                                 draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
1347                                 draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);
1348
1349                                 if (fp)
1350                                         fp += 2;
1351                         }
1352                 }
1353
1354                 track = track->next;
1355         }
1356
1357         /* selected areas only, so selection wouldn't be overlapped by
1358          * non-selected areas */
1359         track = tracksbase->first;
1360         fp = marker_pos;
1361         while (track) {
1362                 if ((track->flag & TRACK_HIDDEN) == 0) {
1363                         int act = track == act_track;
1364                         marker = BKE_tracking_marker_get(track, framenr);
1365
1366                         if (MARKER_VISIBLE(sc, track, marker)) {
1367                                 if (!act) {
1368                                         copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1369
1370                                         draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
1371                                         draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
1372                                 }
1373
1374                                 if (fp)
1375                                         fp += 2;
1376                         }
1377                 }
1378
1379                 track = track->next;
1380         }
1381
1382         /* active marker would be displayed on top of everything else */
1383         if (act_track) {
1384                 if ((act_track->flag & TRACK_HIDDEN) == 0) {
1385                         marker = BKE_tracking_marker_get(act_track, framenr);
1386
1387                         if (MARKER_VISIBLE(sc, act_track, marker)) {
1388                                 copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
1389
1390                                 draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
1391                                 draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
1392                         }
1393                 }
1394         }
1395
1396         if (sc->flag & SC_SHOW_BUNDLES) {
1397                 MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
1398                 float pos[4], vec[4], mat[4][4], aspy;
1399
1400                 glEnable(GL_POINT_SMOOTH);
1401                 glPointSize(3.0f);
1402
1403                 aspy = 1.0f / clip->tracking.camera.pixel_aspect;
1404                 BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);
1405
1406                 track = tracksbase->first;
1407                 while (track) {
1408                         if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
1409                                 marker = BKE_tracking_marker_get(track, framenr);
1410
1411                                 if (MARKER_VISIBLE(sc, track, marker)) {
1412                                         float npos[2];
1413                                         copy_v3_v3(vec, track->bundle_pos);
1414                                         vec[3] = 1;
1415
1416                                         mul_v4_m4v4(pos, mat, vec);
1417
1418                                         pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
1419                                         pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;
1420
1421                                         BKE_tracking_distort_v2(tracking, pos, npos);
1422
1423                                         if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
1424                                                 vec[0] = (marker->pos[0] + track->offset[0]) * width;
1425                                                 vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;
1426
1427                                                 sub_v2_v2(vec, npos);
1428
1429                                                 if (len_squared_v2(vec) < (3.0f * 3.0f))
1430                                                         glColor3f(0.0f, 1.0f, 0.0f);
1431                                                 else
1432                                                         glColor3f(1.0f, 0.0f, 0.0f);
1433
1434                                                 glBegin(GL_POINTS);
1435                                                 if (undistort)
1436                                                         glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
1437                                                 else
1438                                                         glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
1439                                                 glEnd();
1440                                         }
1441                                 }
1442                         }
1443
1444                         track = track->next;
1445                 }
1446
1447                 glPointSize(1.0f);
1448                 glDisable(GL_POINT_SMOOTH);
1449         }
1450
1451         glPopMatrix();
1452
1453         if (sc->flag & SC_SHOW_NAMES) {
1454                 /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
1455                 track = tracksbase->first;
1456                 fp = marker_pos;
1457                 while (track) {
1458                         if ((track->flag & TRACK_HIDDEN) == 0) {
1459                                 marker = BKE_tracking_marker_get(track, framenr);
1460
1461                                 if (MARKER_VISIBLE(sc, track, marker)) {
1462                                         int act = track == act_track;
1463
1464                                         copy_v2_v2(cur_pos, fp ? fp : marker->pos);
1465
1466                                         draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);
1467
1468                                         if (fp)
1469                                                 fp += 2;
1470                                 }
1471                         }
1472
1473                         track = track->next;
1474                 }
1475         }
1476
1477         glPopMatrix();
1478
1479         if (marker_pos)
1480                 MEM_freeN(marker_pos);
1481 }
1482
1483 static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
1484                             int width, int height, float zoomx, float zoomy)
1485 {
1486         float x, y;
1487         const int n = 10;
1488         int i, j, a;
1489         float pos[2], tpos[2], grid[11][11][2];
1490         MovieTracking *tracking = &clip->tracking;
1491         bGPdata *gpd = NULL;
1492         float aspy = 1.0f / tracking->camera.pixel_aspect;
1493         float dx = (float)width / n, dy = (float)height / n * aspy;
1494         float offsx = 0.0f, offsy = 0.0f;
1495
1496         if (!tracking->camera.focal)
1497                 return;
1498
1499         if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
1500                 return;
1501
1502         UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
1503
1504         glPushMatrix();
1505         glTranslatef(x, y, 0);
1506         glScalef(zoomx, zoomy, 0);
1507         glMultMatrixf(sc->stabmat);
1508         glScalef(width, height, 0);
1509
1510         /* grid */
1511         if (sc->flag & SC_SHOW_GRID) {
1512                 float val[4][2], idx[4][2];
1513                 float min[2], max[2];
1514
1515                 for (a = 0; a < 4; a++) {
1516                         if (a < 2)
1517                                 val[a][a % 2] = FLT_MAX;
1518                         else
1519                                 val[a][a % 2] = -FLT_MAX;
1520                 }
1521
1522                 zero_v2(pos);
1523                 for (i = 0; i <= n; i++) {
1524                         for (j = 0; j <= n; j++) {
1525                                 if (i == 0 || j == 0 || i == n || j == n) {
1526                                         BKE_tracking_distort_v2(tracking, pos, tpos);
1527
1528                                         for (a = 0; a < 4; a++) {
1529                                                 int ok;
1530
1531                                                 if (a < 2)
1532                                                         ok = tpos[a % 2] < val[a][a % 2];
1533                                                 else
1534                                                         ok = tpos[a % 2] > val[a][a % 2];
1535
1536                                                 if (ok) {
1537                                                         copy_v2_v2(val[a], tpos);
1538                                                         idx[a][0] = j;
1539                                                         idx[a][1] = i;
1540                                                 }
1541                                         }
1542                                 }
1543
1544                                 pos[0] += dx;
1545                         }
1546
1547                         pos[0] = 0.0f;
1548                         pos[1] += dy;
1549                 }
1550
1551                 INIT_MINMAX2(min, max);
1552
1553                 for (a = 0; a < 4; a++) {
1554                         pos[0] = idx[a][0] * dx;
1555                         pos[1] = idx[a][1] * dy;
1556
1557                         BKE_tracking_undistort_v2(tracking, pos, tpos);
1558
1559                         minmax_v2v2_v2(min, max, tpos);
1560                 }
1561
1562                 copy_v2_v2(pos, min);
1563                 dx = (max[0] - min[0]) / n;
1564                 dy = (max[1] - min[1]) / n;
1565
1566                 for (i = 0; i <= n; i++) {
1567                         for (j = 0; j <= n; j++) {
1568                                 BKE_tracking_distort_v2(tracking, pos, grid[i][j]);
1569
1570                                 grid[i][j][0] /= width;
1571                                 grid[i][j][1] /= height * aspy;
1572
1573                                 pos[0] += dx;
1574                         }
1575
1576                         pos[0] = min[0];
1577                         pos[1] += dy;
1578                 }
1579
1580                 glColor3f(1.0f, 0.0f, 0.0f);
1581
1582                 for (i = 0; i <= n; i++) {
1583                         glBegin(GL_LINE_STRIP);
1584                         for (j = 0; j <= n; j++) {
1585                                 glVertex2fv(grid[i][j]);
1586                         }
1587                         glEnd();
1588                 }
1589
1590                 for (j = 0; j <= n; j++) {
1591                         glBegin(GL_LINE_STRIP);
1592                         for (i = 0; i <= n; i++) {
1593                                 glVertex2fv(grid[i][j]);
1594                         }
1595                         glEnd();
1596                 }
1597         }
1598
1599         if (sc->gpencil_src != SC_GPENCIL_SRC_TRACK) {
1600                 gpd = clip->gpd;
1601         }
1602
1603         if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
1604                 bGPDlayer *layer = gpd->layers.first;
1605
1606                 while (layer) {
1607                         bGPDframe *frame = layer->frames.first;
1608
1609                         if (layer->flag & GP_LAYER_HIDE) {
1610                                 layer = layer->next;
1611                                 continue;
1612                         }
1613
1614                         glColor4fv(layer->color);
1615                         glLineWidth(layer->thickness);
1616                         glPointSize((float)(layer->thickness + 2));
1617
1618                         while (frame) {
1619                                 bGPDstroke *stroke = frame->strokes.first;
1620
1621                                 while (stroke) {
1622                                         if (stroke->flag & GP_STROKE_2DSPACE) {
1623                                                 if (stroke->totpoints > 1) {
1624                                                         glBegin(GL_LINE_STRIP);
1625                                                         for (i = 0; i < stroke->totpoints - 1; i++) {
1626                                                                 float npos[2], dpos[2], len;
1627                                                                 int steps;
1628
1629                                                                 pos[0] = (stroke->points[i].x + offsx) * width;
1630                                                                 pos[1] = (stroke->points[i].y + offsy) * height * aspy;
1631
1632                                                                 npos[0] = (stroke->points[i + 1].x + offsx) * width;
1633                                                                 npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;
1634
1635                                                                 len = len_v2v2(pos, npos);
1636                                                                 steps = ceil(len / 5.0f);
1637
1638                                                                 /* we want to distort only long straight lines */
1639                                                                 if (stroke->totpoints == 2) {
1640                                                                         BKE_tracking_undistort_v2(tracking, pos, pos);
1641                                                                         BKE_tracking_undistort_v2(tracking, npos, npos);
1642                                                                 }
1643
1644                                                                 sub_v2_v2v2(dpos, npos, pos);
1645                                                                 mul_v2_fl(dpos, 1.0f / steps);
1646
1647                                                                 for (j = 0; j <= steps; j++) {
1648                                                                         BKE_tracking_distort_v2(tracking, pos, tpos);
1649                                                                         glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));
1650
1651                                                                         add_v2_v2(pos, dpos);
1652                                                                 }
1653                                                         }
1654                                                         glEnd();
1655                                                 }
1656                                                 else if (stroke->totpoints == 1) {
1657                                                         glBegin(GL_POINTS);
1658                                                         glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
1659                                                         glEnd();
1660                                                 }
1661                                         }
1662
1663                                         stroke = stroke->next;
1664                                 }
1665
1666                                 frame = frame->next;
1667                         }
1668
1669                         layer = layer->next;
1670                 }
1671
1672                 glLineWidth(1.0f);
1673                 glPointSize(1.0f);
1674         }
1675
1676         glPopMatrix();
1677 }
1678
1679 void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
1680 {
1681         MovieClip *clip = ED_space_clip_get_clip(sc);
1682         Scene *scene = CTX_data_scene(C);
1683         ImBuf *ibuf = NULL;
1684         int width, height;
1685         float zoomx, zoomy;
1686
1687         ED_space_clip_get_size(sc, &width, &height);
1688         ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
1689
1690         /* if no clip, nothing to do */
1691         if (!clip) {
1692                 ED_region_grid_draw(ar, zoomx, zoomy);
1693                 return;
1694         }
1695
1696         if (sc->flag & SC_SHOW_STABLE) {
1697                 float translation[2];
1698                 float aspect = clip->tracking.camera.pixel_aspect;
1699                 float smat[4][4], ismat[4][4];
1700
1701                 if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
1702                         ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc,
1703                                                                &sc->scale, &sc->angle);
1704                 }
1705
1706                 if (ibuf != NULL && width != ibuf->x)
1707                         mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x);
1708                 else
1709                         copy_v2_v2(translation, sc->loc);
1710
1711                 BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation,
1712                                                         sc->scale, sc->angle, sc->stabmat);
1713
1714                 unit_m4(smat);
1715                 smat[0][0] = 1.0f / width;
1716                 smat[1][1] = 1.0f / height;
1717                 invert_m4_m4(ismat, smat);
1718
1719                 mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
1720         }
1721         else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
1722                 ibuf = ED_space_clip_get_buffer(sc);
1723
1724                 zero_v2(sc->loc);
1725                 sc->scale = 1.0f;
1726                 unit_m4(sc->stabmat);
1727                 unit_m4(sc->unistabmat);
1728         }
1729
1730         if (ibuf) {
1731                 draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
1732                 IMB_freeImBuf(ibuf);
1733         }
1734         else if (sc->flag & SC_MUTE_FOOTAGE) {
1735                 draw_movieclip_muted(ar, width, height, zoomx, zoomy);
1736         }
1737         else {
1738                 ED_region_grid_draw(ar, zoomx, zoomy);
1739         }
1740
1741         if (width && height) {
1742                 draw_stabilization_border(sc, ar, width, height, zoomx, zoomy);
1743                 draw_tracking_tracks(sc, scene, ar, clip, width, height, zoomx, zoomy);
1744                 draw_distortion(sc, ar, clip, width, height, zoomx, zoomy);
1745         }
1746 }
1747
1748 void clip_draw_cache_and_notes(const bContext *C, SpaceClip *sc, ARegion *ar)
1749 {
1750         Scene *scene = CTX_data_scene(C);
1751         MovieClip *clip = ED_space_clip_get_clip(sc);
1752         if (clip) {
1753                 draw_movieclip_cache(sc, ar, clip, scene);
1754                 draw_movieclip_notes(sc, ar);
1755         }
1756 }
1757
1758 /* draw grease pencil */
1759 void clip_draw_grease_pencil(bContext *C, int onlyv2d)
1760 {
1761         SpaceClip *sc = CTX_wm_space_clip(C);
1762         MovieClip *clip = ED_space_clip_get_clip(sc);
1763
1764         if (!clip)
1765                 return;
1766
1767         if (onlyv2d) {
1768                 bool is_track_source = sc->gpencil_src == SC_GPENCIL_SRC_TRACK;
1769                 /* if manual calibration is used then grease pencil data
1770                  * associated with the clip is already drawn in draw_distortion
1771                  */
1772                 if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
1773                         glPushMatrix();
1774                         glMultMatrixf(sc->unistabmat);
1775
1776                         if (is_track_source) {
1777                                 MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
1778
1779                                 if (track) {
1780                                         int framenr = ED_space_clip_get_clip_frame_number(sc);
1781                                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1782
1783                                         glTranslatef(marker->pos[0], marker->pos[1], 0.0f);
1784                                 }
1785                         }
1786
1787                         ED_gpencil_draw_2dimage(C);
1788
1789                         glPopMatrix();
1790                 }
1791         }
1792         else {
1793                 ED_gpencil_draw_view2d(C, 0);
1794         }
1795 }