Blender V4.3
node_composite_trackpos.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_index_range.hh"
11#include "BLI_string.h"
12
13#include "DNA_defaults.h"
14#include "DNA_movieclip_types.h"
15#include "DNA_tracking_types.h"
16
17#include "BKE_context.hh"
18#include "BKE_lib_id.hh"
19#include "BKE_movieclip.h"
20#include "BKE_tracking.h"
21
22#include "RNA_access.hh"
23#include "RNA_prototypes.hh"
24
25#include "UI_interface.hh"
26#include "UI_resources.hh"
27
28#include "COM_node_operation.hh"
29
31
33
35
37{
38 b.add_output<decl::Float>("X");
39 b.add_output<decl::Float>("Y");
40 b.add_output<decl::Vector>("Speed").subtype(PROP_VELOCITY);
41}
42
43static void init(const bContext *C, PointerRNA *ptr)
44{
45 bNode *node = (bNode *)ptr->data;
46
47 NodeTrackPosData *data = MEM_cnew<NodeTrackPosData>(__func__);
48 node->storage = data;
49
50 const Scene *scene = CTX_data_scene(C);
51 if (scene->clip) {
52 MovieClip *clip = scene->clip;
53 MovieTracking *tracking = &clip->tracking;
54
55 node->id = &clip->id;
56 id_us_plus(&clip->id);
57
58 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
59 STRNCPY(data->tracking_object, tracking_object->name);
60
61 if (tracking_object->active_track) {
62 STRNCPY(data->track_name, tracking_object->active_track->name);
63 }
64 }
65}
66
68{
69 bNode *node = (bNode *)ptr->data;
70
71 uiTemplateID(layout, C, ptr, "clip", nullptr, "CLIP_OT_open", nullptr);
72
73 if (node->id) {
74 MovieClip *clip = (MovieClip *)node->id;
75 MovieTracking *tracking = &clip->tracking;
76 MovieTrackingObject *tracking_object;
78 NodeTrackPosData *data = (NodeTrackPosData *)node->storage;
79 PointerRNA tracking_ptr = RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking);
80
81 col = uiLayoutColumn(layout, false);
82 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
83
84 tracking_object = BKE_tracking_object_get_named(tracking, data->tracking_object);
85 if (tracking_object) {
86 PointerRNA object_ptr = RNA_pointer_create(
87 &clip->id, &RNA_MovieTrackingObject, tracking_object);
88
89 uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
90 }
91 else {
92 uiItemR(layout, ptr, "track_name", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_ANIM_DATA);
93 }
94
95 uiItemR(layout, ptr, "position", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
96
97 if (ELEM(node->custom1,
100 {
101 uiItemR(layout, ptr, "frame_relative", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
102 }
103 }
104}
105
106using namespace blender::realtime_compositor;
107
109 public:
111
112 void execute() override
113 {
115
116 if (!track) {
118 return;
119 }
120
121 const float2 current_marker_position = compute_marker_position_at_frame(track, get_frame());
122 const int2 size = get_size();
123
124 execute_position(track, current_marker_position, size);
125 execute_speed(track, current_marker_position, size);
126 }
127
128 void execute_position(MovieTrackingTrack *track, float2 current_marker_position, int2 size)
129 {
130 const bool should_compute_x = should_compute_output("X");
131 const bool should_compute_y = should_compute_output("Y");
132 if (!should_compute_x && !should_compute_y) {
133 return;
134 }
135
136 /* Compute the position relative to the reference marker position. Multiply by the size to get
137 * the position in pixel space. */
138 const float2 reference_marker_position = compute_reference_marker_position(track);
139 const float2 position = (current_marker_position - reference_marker_position) * float2(size);
140
141 if (should_compute_x) {
142 Result &result = get_result("X");
143 result.allocate_single_value();
144 result.set_float_value(position.x);
145 }
146
147 if (should_compute_y) {
148 Result &result = get_result("Y");
149 result.allocate_single_value();
150 result.set_float_value(position.y);
151 }
152 }
153
154 void execute_speed(MovieTrackingTrack *track, float2 current_marker_position, int2 size)
155 {
156 if (!should_compute_output("Speed")) {
157 return;
158 }
159
160 /* Compute the speed as the difference between the previous marker position and the current
161 * marker position. Notice that we compute the speed from the current to the previous position,
162 * not the other way around. */
163 const float2 previous_marker_position = compute_temporally_neighboring_marker_position(
164 track, current_marker_position, -1);
165 const float2 speed_toward_previous = previous_marker_position - current_marker_position;
166
167 /* Compute the speed as the difference between the current marker position and the next marker
168 * position. */
169 const float2 next_marker_position = compute_temporally_neighboring_marker_position(
170 track, current_marker_position, 1);
171 const float2 speed_toward_next = current_marker_position - next_marker_position;
172
173 /* Encode both speeds in a 4D vector. Multiply by the size to get the speed in pixel space. */
174 const float4 speed = float4(speed_toward_previous, speed_toward_next) * float4(size, size);
175
176 Result &result = get_result("Speed");
177 result.allocate_single_value();
178 result.set_vector_value(speed);
179 }
180
182 {
183 if (should_compute_output("X")) {
184 Result &result = get_result("X");
185 result.allocate_single_value();
186 result.set_float_value(0.0f);
187 }
188 if (should_compute_output("Y")) {
189 Result &result = get_result("Y");
190 result.allocate_single_value();
191 result.set_float_value(0.0f);
192 }
193 if (should_compute_output("Speed")) {
194 Result &result = get_result("Speed");
195 result.allocate_single_value();
196 result.set_vector_value(float4(0.0f));
197 }
198 }
199
200 /* Compute the position of the marker that is delta time away from the evaluation frame. If no
201 * marker exist for that particular frame or is disabled, the current marker position is
202 * returned. This is useful for computing the speed by providing small negative and positive
203 * delta times. */
205 float2 current_marker_position,
206 int time_delta)
207 {
208 const int local_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
209 get_movie_clip(), get_frame() + time_delta);
210 MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, local_frame_number);
211
212 if (marker == nullptr || marker->flag & MARKER_DISABLED) {
213 return current_marker_position;
214 }
215
216 return float2(marker->pos);
217 }
218
219 /* Compute the position of the reference marker which the output position will be computed
220 * relative to. For non-relative modes, this is just the zero origin or the tracking space. See
221 * the get_mode() method for more information. */
233
234 /* Compute the position of the first non-disabled marker in the track. */
236 {
237 for (const int i : IndexRange(track->markersnr)) {
238 MovieTrackingMarker &marker = track->markers[i];
239
240 if (marker.flag & MARKER_DISABLED) {
241 continue;
242 }
243
244 return float2(marker.pos);
245 }
246
247 return float2(0.0f);
248 }
249
250 /* Compute the marker position at the given frame, if no such marker exist, return the position
251 * of the temporally nearest marker before it, if no such marker exist, return the position of
252 * the temporally nearest marker after it. */
254 {
255 const int local_frame_number = BKE_movieclip_remap_scene_to_clip_frame(get_movie_clip(),
256 frame);
257 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, local_frame_number);
258 return float2(marker->pos);
259 }
260
261 /* Get the movie tracking track corresponding to the given object and track names. If no such
262 * track exist, return nullptr. */
264 {
265 MovieClip *movie_clip = get_movie_clip();
266 if (!movie_clip) {
267 return nullptr;
268 }
269
270 MovieTracking *movie_tracking = &movie_clip->tracking;
271
272 MovieTrackingObject *movie_tracking_object = BKE_tracking_object_get_named(
273 movie_tracking, node_storage(bnode()).tracking_object);
274 if (!movie_tracking_object) {
275 return nullptr;
276 }
277
278 return BKE_tracking_object_find_track_with_name(movie_tracking_object,
279 node_storage(bnode()).track_name);
280 }
281
282 /* Get the size of the movie clip at the evaluation frame. This is constant for all frames in
283 * most cases. */
285 {
288
289 int2 size;
290 BKE_movieclip_get_size(get_movie_clip(), &user, &size.x, &size.y);
291
292 return size;
293 }
294
295 /* In the CMP_NODE_TRACK_POSITION_RELATIVE_FRAME mode, this represents the offset that will be
296 * added to the current scene frame. See the get_mode() method for more information. */
298 {
299 return bnode().custom2;
300 }
301
302 /* Get the frame where the marker will be retrieved. This is the absolute frame for the absolute
303 * mode and the current scene frame otherwise. */
305 {
307 return get_absolute_frame();
308 }
309
310 return context().get_frame_number();
311 }
312
313 /* In the CMP_NODE_TRACK_POSITION_ABSOLUTE_FRAME mode, this represents the frame where the marker
314 * will be retrieved. See the get_mode() method for more information. */
316 {
317 return bnode().custom2;
318 }
319
320 /* CMP_NODE_TRACK_POSITION_ABSOLUTE:
321 * Returns the position and speed of the marker at the current scene frame relative to the zero
322 * origin of the tracking space.
323 *
324 * CMP_NODE_TRACK_POSITION_RELATIVE_START:
325 * Returns the position and speed of the marker at the current scene frame relative to the
326 * position of the first non-disabled marker in the track.
327 *
328 * CMP_NODE_TRACK_POSITION_RELATIVE_FRAME:
329 * Returns the position and speed of the marker at the current scene frame relative to the
330 * position of the marker at the current scene frame plus the user given relative frame.
331 *
332 * CMP_NODE_TRACK_POSITION_ABSOLUTE_FRAME:
333 * Returns the position and speed of the marker at the given absolute frame. */
335 {
336 return static_cast<CMPNodeTrackPositionMode>(bnode().custom1);
337 }
338
340 {
341 return (MovieClip *)bnode().id;
342 }
343};
344
346{
347 return new TrackPositionOperation(context, node);
348}
349
350} // namespace blender::nodes::node_composite_trackpos_cc
351
353{
355
356 static blender::bke::bNodeType ntype;
357
358 cmp_node_type_base(&ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT);
359 ntype.declare = file_ns::cmp_node_trackpos_declare;
360 ntype.draw_buttons = file_ns::node_composit_buts_trackpos;
361 ntype.initfunc_api = file_ns::init;
363 &ntype, "NodeTrackPosData", node_free_standard_storage, node_copy_standard_storage);
364 ntype.get_compositor_operation = file_ns::get_compositor_operation;
365
367}
Scene * CTX_data_scene(const bContext *C)
void id_us_plus(ID *id)
Definition lib_id.cc:351
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition tracking.cc:1966
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1358
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
struct MovieTrackingTrack * BKE_tracking_object_find_track_with_name(struct MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:1993
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ELEM(...)
#define DNA_struct_default_get(struct_name)
CMPNodeTrackPositionMode
@ CMP_NODE_TRACK_POSITION_RELATIVE_START
@ CMP_NODE_TRACK_POSITION_ABSOLUTE_FRAME
@ CMP_NODE_TRACK_POSITION_RELATIVE_FRAME
@ MARKER_DISABLED
@ PROP_VELOCITY
Definition RNA_types.hh:166
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, const char *text=nullptr)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
void init()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void execute_position(MovieTrackingTrack *track, float2 current_marker_position, int2 size)
void execute_speed(MovieTrackingTrack *track, float2 current_marker_position, int2 size)
float2 compute_marker_position_at_frame(MovieTrackingTrack *track, int frame)
float2 compute_temporally_neighboring_marker_position(MovieTrackingTrack *track, float2 current_marker_position, int time_delta)
NodeOperation(Context &context, DNode node)
bool should_compute_output(StringRef identifier)
Result & get_result(StringRef identifier)
Definition operation.cc:46
local_group_size(16, 16) .push_constant(Type b
uint col
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
static void cmp_node_trackpos_declare(NodeDeclarationBuilder &b)
static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
VecBase< float, 4 > float4
VecBase< float, 2 > float2
void register_node_type_cmp_trackpos()
void cmp_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
struct MovieTracking tracking
MovieTrackingTrack * active_track
MovieTrackingMarker * markers
void * data
Definition RNA_types.hh:42
int16_t custom1
struct ID * id
int16_t custom2
Defines a node type.
Definition BKE_node.hh:218
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:324
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:280
PointerRNA * ptr
Definition wm_files.cc:4126