Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / space_clip / clip_graph_draw.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup spclip
22  */
23
24 #include "DNA_movieclip_types.h"
25 #include "DNA_scene_types.h"
26
27 #include "BLI_utildefines.h"
28 #include "BLI_math.h"
29
30 #include "BKE_context.h"
31 #include "BKE_movieclip.h"
32 #include "BKE_tracking.h"
33
34 #include "ED_screen.h"
35 #include "ED_clip.h"
36
37 #include "GPU_immediate.h"
38 #include "GPU_immediate_util.h"
39 #include "GPU_matrix.h"
40 #include "GPU_state.h"
41
42 #include "WM_types.h"
43
44 #include "UI_interface.h"
45 #include "UI_resources.h"
46 #include "UI_view2d.h"
47
48 #include "clip_intern.h"  // own include
49
50 typedef struct TrackMotionCurveUserData {
51   MovieTrackingTrack *act_track;
52   bool sel;
53   float xscale, yscale, hsize;
54   unsigned int pos;
55 } TrackMotionCurveUserData;
56
57 static void tracking_segment_point_cb(void *userdata,
58                                       MovieTrackingTrack *UNUSED(track),
59                                       MovieTrackingMarker *UNUSED(marker),
60                                       int UNUSED(coord),
61                                       int scene_framenr,
62                                       float val)
63 {
64   TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata;
65
66   immVertex2f(data->pos, scene_framenr, val);
67 }
68
69 static void tracking_segment_start_cb(void *userdata,
70                                       MovieTrackingTrack *track,
71                                       int coord,
72                                       bool is_point)
73 {
74   TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata;
75   float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
76
77   col[coord] = 1.0f;
78
79   if (track == data->act_track) {
80     col[3] = 1.0f;
81     GPU_line_width(2.0f);
82   }
83   else {
84     col[3] = 0.5f;
85     GPU_line_width(1.0f);
86   }
87
88   immUniformColor4fv(col);
89
90   if (is_point) {
91     immBeginAtMost(GPU_PRIM_POINTS, 1);
92   }
93   else {
94     /* Graph can be composed of smaller segments, if any marker is disabled */
95     immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
96   }
97 }
98
99 static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord))
100 {
101   immEnd();
102 }
103
104 static void tracking_segment_knot_cb(void *userdata,
105                                      MovieTrackingTrack *track,
106                                      MovieTrackingMarker *marker,
107                                      int coord,
108                                      int scene_framenr,
109                                      float val)
110 {
111   TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata;
112   int sel = 0, sel_flag;
113
114   if (track != data->act_track) {
115     return;
116   }
117
118   sel_flag = coord == 0 ? MARKER_GRAPH_SEL_X : MARKER_GRAPH_SEL_Y;
119   sel = (marker->flag & sel_flag) ? 1 : 0;
120
121   if (sel == data->sel) {
122     immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX);
123
124     GPU_matrix_push();
125     GPU_matrix_translate_2f(scene_framenr, val);
126     GPU_matrix_scale_2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
127
128     imm_draw_circle_wire_2d(data->pos, 0, 0, 0.7, 8);
129
130     GPU_matrix_pop();
131   }
132 }
133
134 static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int pos)
135 {
136   MovieClip *clip = ED_space_clip_get_clip(sc);
137   MovieTracking *tracking = &clip->tracking;
138   MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
139   int width, height;
140   TrackMotionCurveUserData userdata;
141
142   BKE_movieclip_get_size(clip, &sc->user, &width, &height);
143
144   if (!width || !height) {
145     return;
146   }
147
148   /* non-selected knot handles */
149   userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
150   userdata.sel = false;
151   userdata.act_track = act_track;
152   userdata.pos = pos;
153   UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale);
154   clip_graph_tracking_values_iterate(sc,
155                                      (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
156                                      (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
157                                      &userdata,
158                                      tracking_segment_knot_cb,
159                                      NULL,
160                                      NULL);
161   /* draw graph lines */
162   GPU_blend(true);
163   clip_graph_tracking_values_iterate(sc,
164                                      (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
165                                      (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
166                                      &userdata,
167                                      tracking_segment_point_cb,
168                                      tracking_segment_start_cb,
169                                      tracking_segment_end_cb);
170   GPU_blend(false);
171
172   /* selected knot handles on top of curves */
173   userdata.sel = true;
174   clip_graph_tracking_values_iterate(sc,
175                                      (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
176                                      (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
177                                      &userdata,
178                                      tracking_segment_knot_cb,
179                                      NULL,
180                                      NULL);
181 }
182
183 typedef struct TrackErrorCurveUserData {
184   MovieClip *clip;
185   MovieTracking *tracking;
186   MovieTrackingObject *tracking_object;
187   MovieTrackingTrack *active_track;
188   bool matrix_initialized;
189   int matrix_frame;
190   float projection_matrix[4][4];
191   int width, height;
192   float aspy;
193   unsigned int pos;
194 } TrackErrorCurveUserData;
195
196 static void tracking_error_segment_point_cb(void *userdata,
197                                             MovieTrackingTrack *track,
198                                             MovieTrackingMarker *marker,
199                                             int coord,
200                                             int scene_framenr,
201                                             float UNUSED(value))
202 {
203   if (coord == 1) {
204     TrackErrorCurveUserData *data = (TrackErrorCurveUserData *)userdata;
205     float reprojected_position[4], bundle_position[4], marker_position[2], delta[2];
206     float reprojection_error;
207     float weight = BKE_tracking_track_get_weight_for_marker(data->clip, track, marker);
208
209     if (!data->matrix_initialized || data->matrix_frame != scene_framenr) {
210       BKE_tracking_get_projection_matrix(data->tracking,
211                                          data->tracking_object,
212                                          scene_framenr,
213                                          data->width,
214                                          data->height,
215                                          data->projection_matrix);
216     }
217
218     copy_v3_v3(bundle_position, track->bundle_pos);
219     bundle_position[3] = 1;
220
221     mul_v4_m4v4(reprojected_position, data->projection_matrix, bundle_position);
222     reprojected_position[0] = (reprojected_position[0] / (reprojected_position[3] * 2.0f) + 0.5f) *
223                               data->width;
224     reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) *
225                               data->height * data->aspy;
226
227     BKE_tracking_distort_v2(data->tracking, reprojected_position, reprojected_position);
228
229     marker_position[0] = (marker->pos[0] + track->offset[0]) * data->width;
230     marker_position[1] = (marker->pos[1] + track->offset[1]) * data->height * data->aspy;
231
232     sub_v2_v2v2(delta, reprojected_position, marker_position);
233     reprojection_error = len_v2(delta) * weight;
234
235     immVertex2f(data->pos, scene_framenr, reprojection_error);
236   }
237 }
238
239 static void tracking_error_segment_start_cb(void *userdata,
240                                             MovieTrackingTrack *track,
241                                             int coord,
242                                             bool is_point)
243 {
244   if (coord == 1) {
245     TrackErrorCurveUserData *data = (TrackErrorCurveUserData *)userdata;
246     float col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
247
248     if (track == data->active_track) {
249       col[3] = 1.0f;
250       GPU_line_width(2.0f);
251     }
252     else {
253       col[3] = 0.5f;
254       GPU_line_width(1.0f);
255     }
256
257     immUniformColor4fv(col);
258
259     if (is_point) { /* This probably never happens here, but just in case... */
260       immBeginAtMost(GPU_PRIM_POINTS, 1);
261     }
262     else {
263       /* Graph can be composed of smaller segments, if any marker is disabled */
264       immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr);
265     }
266   }
267 }
268
269 static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord)
270 {
271   if (coord == 1) {
272     immEnd();
273   }
274 }
275
276 static void draw_tracks_error_curves(SpaceClip *sc, unsigned int pos)
277 {
278   MovieClip *clip = ED_space_clip_get_clip(sc);
279   MovieTracking *tracking = &clip->tracking;
280   TrackErrorCurveUserData data;
281
282   data.clip = clip;
283   data.tracking = tracking;
284   data.tracking_object = BKE_tracking_object_get_active(tracking);
285   data.active_track = BKE_tracking_track_get_active(tracking);
286   data.matrix_initialized = false;
287   data.pos = pos;
288   BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height);
289   data.aspy = 1.0f / tracking->camera.pixel_aspect;
290
291   if (!data.width || !data.height) {
292     return;
293   }
294
295   clip_graph_tracking_values_iterate(sc,
296                                      (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
297                                      (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
298                                      &data,
299                                      tracking_error_segment_point_cb,
300                                      tracking_error_segment_start_cb,
301                                      tracking_error_segment_end_cb);
302 }
303
304 static void draw_frame_curves(SpaceClip *sc, unsigned int pos)
305 {
306   MovieClip *clip = ED_space_clip_get_clip(sc);
307   MovieTracking *tracking = &clip->tracking;
308   MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
309   int i, lines = 0, prevfra = 0;
310
311   immUniformColor3f(0.0f, 0.0f, 1.0f);
312
313   for (i = 0; i < reconstruction->camnr; i++) {
314     MovieReconstructedCamera *camera = &reconstruction->cameras[i];
315     int framenr;
316
317     if (lines && camera->framenr != prevfra + 1) {
318       immEnd();
319       lines = 0;
320     }
321
322     if (!lines) {
323       immBeginAtMost(GPU_PRIM_LINE_STRIP, reconstruction->camnr);
324       lines = 1;
325     }
326
327     framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, camera->framenr);
328     immVertex2f(pos, framenr, camera->error);
329
330     prevfra = camera->framenr;
331   }
332
333   if (lines) {
334     immEnd();
335   }
336 }
337
338 void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
339 {
340   MovieClip *clip = ED_space_clip_get_clip(sc);
341   View2D *v2d = &ar->v2d;
342   View2DGrid *grid;
343   short unitx = V2D_UNIT_FRAMESCALE, unity = V2D_UNIT_VALUES;
344
345   /* grid */
346   grid = UI_view2d_grid_calc(
347       scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
348   UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
349   UI_view2d_grid_free(grid);
350
351   if (clip) {
352     uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
353     immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
354
355     GPU_point_size(3.0f);
356
357     if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) {
358       draw_tracks_motion_curves(v2d, sc, pos);
359     }
360
361     if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) {
362       draw_tracks_error_curves(sc, pos);
363     }
364
365     if (sc->flag & SC_SHOW_GRAPH_FRAMES) {
366       draw_frame_curves(sc, pos);
367     }
368
369     immUnbindProgram();
370   }
371
372   /* frame range */
373   clip_draw_sfra_efra(v2d, scene);
374 }