Blender V4.5
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
8
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).dimensions(2);
41}
42
43static void init(const bContext *C, PointerRNA *ptr)
44{
45 bNode *node = (bNode *)ptr->data;
46
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;
79 PointerRNA tracking_ptr = RNA_pointer_create_discrete(&clip->id, &RNA_MovieTracking, tracking);
80
81 col = &layout->column(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) {
87 &clip->id, &RNA_MovieTrackingObject, tracking_object);
88
89 uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
90 }
91 else {
92 layout->prop(ptr, "track_name", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_ANIM_DATA);
93 }
94
95 layout->prop(ptr, "position", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
96
97 if (ELEM(node->custom1,
100 {
101 layout->prop(ptr, "frame_relative", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
102 }
103 }
104}
105
106using namespace blender::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_single_value(position.x);
145 }
146
147 if (should_compute_y) {
148 Result &result = get_result("Y");
149 result.allocate_single_value();
150 result.set_single_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 * float2(size),
175 speed_toward_next * float2(size));
176
177 Result &result = get_result("Speed");
178 result.set_type(ResultType::Float4);
179 result.allocate_single_value();
180 result.set_single_value(speed);
181 }
182
184 {
185 if (should_compute_output("X")) {
186 Result &result = get_result("X");
187 result.allocate_single_value();
188 result.set_single_value(0.0f);
189 }
190 if (should_compute_output("Y")) {
191 Result &result = get_result("Y");
192 result.allocate_single_value();
193 result.set_single_value(0.0f);
194 }
195 if (should_compute_output("Speed")) {
196 Result &result = get_result("Speed");
197 result.set_type(ResultType::Float4);
198 result.allocate_single_value();
199 result.set_single_value(float4(0.0f));
200 }
201 }
202
203 /* Compute the position of the marker that is delta time away from the evaluation frame. If no
204 * marker exist for that particular frame or is disabled, the current marker position is
205 * returned. This is useful for computing the speed by providing small negative and positive
206 * delta times. */
208 float2 current_marker_position,
209 int time_delta)
210 {
211 const int local_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
212 get_movie_clip(), get_frame() + time_delta);
213 MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, local_frame_number);
214
215 if (marker == nullptr || marker->flag & MARKER_DISABLED) {
216 return current_marker_position;
217 }
218
219 return float2(marker->pos);
220 }
221
222 /* Compute the position of the reference marker which the output position will be computed
223 * relative to. For non-relative modes, this is just the zero origin or the tracking space. See
224 * the get_mode() method for more information. */
236
237 /* Compute the position of the first non-disabled marker in the track. */
239 {
240 for (const int i : IndexRange(track->markersnr)) {
241 MovieTrackingMarker &marker = track->markers[i];
242
243 if (marker.flag & MARKER_DISABLED) {
244 continue;
245 }
246
247 return float2(marker.pos);
248 }
249
250 return float2(0.0f);
251 }
252
253 /* Compute the marker position at the given frame, if no such marker exist, return the position
254 * of the temporally nearest marker before it, if no such marker exist, return the position of
255 * the temporally nearest marker after it. */
257 {
258 const int local_frame_number = BKE_movieclip_remap_scene_to_clip_frame(get_movie_clip(),
259 frame);
260 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, local_frame_number);
261 return float2(marker->pos);
262 }
263
264 /* Get the movie tracking track corresponding to the given object and track names. If no such
265 * track exist, return nullptr. */
267 {
268 MovieClip *movie_clip = get_movie_clip();
269 if (!movie_clip) {
270 return nullptr;
271 }
272
273 MovieTracking *movie_tracking = &movie_clip->tracking;
274
275 MovieTrackingObject *movie_tracking_object = BKE_tracking_object_get_named(
276 movie_tracking, node_storage(bnode()).tracking_object);
277 if (!movie_tracking_object) {
278 return nullptr;
279 }
280
281 return BKE_tracking_object_find_track_with_name(movie_tracking_object,
282 node_storage(bnode()).track_name);
283 }
284
285 /* Get the size of the movie clip at the evaluation frame. This is constant for all frames in
286 * most cases. */
288 {
291
292 int2 size;
294
295 return size;
296 }
297
298 /* In the CMP_NODE_TRACK_POSITION_RELATIVE_FRAME mode, this represents the offset that will be
299 * added to the current scene frame. See the get_mode() method for more information. */
301 {
302 return bnode().custom2;
303 }
304
305 /* Get the frame where the marker will be retrieved. This is the absolute frame for the absolute
306 * mode and the current scene frame otherwise. */
308 {
310 return get_absolute_frame();
311 }
312
313 return context().get_frame_number();
314 }
315
316 /* In the CMP_NODE_TRACK_POSITION_ABSOLUTE_FRAME mode, this represents the frame where the marker
317 * will be retrieved. See the get_mode() method for more information. */
319 {
320 return bnode().custom2;
321 }
322
323 /* CMP_NODE_TRACK_POSITION_ABSOLUTE:
324 * Returns the position and speed of the marker at the current scene frame relative to the zero
325 * origin of the tracking space.
326 *
327 * CMP_NODE_TRACK_POSITION_RELATIVE_START:
328 * Returns the position and speed of the marker at the current scene frame relative to the
329 * position of the first non-disabled marker in the track.
330 *
331 * CMP_NODE_TRACK_POSITION_RELATIVE_FRAME:
332 * Returns the position and speed of the marker at the current scene frame relative to the
333 * position of the marker at the current scene frame plus the user given relative frame.
334 *
335 * CMP_NODE_TRACK_POSITION_ABSOLUTE_FRAME:
336 * Returns the position and speed of the marker at the given absolute frame. */
338 {
339 return static_cast<CMPNodeTrackPositionMode>(bnode().custom1);
340 }
341
343 {
344 return (MovieClip *)bnode().id;
345 }
346};
347
349{
350 return new TrackPositionOperation(context, node);
351}
352
353} // namespace blender::nodes::node_composite_trackpos_cc
354
356{
358
359 static blender::bke::bNodeType ntype;
360
361 cmp_node_type_base(&ntype, "CompositorNodeTrackPos", CMP_NODE_TRACKPOS);
362 ntype.ui_name = "Track Position";
363 ntype.ui_description =
364 "Provide information about motion tracking points, such as x and y values";
365 ntype.enum_name_legacy = "TRACKPOS";
366 ntype.nclass = NODE_CLASS_INPUT;
367 ntype.declare = file_ns::cmp_node_trackpos_declare;
368 ntype.draw_buttons = file_ns::node_composit_buts_trackpos;
369 ntype.initfunc_api = file_ns::init;
371 ntype, "NodeTrackPosData", node_free_standard_storage, node_copy_standard_storage);
372 ntype.get_compositor_operation = file_ns::get_compositor_operation;
373
375}
Scene * CTX_data_scene(const bContext *C)
void id_us_plus(ID *id)
Definition lib_id.cc:353
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:1215
#define NODE_CLASS_INPUT
Definition BKE_node.hh:433
#define CMP_NODE_TRACKPOS
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition tracking.cc:1965
struct MovieTrackingMarker * BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1357
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:1390
struct MovieTrackingTrack * BKE_tracking_object_find_track_with_name(struct MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:1992
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#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
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_VELOCITY
Definition RNA_types.hh:251
#define C
Definition RandGen.cpp:29
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *searchptr, blender::StringRefNull searchpropname, std::optional< blender::StringRefNull > name, int icon)
BMesh const char void * data
void init()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool should_compute_output(StringRef identifier)
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Definition operation.cc:39
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)
uint col
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5603
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< int32_t, 2 > int2
VecBase< float, 2 > float2
static void register_node_type_cmp_trackpos()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
struct MovieTracking tracking
MovieTrackingTrack * active_track
MovieTrackingMarker * markers
struct MovieClip * clip
int16_t custom1
struct ID * id
void * storage
int16_t custom2
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:336
const char * enum_name_legacy
Definition BKE_node.hh:235
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:355
void(* initfunc_api)(const bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:290
uiLayout & column(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4227