Blender V4.3
constraint.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9/* Allow using deprecated functionality for .blend file I/O. */
10#define DNA_DEPRECATED_ALLOW
11
12#include <algorithm>
13#include <cfloat>
14#include <cmath>
15#include <cstddef>
16#include <cstdio>
17#include <cstring>
18
19#include "MEM_guardedalloc.h"
20
21#include "BLI_blenlib.h"
22#include "BLI_kdopbvh.h"
23#include "BLI_listbase.h"
24#include "BLI_math_matrix.h"
25#include "BLI_math_rotation.h"
26#include "BLI_math_vector.h"
27#include "BLI_string_utils.hh"
28#include "BLI_utildefines.h"
29#include "BLT_translation.hh"
30
31#include "DNA_action_types.h"
32#include "DNA_armature_types.h"
33#include "DNA_cachefile_types.h"
35#include "DNA_curve_types.h"
36#include "DNA_mesh_types.h"
37#include "DNA_meshdata_types.h"
38#include "DNA_modifier_types.h"
39#include "DNA_object_types.h"
40#include "DNA_screen_types.h"
41
42#include "DNA_lattice_types.h"
43#include "DNA_movieclip_types.h"
44#include "DNA_scene_types.h"
45#include "DNA_tracking_types.h"
46
47#include "BKE_action.hh"
48#include "BKE_anim_path.h"
49#include "BKE_animsys.h"
50#include "BKE_armature.hh"
51#include "BKE_bvhutils.hh"
52#include "BKE_cachefile.hh"
53#include "BKE_camera.h"
54#include "BKE_constraint.h"
55#include "BKE_curve.hh"
56#include "BKE_deform.hh"
57#include "BKE_displist.h"
58#include "BKE_editmesh.hh"
59#include "BKE_fcurve_driver.h"
60#include "BKE_global.hh"
61#include "BKE_idprop.hh"
62#include "BKE_lib_id.hh"
63#include "BKE_lib_query.hh"
64#include "BKE_mesh.hh"
65#include "BKE_mesh_runtime.hh"
66#include "BKE_movieclip.h"
67#include "BKE_object.hh"
68#include "BKE_object_types.hh"
69#include "BKE_scene.hh"
70#include "BKE_shrinkwrap.hh"
71#include "BKE_tracking.h"
72
73#include "BIK_api.h"
74
75#include "DEG_depsgraph.hh"
77
78#include "BLO_read_write.hh"
79
80#include "ANIM_action.hh"
81
82#include "CLG_log.h"
83
84#ifdef WITH_PYTHON
85# include "BPY_extern.hh"
86#endif
87
88#ifdef WITH_ALEMBIC
89# include "ABC_alembic.h"
90#endif
91
92#ifdef WITH_USD
93# include "usd.hh"
94#endif
95
96/* ---------------------------------------------------------------------------- */
97/* Useful macros for testing various common flag combinations */
98
99/* Constraint Target Macros */
100#define VALID_CONS_TARGET(ct) ((ct) && (ct->tar))
101
102static CLG_LogRef LOG = {"bke.constraint"};
103
104/* ************************ Constraints - General Utilities *************************** */
105/* These functions here don't act on any specific constraints, and are therefore should/will
106 * not require any of the special function-pointers afforded by the relevant constraint
107 * type-info structs.
108 */
109
110static void damptrack_do_transform(float matrix[4][4], const float tarvec[3], int track_axis);
111
113 bPoseChannel *pchan,
114 bConstraint *con,
115 Object **r_orig_ob);
117
118/* -------------- Naming -------------- */
119
121{
122 BLI_uniquename(list, con, DATA_("Const"), '.', offsetof(bConstraint, name), sizeof(con->name));
123}
124
125/* ----------------- Evaluation Loop Preparation --------------- */
126
128 Depsgraph *depsgraph, Scene *scene, Object *ob, void *subdata, short datatype)
129{
130 bConstraintOb *cob;
131
132 /* create regardless of whether we have any data! */
133 cob = static_cast<bConstraintOb *>(MEM_callocN(sizeof(bConstraintOb), "bConstraintOb"));
134
135 /* NOTE(@ton): For system time, part of de-globalization, code nicer later with local time. */
136 cob->scene = scene;
137 cob->depsgraph = depsgraph;
138
139 /* based on type of available data */
140 switch (datatype) {
142 /* disregard subdata... calloc should set other values right */
143 if (ob) {
144 cob->ob = ob;
145 cob->type = datatype;
146
147 if (cob->ob->rotmode > 0) {
148 /* Should be some kind of Euler order, so use it */
149 /* NOTE: Versions <= 2.76 assumed that "default" order
150 * would always get used, so we may seem some rig
151 * breakage as a result. However, this change here
152 * is needed to fix #46599
153 */
154 cob->rotOrder = ob->rotmode;
155 }
156 else {
157 /* Quaternion/Axis-Angle, so Eulers should just use default order. */
159 }
160 copy_m4_m4(cob->matrix, ob->object_to_world().ptr());
161 }
162 else {
163 unit_m4(cob->matrix);
164 }
165
166 copy_m4_m4(cob->startmat, cob->matrix);
167 break;
168 }
170 /* only set if we have valid bone, otherwise default */
171 if (ob && subdata) {
172 cob->ob = ob;
173 cob->pchan = (bPoseChannel *)subdata;
174 cob->type = datatype;
175
176 if (cob->pchan->rotmode > 0) {
177 /* should be some type of Euler order */
178 cob->rotOrder = cob->pchan->rotmode;
179 }
180 else {
181 /* Quaternion, so eulers should just use default order */
183 }
184
185 /* matrix in world-space */
186 mul_m4_m4m4(cob->matrix, ob->object_to_world().ptr(), cob->pchan->pose_mat);
187 }
188 else {
189 unit_m4(cob->matrix);
190 }
191
192 copy_m4_m4(cob->startmat, cob->matrix);
193 break;
194 }
195 default: /* other types not yet handled */
196 unit_m4(cob->matrix);
197 unit_m4(cob->startmat);
198 break;
199 }
200
201 return cob;
202}
203
205{
206 float delta[4][4], imat[4][4];
207
208 /* prevent crashes */
209 if (cob == nullptr) {
210 return;
211 }
212
213 /* calculate delta of constraints evaluation */
214 invert_m4_m4(imat, cob->startmat);
215 /* XXX This would seem to be in wrong order. However, it does not work in 'right' order - would
216 * be nice to understand why pre-multiply is needed here instead of usual post-multiply?
217 * In any case, we *do not get a delta* here (e.g. startmat & matrix having same location,
218 * still gives a 'delta' with non-null translation component :/ ). */
219 mul_m4_m4m4(delta, cob->matrix, imat);
220
221 /* copy matrices back to source */
222 switch (cob->type) {
224 /* cob->ob might not exist! */
225 if (cob->ob) {
226 /* copy new ob-matrix back to owner */
227 copy_m4_m4(cob->ob->runtime->object_to_world.ptr(), cob->matrix);
228
229 /* copy inverse of delta back to owner */
230 invert_m4_m4(cob->ob->constinv, delta);
231 }
232 break;
233 }
235 /* cob->ob or cob->pchan might not exist */
236 if (cob->ob && cob->pchan) {
237 /* copy new pose-matrix back to owner */
238 mul_m4_m4m4(cob->pchan->pose_mat, cob->ob->world_to_object().ptr(), cob->matrix);
239
240 /* copy inverse of delta back to owner */
241 invert_m4_m4(cob->pchan->constinv, delta);
242 }
243 break;
244 }
245 }
246
247 /* Free temporary struct. */
248 MEM_freeN(cob);
249}
250
251/* -------------- Space-Conversion API -------------- */
252
254 bPoseChannel *pchan,
255 bConstraintOb *cob,
256 float mat[4][4],
257 short from,
258 short to,
259 const bool keep_scale)
260{
261 float diff_mat[4][4];
262 float imat[4][4];
263
264 /* Prevent crashes in these unlikely events. */
265 if (ob == nullptr || mat == nullptr) {
266 return;
267 }
268 /* optimize trick - check if need to do anything */
269 if (from == to) {
270 return;
271 }
272
273 /* are we dealing with pose-channels or objects */
274 if (pchan) {
275 /* pose channels */
276 switch (from) {
277 case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */
278 {
279 if (to == CONSTRAINT_SPACE_CUSTOM) {
280 /* World to custom. */
281 BLI_assert(cob);
283 mul_m4_m4m4(mat, imat, mat);
284 }
285 else {
286 /* World to pose. */
287 invert_m4_m4(imat, ob->object_to_world().ptr());
288 mul_m4_m4m4(mat, imat, mat);
289
290 /* Use pose-space as stepping stone for other spaces. */
291 if (ELEM(to,
295 {
296 /* Call self with slightly different values. */
298 ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
299 }
300 }
301 break;
302 }
303 case CONSTRAINT_SPACE_POSE: /* ---------- FROM POSESPACE ---------- */
304 {
305 /* pose to local */
306 if (to == CONSTRAINT_SPACE_LOCAL) {
307 if (pchan->bone) {
308 BKE_armature_mat_pose_to_bone(pchan, mat, mat);
309 }
310 }
311 /* pose to owner local */
312 else if (to == CONSTRAINT_SPACE_OWNLOCAL) {
313 /* pose to local */
314 if (pchan->bone) {
315 BKE_armature_mat_pose_to_bone(pchan, mat, mat);
316 }
317
318 /* local to owner local (recursive) */
320 ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale);
321 }
322 /* pose to local with parent */
323 else if (to == CONSTRAINT_SPACE_PARLOCAL) {
324 if (pchan->bone) {
325 invert_m4_m4(imat, pchan->bone->arm_mat);
326 mul_m4_m4m4(mat, imat, mat);
327 }
328 }
329 else {
330 /* Pose to world. */
331 mul_m4_m4m4(mat, ob->object_to_world().ptr(), mat);
332 /* Use world-space as stepping stone for other spaces. */
333 if (to != CONSTRAINT_SPACE_WORLD) {
334 /* Call self with slightly different values. */
336 ob, pchan, cob, mat, CONSTRAINT_SPACE_WORLD, to, keep_scale);
337 }
338 }
339 break;
340 }
341 case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */
342 {
343 /* local to owner local */
344 if (to == CONSTRAINT_SPACE_OWNLOCAL) {
345 if (pchan->bone) {
346 copy_m4_m4(diff_mat, pchan->bone->arm_mat);
347
348 if (cob && cob->pchan && cob->pchan->bone) {
349 invert_m4_m4(imat, cob->pchan->bone->arm_mat);
350 mul_m4_m4m4(diff_mat, imat, diff_mat);
351 }
352
353 zero_v3(diff_mat[3]);
354 invert_m4_m4(imat, diff_mat);
355 mul_m4_series(mat, diff_mat, mat, imat);
356 }
357 }
358 /* local to pose - do inverse procedure that was done for pose to local */
359 else {
360 if (pchan->bone) {
361 /* We need the:
362 * `posespace_matrix = local_matrix + (parent_posespace_matrix + restpos)`. */
363 BKE_armature_mat_bone_to_pose(pchan, mat, mat);
364 }
365
366 /* use pose-space as stepping stone for other spaces */
368 {
369 /* call self with slightly different values */
371 ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
372 }
373 }
374 break;
375 }
376 case CONSTRAINT_SPACE_OWNLOCAL: { /* -------------- FROM OWNER LOCAL ---------- */
377 /* owner local to local */
378 if (pchan->bone) {
379 copy_m4_m4(diff_mat, pchan->bone->arm_mat);
380
381 if (cob && cob->pchan && cob->pchan->bone) {
382 invert_m4_m4(imat, cob->pchan->bone->arm_mat);
383 mul_m4_m4m4(diff_mat, imat, diff_mat);
384 }
385
386 zero_v3(diff_mat[3]);
387 invert_m4_m4(imat, diff_mat);
388 mul_m4_series(mat, imat, mat, diff_mat);
389 }
390
391 if (to != CONSTRAINT_SPACE_LOCAL) {
392 /* call self with slightly different values */
394 ob, pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, to, keep_scale);
395 }
396 break;
397 }
398 case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */
399 {
400 /* local + parent to pose */
401 if (pchan->bone) {
402 mul_m4_m4m4(mat, pchan->bone->arm_mat, mat);
403 }
404
405 /* use pose-space as stepping stone for other spaces */
406 if (ELEM(to,
411 {
412 /* call self with slightly different values */
414 ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale);
415 }
416 break;
417 }
418 case CONSTRAINT_SPACE_CUSTOM: /* -------------- FROM CUSTOM SPACE ---------- */
419 {
420 /* Custom to world. */
421 BLI_assert(cob);
422 mul_m4_m4m4(mat, cob->space_obj_world_matrix, mat);
423
424 /* Use world-space as stepping stone for other spaces. */
425 if (to != CONSTRAINT_SPACE_WORLD) {
426 /* Call self with slightly different values. */
428 ob, pchan, cob, mat, CONSTRAINT_SPACE_WORLD, to, keep_scale);
429 }
430 break;
431 }
432 }
433 }
434 else {
435 /* objects */
436 if (from == CONSTRAINT_SPACE_WORLD) {
437 if (to == CONSTRAINT_SPACE_LOCAL) {
438 /* Check if object has a parent. */
439 if (ob->parent) {
440 /* 'subtract' parent's effects from owner. */
441 mul_m4_m4m4(diff_mat, ob->parent->object_to_world().ptr(), ob->parentinv);
442 invert_m4_m4_safe(imat, diff_mat);
443 mul_m4_m4m4(mat, imat, mat);
444 }
445 else {
446 /* Local space in this case will have to be defined as local to the owner's
447 * transform-property-rotated axes. So subtract this rotation component.
448 */
449 /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same
450 * as global space! Think what we want actually here is some kind of 'Final Space', i.e
451 * . once transformations are applied - users are often confused about this too,
452 * this is not consistent with bones
453 * local space either... Meh :|
454 * --mont29
455 */
456 BKE_object_to_mat4(ob, diff_mat);
457 if (!keep_scale) {
458 normalize_m4(diff_mat);
459 }
460 zero_v3(diff_mat[3]);
461
462 invert_m4_m4_safe(imat, diff_mat);
463 mul_m4_m4m4(mat, imat, mat);
464 }
465 }
466 else if (to == CONSTRAINT_SPACE_CUSTOM) {
467 /* 'subtract' custom objects's effects from owner. */
468 BLI_assert(cob);
470 mul_m4_m4m4(mat, imat, mat);
471 }
472 }
473 else if (from == CONSTRAINT_SPACE_LOCAL) {
474 /* check that object has a parent - otherwise this won't work */
475 if (ob->parent) {
476 /* 'add' parent's effect back to owner */
477 mul_m4_m4m4(diff_mat, ob->parent->object_to_world().ptr(), ob->parentinv);
478 mul_m4_m4m4(mat, diff_mat, mat);
479 }
480 else {
481 /* Local space in this case will have to be defined as local to the owner's
482 * transform-property-rotated axes. So add back this rotation component.
483 */
484 /* XXX See comment above for world->local case... */
485 BKE_object_to_mat4(ob, diff_mat);
486 if (!keep_scale) {
487 normalize_m4(diff_mat);
488 }
489 zero_v3(diff_mat[3]);
490
491 mul_m4_m4m4(mat, diff_mat, mat);
492 }
493 if (to == CONSTRAINT_SPACE_CUSTOM) {
494 /* 'subtract' objects's effects from owner. */
495 BLI_assert(cob);
497 mul_m4_m4m4(mat, imat, mat);
498 }
499 }
500 else if (from == CONSTRAINT_SPACE_CUSTOM) {
501 /* Custom to world. */
502 BLI_assert(cob);
503 mul_m4_m4m4(mat, cob->space_obj_world_matrix, mat);
504
505 /* Use world-space as stepping stone for other spaces. */
506 if (to != CONSTRAINT_SPACE_WORLD) {
507 /* Call self with slightly different values. */
509 ob, pchan, cob, mat, CONSTRAINT_SPACE_WORLD, to, keep_scale);
510 }
511 }
512 }
513}
514
515/* ------------ General Target Matrix Tools ---------- */
516
517/* function that sets the given matrix based on given vertex group in mesh */
518static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[4][4])
519{
520 /* when not in EditMode, use the 'final' evaluated mesh, depsgraph
521 * ensures we build with CD_MDEFORMVERT layer
522 */
523 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
525 float plane[3];
526 float imat[3][3], tmat[3][3];
527 const int defgroup = BKE_object_defgroup_name_index(ob, substring);
528
529 /* initialize target matrix using target matrix */
530 copy_m4_m4(mat, ob->object_to_world().ptr());
531
532 /* get index of vertex group */
533 if (defgroup == -1) {
534 return;
535 }
536
537 float vec[3] = {0.0f, 0.0f, 0.0f};
538 float normal[3] = {0.0f, 0.0f, 0.0f};
539 float weightsum = 0.0f;
540 if (em) {
542 BMVert *v;
543 BMIter iter;
544
545 BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
546 MDeformVert *dv = static_cast<MDeformVert *>(
548 MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
549
550 if (dw && dw->weight > 0.0f) {
551 madd_v3_v3fl(vec, v->co, dw->weight);
552 madd_v3_v3fl(normal, v->no, dw->weight);
553 weightsum += dw->weight;
554 }
555 }
556 }
557 }
558 else if (mesh_eval) {
559 const blender::Span<blender::float3> positions = mesh_eval->vert_positions();
560 const blender::Span<blender::float3> vert_normals = mesh_eval->vert_normals();
561 const MDeformVert *dvert = static_cast<const MDeformVert *>(
563
564 /* check that dvert is a valid pointers (just in case) */
565 if (dvert) {
566
567 /* get the average of all verts with that are in the vertex-group */
568 for (const int i : positions.index_range()) {
569 const MDeformVert *dv = &dvert[i];
570 const MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
571
572 if (dw && dw->weight > 0.0f) {
573 madd_v3_v3fl(vec, positions[i], dw->weight);
574 madd_v3_v3fl(normal, vert_normals[i], dw->weight);
575 weightsum += dw->weight;
576 }
577 }
578 }
579 }
580 else {
581 /* No valid edit or evaluated mesh, just abort. */
582 return;
583 }
584
585 /* calculate averages of normal and coordinates */
586 if (weightsum > 0) {
587 mul_v3_fl(vec, 1.0f / weightsum);
588 mul_v3_fl(normal, 1.0f / weightsum);
589 }
590
591 /* derive the rotation from the average normal:
592 * - code taken from transform_gizmo.c,
593 * calc_gizmo_stats, V3D_ORIENT_NORMAL case */
594
595 /* We need the transpose of the inverse for a normal. */
596 copy_m3_m4(imat, ob->object_to_world().ptr());
597
598 invert_m3_m3(tmat, imat);
599 transpose_m3(tmat);
600 mul_m3_v3(tmat, normal);
601
602 normalize_v3(normal);
603 copy_v3_v3(plane, tmat[1]);
604
605 cross_v3_v3v3(mat[0], normal, plane);
606 if (len_squared_v3(mat[0]) < square_f(1e-3f)) {
607 copy_v3_v3(plane, tmat[0]);
608 cross_v3_v3v3(mat[0], normal, plane);
609 }
610
611 copy_v3_v3(mat[2], normal);
612 cross_v3_v3v3(mat[1], mat[2], mat[0]);
613
614 normalize_m4(mat);
615
616 /* apply the average coordinate as the new location */
617 mul_v3_m4v3(mat[3], ob->object_to_world().ptr(), vec);
618}
619
620/* function that sets the given matrix based on given vertex group in lattice */
621static void contarget_get_lattice_mat(Object *ob, const char *substring, float mat[4][4])
622{
623 Lattice *lt = (Lattice *)ob->data;
624
625 DispList *dl = ob->runtime->curve_cache ?
626 BKE_displist_find(&ob->runtime->curve_cache->disp, DL_VERTS) :
627 nullptr;
628 const float *co = dl ? dl->verts : nullptr;
629 BPoint *bp = lt->def;
630
631 MDeformVert *dv = lt->dvert;
632 int tot_verts = lt->pntsu * lt->pntsv * lt->pntsw;
633 float vec[3] = {0.0f, 0.0f, 0.0f}, tvec[3];
634 int grouped = 0;
635 int i, n;
636 const int defgroup = BKE_object_defgroup_name_index(ob, substring);
637
638 /* initialize target matrix using target matrix */
639 copy_m4_m4(mat, ob->object_to_world().ptr());
640
641 /* get index of vertex group */
642 if (defgroup == -1) {
643 return;
644 }
645 if (dv == nullptr) {
646 return;
647 }
648
649 /* 1. Loop through control-points checking if in nominated vertex-group.
650 * 2. If it is, add it to vec to find the average point.
651 */
652 for (i = 0; i < tot_verts; i++, dv++) {
653 for (n = 0; n < dv->totweight; n++) {
654 MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
655 if (dw && dw->weight > 0.0f) {
656 /* copy coordinates of point to temporary vector, then add to find average */
657 memcpy(tvec, co ? co : bp->vec, sizeof(float[3]));
658
659 add_v3_v3(vec, tvec);
660 grouped++;
661 }
662 }
663
664 /* advance pointer to coordinate data */
665 if (co) {
666 co += 3;
667 }
668 else {
669 bp++;
670 }
671 }
672
673 /* find average location, then multiply by ob->object_to_world().ptr() to find world-space
674 * location */
675 if (grouped) {
676 mul_v3_fl(vec, 1.0f / grouped);
677 }
678 mul_v3_m4v3(tvec, ob->object_to_world().ptr(), vec);
679
680 /* copy new location to matrix */
681 copy_v3_v3(mat[3], tvec);
682}
683
684/* generic function to get the appropriate matrix for most target cases */
685/* The cases where the target can be object data have not been implemented */
687 const char *substring,
688 bConstraintOb *cob,
689 float mat[4][4],
690 short from,
691 short to,
692 short flag,
693 float headtail)
694{
695 /* Case OBJECT */
696 if (substring[0] == '\0') {
697 copy_m4_m4(mat, ob->object_to_world().ptr());
698 BKE_constraint_mat_convertspace(ob, nullptr, cob, mat, from, to, false);
699 }
700 /* Case VERTEXGROUP */
701 /* Current method just takes the average location of all the points in the
702 * VertexGroup, and uses that as the location value of the targets. Where
703 * possible, the orientation will also be calculated, by calculating an
704 * 'average' vertex normal, and deriving the rotation from that.
705 *
706 * NOTE: EditMode is not currently supported, and will most likely remain that
707 * way as constraints can only really affect things on object/bone level.
708 */
709 else if (ob->type == OB_MESH) {
710 contarget_get_mesh_mat(ob, substring, mat);
711 BKE_constraint_mat_convertspace(ob, nullptr, cob, mat, from, to, false);
712 }
713 else if (ob->type == OB_LATTICE) {
714 contarget_get_lattice_mat(ob, substring, mat);
715 BKE_constraint_mat_convertspace(ob, nullptr, cob, mat, from, to, false);
716 }
717 /* Case BONE */
718 else {
719 bPoseChannel *pchan;
720
721 pchan = BKE_pose_channel_find_name(ob->pose, substring);
722 if (pchan) {
723 /* Multiply the PoseSpace accumulation/final matrix for this
724 * PoseChannel by the Armature Object's Matrix to get a world-space matrix.
725 */
726 bool is_bbone = (pchan->bone) && (pchan->bone->segments > 1) &&
728 bool full_bbone = (flag & CONSTRAINT_BBONE_SHAPE_FULL) != 0;
729
730 if (headtail < 0.000001f && !(is_bbone && full_bbone)) {
731 /* skip length interpolation if set to head */
732 mul_m4_m4m4(mat, ob->object_to_world().ptr(), pchan->pose_mat);
733 }
734 else if (is_bbone && pchan->bone->segments == pchan->runtime.bbone_segments) {
735 /* use point along bbone */
736 Mat4 *bbone = pchan->runtime.bbone_pose_mats;
737 float tempmat[4][4];
738 float loc[3], fac;
739 int index;
740
741 /* figure out which segment(s) the headtail value falls in */
742 BKE_pchan_bbone_deform_clamp_segment_index(pchan, headtail, &index, &fac);
743
744 /* apply full transformation of the segment if requested */
745 if (full_bbone) {
746 interp_m4_m4m4(tempmat, bbone[index].mat, bbone[index + 1].mat, fac);
747
748 mul_m4_m4m4(tempmat, pchan->pose_mat, tempmat);
749 }
750 /* only interpolate location */
751 else {
752 interp_v3_v3v3(loc, bbone[index].mat[3], bbone[index + 1].mat[3], fac);
753
754 copy_m4_m4(tempmat, pchan->pose_mat);
755 mul_v3_m4v3(tempmat[3], pchan->pose_mat, loc);
756 }
757
758 mul_m4_m4m4(mat, ob->object_to_world().ptr(), tempmat);
759 }
760 else {
761 float tempmat[4][4], loc[3];
762
763 /* interpolate along length of bone */
764 interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail);
765
766 /* use interpolated distance for subtarget */
767 copy_m4_m4(tempmat, pchan->pose_mat);
768 copy_v3_v3(tempmat[3], loc);
769
770 mul_m4_m4m4(mat, ob->object_to_world().ptr(), tempmat);
771 }
772 }
773 else {
774 copy_m4_m4(mat, ob->object_to_world().ptr());
775 }
776
777 /* convert matrix space as required */
778 BKE_constraint_mat_convertspace(ob, pchan, cob, mat, from, to, false);
779 }
780}
781
782/* ************************* Specific Constraints ***************************** */
783/* Each constraint defines a set of functions, which will be called at the appropriate
784 * times. In addition to this, each constraint should have a type-info struct, where
785 * its functions are attached for use.
786 */
787
788/* Template for type-info data:
789 * - make a copy of this when creating new constraints, and just change the functions
790 * pointed to as necessary
791 * - although the naming of functions doesn't matter, it would help for code
792 * readability, to follow the same naming convention as is presented here
793 * - any functions that a constraint doesn't need to define, don't define
794 * for such cases, just use nullptr
795 * - these should be defined after all the functions have been defined, so that
796 * forward-definitions/prototypes don't need to be used!
797 * - keep this copy #if-def'd so that future constraints can get based off this
798 */
799#if 0
800static bConstraintTypeInfo CTI_CONSTRNAME = {
801 /*type*/ CONSTRAINT_TYPE_CONSTRNAME,
802 /*size*/ sizeof(bConstrNameConstraint),
803 /*name*/ "ConstrName",
804 /*struct_name*/ "bConstrNameConstraint",
805 /*free_data*/ constrname_free,
806 /*id_looper*/ constrname_id_looper,
807 /*copy_data*/ constrname_copy,
808 /*new_data*/ constrname_new_data,
809 /*get_constraint_targets*/ constrname_get_tars,
810 /*flush_constraint_targets*/ constrname_flush_tars,
811 /*get_target_matrix*/ constrname_get_tarmat,
812 /*evaluate_constraint*/ constrname_evaluate,
813};
814#endif
815
816/* This function should be used for the get_target_matrix member of all
817 * constraints that are not picky about what happens to their target matrix.
818 */
819static void default_get_tarmat(Depsgraph * /*depsgraph*/,
820 bConstraint *con,
821 bConstraintOb *cob,
823 float /*ctime*/)
824{
825 if (VALID_CONS_TARGET(ct)) {
827 ct->subtarget,
828 cob,
829 ct->matrix,
831 ct->space,
832 con->flag,
833 con->headtail);
834 }
835 else if (ct) {
836 unit_m4(ct->matrix);
837 }
838}
839
840/* This is a variant that extracts full transformation from B-Bone segments.
841 */
842static void default_get_tarmat_full_bbone(Depsgraph * /*depsgraph*/,
843 bConstraint *con,
844 bConstraintOb *cob,
846 float /*ctime*/)
847{
848 if (VALID_CONS_TARGET(ct)) {
850 ct->subtarget,
851 cob,
852 ct->matrix,
854 ct->space,
856 con->headtail);
857 }
858 else if (ct) {
859 unit_m4(ct->matrix);
860 }
861}
862
863/* This following macro should be used for all standard single-target *_get_tars functions
864 * to save typing and reduce maintenance woes.
865 * (Hopefully all compilers will be happy with the lines with just a space on them.
866 * Those are really just to help this code easier to read).
867 */
868/* TODO: cope with getting rotation order... */
869#define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \
870 { \
871 ct = static_cast<bConstraintTarget *>( \
872 MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget")); \
873\
874 ct->tar = datatar; \
875 STRNCPY(ct->subtarget, datasubtarget); \
876 ct->space = con->tarspace; \
877 ct->flag = CONSTRAINT_TAR_TEMP; \
878\
879 if (ct->tar) { \
880 if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) { \
881 bPoseChannel *pchan = BKE_pose_channel_find_name(ct->tar->pose, ct->subtarget); \
882 ct->type = CONSTRAINT_OBTYPE_BONE; \
883 ct->rotOrder = (pchan) ? (pchan->rotmode) : int(EULER_ORDER_DEFAULT); \
884 } \
885 else if (OB_TYPE_SUPPORT_VGROUP(ct->tar->type) && (ct->subtarget[0])) { \
886 ct->type = CONSTRAINT_OBTYPE_VERT; \
887 ct->rotOrder = EULER_ORDER_DEFAULT; \
888 } \
889 else { \
890 ct->type = CONSTRAINT_OBTYPE_OBJECT; \
891 ct->rotOrder = ct->tar->rotmode; \
892 } \
893 } \
894\
895 BLI_addtail(list, ct); \
896 } \
897 (void)0
898
899/* This following macro should be used for all standard single-target *_get_tars functions
900 * to save typing and reduce maintenance woes. It does not do the subtarget related operations
901 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
902 * really just to help this code easier to read)
903 */
904/* TODO: cope with getting rotation order... */
905#define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \
906 { \
907 ct = static_cast<bConstraintTarget *>( \
908 MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget")); \
909\
910 ct->tar = datatar; \
911 ct->space = con->tarspace; \
912 ct->flag = CONSTRAINT_TAR_TEMP; \
913\
914 if (ct->tar) { \
915 ct->type = CONSTRAINT_OBTYPE_OBJECT; \
916 } \
917 BLI_addtail(list, ct); \
918 } \
919 (void)0
920
921/* This following macro should be used for all standard single-target *_flush_tars functions
922 * to save typing and reduce maintenance woes.
923 * NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed)
924 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
925 * really just to help this code easier to read)
926 */
927#define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, no_copy) \
928 { \
929 if (ct) { \
930 bConstraintTarget *ctn = ct->next; \
931 if (no_copy == 0) { \
932 datatar = ct->tar; \
933 STRNCPY(datasubtarget, ct->subtarget); \
934 con->tarspace = char(ct->space); \
935 } \
936\
937 BLI_freelinkN(list, ct); \
938 ct = ctn; \
939 } \
940 } \
941 (void)0
942
943/* This following macro should be used for all standard single-target *_flush_tars functions
944 * to save typing and reduce maintenance woes. It does not do the subtarget related operations.
945 * NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed)
946 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
947 * really just to help this code easier to read)
948 */
949#define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, no_copy) \
950 { \
951 if (ct) { \
952 bConstraintTarget *ctn = ct->next; \
953 if (no_copy == 0) { \
954 datatar = ct->tar; \
955 con->tarspace = char(ct->space); \
956 } \
957\
958 BLI_freelinkN(list, ct); \
959 ct = ctn; \
960 } \
961 } \
962 (void)0
963
968
969/* --------- ChildOf Constraint ------------ */
970
971static void childof_new_data(void *cdata)
972{
973 bChildOfConstraint *data = (bChildOfConstraint *)cdata;
974
978 unit_m4(data->invmat);
979}
980
981static void childof_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
982{
983 bChildOfConstraint *data = static_cast<bChildOfConstraint *>(con->data);
984
985 /* target only */
986 func(con, (ID **)&data->tar, false, userdata);
987}
988
989static int childof_get_tars(bConstraint *con, ListBase *list)
990{
991 if (con && list) {
992 bChildOfConstraint *data = static_cast<bChildOfConstraint *>(con->data);
994
995 /* standard target-getting macro for single-target constraints */
996 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
997
998 return 1;
999 }
1000
1001 return 0;
1002}
1003
1004static void childof_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
1005{
1006 if (con && list) {
1007 bChildOfConstraint *data = static_cast<bChildOfConstraint *>(con->data);
1008 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
1009
1010 /* the following macro is used for all standard single-target constraints */
1011 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
1012 }
1013}
1014
1015static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
1016{
1017 bChildOfConstraint *data = static_cast<bChildOfConstraint *>(con->data);
1018 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
1019
1020 /* Only evaluate if there is a target.
1021 *
1022 * NOTE: we're setting/unsetting the CONSTRAINT_SPACEONCE flag here because:
1023 *
1024 * 1. It's only used by the Child Of constraint anyway.
1025 * 2. It's only used to affect the steps taken immediately after this function
1026 * returns, and this way we ensure it's always set correctly for that.
1027 *
1028 * It was previously set in other places which resulted in bugs like #116567.
1029 * In the future we should ideally move to a different approach entirely. */
1030 if (!VALID_CONS_TARGET(ct)) {
1031 con->flag &= ~CONSTRAINT_SPACEONCE;
1032 return;
1033 }
1034 con->flag |= CONSTRAINT_SPACEONCE;
1035
1036 float parmat[4][4];
1037 float inverse_matrix[4][4];
1038 /* Simple matrix parenting. */
1039 if ((data->flag & CHILDOF_ALL) == CHILDOF_ALL) {
1040 copy_m4_m4(parmat, ct->matrix);
1041 copy_m4_m4(inverse_matrix, data->invmat);
1042 }
1043 /* Filter the parent matrix by channel. */
1044 else {
1045 float loc[3], eul[3], size[3];
1046 float loco[3], eulo[3], sizeo[3];
1047
1048 /* extract components of both matrices */
1049 copy_v3_v3(loc, ct->matrix[3]);
1050 mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
1051 mat4_to_size(size, ct->matrix);
1052
1053 copy_v3_v3(loco, data->invmat[3]);
1054 mat4_to_eulO(eulo, cob->rotOrder, data->invmat);
1055 mat4_to_size(sizeo, data->invmat);
1056
1057 /* Reset the locked channels to their no-op values. */
1058 if (!(data->flag & CHILDOF_LOCX)) {
1059 loc[0] = loco[0] = 0.0f;
1060 }
1061 if (!(data->flag & CHILDOF_LOCY)) {
1062 loc[1] = loco[1] = 0.0f;
1063 }
1064 if (!(data->flag & CHILDOF_LOCZ)) {
1065 loc[2] = loco[2] = 0.0f;
1066 }
1067 if (!(data->flag & CHILDOF_ROTX)) {
1068 eul[0] = eulo[0] = 0.0f;
1069 }
1070 if (!(data->flag & CHILDOF_ROTY)) {
1071 eul[1] = eulo[1] = 0.0f;
1072 }
1073 if (!(data->flag & CHILDOF_ROTZ)) {
1074 eul[2] = eulo[2] = 0.0f;
1075 }
1076 if (!(data->flag & CHILDOF_SIZEX)) {
1077 size[0] = sizeo[0] = 1.0f;
1078 }
1079 if (!(data->flag & CHILDOF_SIZEY)) {
1080 size[1] = sizeo[1] = 1.0f;
1081 }
1082 if (!(data->flag & CHILDOF_SIZEZ)) {
1083 size[2] = sizeo[2] = 1.0f;
1084 }
1085
1086 /* Construct the new matrices given the disabled channels. */
1087 loc_eulO_size_to_mat4(parmat, loc, eul, size, ct->rotOrder);
1088 loc_eulO_size_to_mat4(inverse_matrix, loco, eulo, sizeo, cob->rotOrder);
1089 }
1090
1091 /* If requested, compute the inverse matrix from the computed parent matrix. */
1092 if (data->flag & CHILDOF_SET_INVERSE) {
1093 invert_m4_m4(data->invmat, parmat);
1094 if (cob->pchan != nullptr) {
1095 mul_m4_series(data->invmat, data->invmat, cob->ob->object_to_world().ptr());
1096 }
1097
1098 copy_m4_m4(inverse_matrix, data->invmat);
1099
1100 data->flag &= ~CHILDOF_SET_INVERSE;
1101
1102 /* Write the computed matrix back to the master copy if in copy-on-eval evaluation. */
1104
1105 if (orig_con != nullptr) {
1106 bChildOfConstraint *orig_data = static_cast<bChildOfConstraint *>(orig_con->data);
1107
1108 copy_m4_m4(orig_data->invmat, data->invmat);
1109 orig_data->flag &= ~CHILDOF_SET_INVERSE;
1110 }
1111 }
1112
1113 /* Multiply together the target (parent) matrix, parent inverse,
1114 * and the owner transform matrix to get the effect of this constraint
1115 * (i.e. owner is 'parented' to parent). */
1116 float orig_cob_matrix[4][4];
1117 copy_m4_m4(orig_cob_matrix, cob->matrix);
1118 mul_m4_series(cob->matrix, parmat, inverse_matrix, orig_cob_matrix);
1119
1120 /* Without this, changes to scale and rotation can change location
1121 * of a parentless bone or a disconnected bone. Even though its set
1122 * to zero above. */
1123 if (!(data->flag & CHILDOF_LOCX)) {
1124 cob->matrix[3][0] = orig_cob_matrix[3][0];
1125 }
1126 if (!(data->flag & CHILDOF_LOCY)) {
1127 cob->matrix[3][1] = orig_cob_matrix[3][1];
1128 }
1129 if (!(data->flag & CHILDOF_LOCZ)) {
1130 cob->matrix[3][2] = orig_cob_matrix[3][2];
1131 }
1132}
1133
1134/* XXX NOTE: con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in `readfile.cc`.
1135 */
1137 /*type*/ CONSTRAINT_TYPE_CHILDOF,
1138 /*size*/ sizeof(bChildOfConstraint),
1139 /*name*/ N_("Child Of"),
1140 /*struct_name*/ "bChildOfConstraint",
1141 /*free_data*/ nullptr,
1142 /*id_looper*/ childof_id_looper,
1143 /*copy_data*/ nullptr,
1144 /*new_data*/ childof_new_data,
1145 /*get_constraint_targets*/ childof_get_tars,
1146 /*flush_constraint_targets*/ childof_flush_tars,
1147 /*get_target_matrix*/ default_get_tarmat,
1148 /*evaluate_constraint*/ childof_evaluate,
1149};
1150
1151/* -------- TrackTo Constraint ------- */
1152
1153static void trackto_new_data(void *cdata)
1154{
1155 bTrackToConstraint *data = (bTrackToConstraint *)cdata;
1156
1157 data->reserved1 = TRACK_nZ;
1158 data->reserved2 = UP_Y;
1159}
1160
1161static void trackto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
1162{
1163 bTrackToConstraint *data = static_cast<bTrackToConstraint *>(con->data);
1164
1165 /* target only */
1166 func(con, (ID **)&data->tar, false, userdata);
1167}
1168
1170{
1171 if (con && list) {
1172 bTrackToConstraint *data = static_cast<bTrackToConstraint *>(con->data);
1174
1175 /* standard target-getting macro for single-target constraints */
1176 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
1177
1178 return 1;
1179 }
1180
1181 return 0;
1182}
1183
1184static void trackto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
1185{
1186 if (con && list) {
1187 bTrackToConstraint *data = static_cast<bTrackToConstraint *>(con->data);
1188 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
1189
1190 /* the following macro is used for all standard single-target constraints */
1191 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
1192 }
1193}
1194
1195static int basis_cross(int n, int m)
1196{
1197 switch (n - m) {
1198 case 1:
1199 case -2:
1200 return 1;
1201
1202 case -1:
1203 case 2:
1204 return -1;
1205
1206 default:
1207 return 0;
1208 }
1209}
1210
1211static void vectomat(const float vec[3],
1212 const float target_up[3],
1213 short axis,
1214 short upflag,
1215 short flags,
1216 float m[3][3])
1217{
1218 float n[3];
1219 float u[3]; /* vector specifying the up axis */
1220 float proj[3];
1221 float right[3];
1222 float neg = -1;
1223 int right_index;
1224
1225 if (normalize_v3_v3(n, vec) == 0.0f) {
1226 n[0] = 0.0f;
1227 n[1] = 0.0f;
1228 n[2] = 1.0f;
1229 }
1230 if (axis > 2) {
1231 axis -= 3;
1232 }
1233 else {
1234 negate_v3(n);
1235 }
1236
1237 /* n specifies the transformation of the track axis */
1238 if (flags & TARGET_Z_UP) {
1239 /* target Z axis is the global up axis */
1240 copy_v3_v3(u, target_up);
1241 }
1242 else {
1243 /* world Z axis is the global up axis */
1244 u[0] = 0;
1245 u[1] = 0;
1246 u[2] = 1;
1247 }
1248
1249 /* NOTE: even though 'n' is normalized, don't use 'project_v3_v3v3_normalized' below
1250 * because precision issues cause a problem in near degenerate states, see: #53455. */
1251
1252 /* project the up vector onto the plane specified by n */
1253 project_v3_v3v3(proj, u, n); /* first u onto n... */
1254 sub_v3_v3v3(proj, u, proj); /* then onto the plane */
1255 /* proj specifies the transformation of the up axis */
1256
1257 if (normalize_v3(proj) == 0.0f) { /* degenerate projection */
1258 proj[0] = 0.0f;
1259 proj[1] = 1.0f;
1260 proj[2] = 0.0f;
1261 }
1262
1263 /* Normalized cross product of n and proj specifies transformation of the right axis */
1264 cross_v3_v3v3(right, proj, n);
1265 normalize_v3(right);
1266
1267 if (axis != upflag) {
1268 right_index = 3 - axis - upflag;
1269 neg = float(basis_cross(axis, upflag));
1270
1271 /* account for up direction, track direction */
1272 m[right_index][0] = neg * right[0];
1273 m[right_index][1] = neg * right[1];
1274 m[right_index][2] = neg * right[2];
1275
1276 copy_v3_v3(m[upflag], proj);
1277
1278 copy_v3_v3(m[axis], n);
1279 }
1280 /* identity matrix - don't do anything if the two axes are the same */
1281 else {
1282 unit_m3(m);
1283 }
1284}
1285
1286static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
1287{
1288 bTrackToConstraint *data = static_cast<bTrackToConstraint *>(con->data);
1289 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
1290
1291 if (VALID_CONS_TARGET(ct)) {
1292 float size[3], vec[3];
1293 float totmat[3][3];
1294
1295 /* Get size property, since ob->scale is only the object's own relative size,
1296 * not its global one. */
1297 mat4_to_size(size, cob->matrix);
1298
1299 /* Clear the object's rotation */
1300 cob->matrix[0][0] = size[0];
1301 cob->matrix[0][1] = 0;
1302 cob->matrix[0][2] = 0;
1303 cob->matrix[1][0] = 0;
1304 cob->matrix[1][1] = size[1];
1305 cob->matrix[1][2] = 0;
1306 cob->matrix[2][0] = 0;
1307 cob->matrix[2][1] = 0;
1308 cob->matrix[2][2] = size[2];
1309
1310 /* NOTE(@joshualung): `targetmat[2]` instead of `ownermat[2]` is passed to #vectomat
1311 * for backwards compatibility it seems. */
1312 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
1313 vectomat(vec,
1314 ct->matrix[2],
1315 std::clamp<short>(data->reserved1, 0, 5),
1316 std::clamp<short>(data->reserved2, 0, 2),
1317 data->flags,
1318 totmat);
1319
1320 mul_m4_m3m4(cob->matrix, totmat, cob->matrix);
1321 }
1322}
1323
1325 /*type*/ CONSTRAINT_TYPE_TRACKTO,
1326 /*size*/ sizeof(bTrackToConstraint),
1327 /*name*/ N_("Track To"),
1328 /*struct_name*/ "bTrackToConstraint",
1329 /*free_data*/ nullptr,
1330 /*id_looper*/ trackto_id_looper,
1331 /*copy_data*/ nullptr,
1332 /*new_data*/ trackto_new_data,
1333 /*get_constraint_targets*/ trackto_get_tars,
1334 /*flush_constraint_targets*/ trackto_flush_tars,
1335 /*get_target_matrix*/ default_get_tarmat,
1336 /*evaluate_constraint*/ trackto_evaluate,
1337};
1338
1339/* --------- Inverse-Kinematics --------- */
1340
1341static void kinematic_new_data(void *cdata)
1342{
1344
1345 data->weight = 1.0f;
1346 data->orientweight = 1.0f;
1347 data->iterations = 500;
1348 data->dist = 1.0f;
1350}
1351
1352static void kinematic_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
1353{
1354 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
1355
1356 /* chain target */
1357 func(con, (ID **)&data->tar, false, userdata);
1358
1359 /* poletarget */
1360 func(con, (ID **)&data->poletar, false, userdata);
1361}
1362
1364{
1365 if (con && list) {
1366 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
1368
1369 /* standard target-getting macro for single-target constraints is used twice here */
1370 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
1371 SINGLETARGET_GET_TARS(con, data->poletar, data->polesubtarget, ct, list);
1372
1373 return 2;
1374 }
1375
1376 return 0;
1377}
1378
1379static void kinematic_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
1380{
1381 if (con && list) {
1382 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
1383 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
1384
1385 /* the following macro is used for all standard single-target constraints */
1386 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
1387 SINGLETARGET_FLUSH_TARS(con, data->poletar, data->polesubtarget, ct, list, no_copy);
1388 }
1389}
1390
1391static void kinematic_get_tarmat(Depsgraph * /*depsgraph*/,
1392 bConstraint *con,
1393 bConstraintOb *cob,
1395 float /*ctime*/)
1396{
1397 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
1398
1399 if (VALID_CONS_TARGET(ct)) {
1401 ct->subtarget,
1402 cob,
1403 ct->matrix,
1405 ct->space,
1406 con->flag,
1407 con->headtail);
1408 }
1409 else if (ct) {
1410 if (data->flag & CONSTRAINT_IK_AUTO) {
1411 Object *ob = cob->ob;
1412
1413 if (ob == nullptr) {
1414 unit_m4(ct->matrix);
1415 }
1416 else {
1417 float vec[3];
1418 /* move grabtarget into world space */
1419 mul_v3_m4v3(vec, ob->object_to_world().ptr(), data->grabtarget);
1420 copy_m4_m4(ct->matrix, ob->object_to_world().ptr());
1421 copy_v3_v3(ct->matrix[3], vec);
1422 }
1423 }
1424 else {
1425 unit_m4(ct->matrix);
1426 }
1427 }
1428}
1429
1432 /*size*/ sizeof(bKinematicConstraint),
1433 /*name*/ N_("IK"),
1434 /*struct_name*/ "bKinematicConstraint",
1435 /*free_data*/ nullptr,
1436 /*id_looper*/ kinematic_id_looper,
1437 /*copy_data*/ nullptr,
1438 /*new_data*/ kinematic_new_data,
1439 /*get_constraint_targets*/ kinematic_get_tars,
1440 /*flush_constraint_targets*/ kinematic_flush_tars,
1441 /*get_target_matrix*/ kinematic_get_tarmat,
1442 /*evaluate_constraint*/ nullptr,
1443};
1444
1445/* -------- Follow-Path Constraint ---------- */
1446
1447static void followpath_new_data(void *cdata)
1448{
1450
1451 data->trackflag = TRACK_Y;
1452 data->upflag = UP_Z;
1453 data->offset = 0;
1454 data->followflag = 0;
1455}
1456
1457static void followpath_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
1458{
1459 bFollowPathConstraint *data = static_cast<bFollowPathConstraint *>(con->data);
1460
1461 /* target only */
1462 func(con, (ID **)&data->tar, false, userdata);
1463}
1464
1466{
1467 if (con && list) {
1468 bFollowPathConstraint *data = static_cast<bFollowPathConstraint *>(con->data);
1470
1471 /* Standard target-getting macro for single-target constraints without sub-targets. */
1472 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list);
1473
1474 return 1;
1475 }
1476
1477 return 0;
1478}
1479
1480static void followpath_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
1481{
1482 if (con && list) {
1483 bFollowPathConstraint *data = static_cast<bFollowPathConstraint *>(con->data);
1484 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
1485
1486 /* the following macro is used for all standard single-target constraints */
1487 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, no_copy);
1488 }
1489}
1490
1491static void followpath_get_tarmat(Depsgraph * /*depsgraph*/,
1492 bConstraint *con,
1493 bConstraintOb * /*cob*/,
1495 float /*ctime*/)
1496{
1497 bFollowPathConstraint *data = static_cast<bFollowPathConstraint *>(con->data);
1498
1499 if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVES_LEGACY)) {
1500 Curve *cu = static_cast<Curve *>(ct->tar->data);
1501 float vec[4], radius;
1502 float curvetime;
1503
1504 unit_m4(ct->matrix);
1505
1506 /* NOTE: when creating constraints that follow path, the curve gets the CU_PATH set now,
1507 * currently for paths to work it needs to go through the bevlist/displist system (ton)
1508 */
1509
1510 if (ct->tar->runtime->curve_cache && ct->tar->runtime->curve_cache->anim_path_accum_length) {
1511 float quat[4];
1512 if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
1513 /* animated position along curve depending on time */
1514 curvetime = cu->ctime - data->offset;
1515
1516 /* ctime is now a proper var setting of Curve which gets set by Animato like any other var
1517 * that's animated, but this will only work if it actually is animated...
1518 *
1519 * we divide the curvetime calculated in the previous step by the length of the path,
1520 * to get a time factor. */
1521 curvetime /= cu->pathlen;
1522
1523 Nurb *nu = static_cast<Nurb *>(cu->nurb.first);
1524 if (!(nu && nu->flagu & CU_NURB_CYCLIC) && cu->flag & CU_PATH_CLAMP) {
1525 /* If curve is not cyclic, clamp to the begin/end points if the curve clamp option is on.
1526 */
1527 CLAMP(curvetime, 0.0f, 1.0f);
1528 }
1529 }
1530 else {
1531 /* fixed position along curve */
1532 curvetime = data->offset_fac;
1533 }
1534
1535 if (BKE_where_on_path(ct->tar,
1536 curvetime,
1537 vec,
1538 nullptr,
1539 (data->followflag & FOLLOWPATH_FOLLOW) ? quat : nullptr,
1540 &radius,
1541 nullptr))
1542 {
1543 float totmat[4][4];
1544 unit_m4(totmat);
1545
1546 if (data->followflag & FOLLOWPATH_FOLLOW) {
1547 quat_apply_track(quat,
1548 std::clamp<short>(data->trackflag, 0, 5),
1549 std::clamp<short>(data->upflag, 0, 2));
1550 quat_to_mat4(totmat, quat);
1551 }
1552
1553 if (data->followflag & FOLLOWPATH_RADIUS) {
1554 float tmat[4][4], rmat[4][4];
1555 scale_m4_fl(tmat, radius);
1556 mul_m4_m4m4(rmat, tmat, totmat);
1557 copy_m4_m4(totmat, rmat);
1558 }
1559
1560 copy_v3_v3(totmat[3], vec);
1561
1562 mul_m4_m4m4(ct->matrix, ct->tar->object_to_world().ptr(), totmat);
1563 }
1564 }
1565 }
1566 else if (ct) {
1567 unit_m4(ct->matrix);
1568 }
1569}
1570
1572{
1573 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
1574
1575 /* only evaluate if there is a target */
1576 if (VALID_CONS_TARGET(ct)) {
1577 float obmat[4][4];
1578 float size[3];
1579 bFollowPathConstraint *data = static_cast<bFollowPathConstraint *>(con->data);
1580
1581 /* get Object transform (loc/rot/size) to determine transformation from path */
1582 /* TODO: this used to be local at one point, but is probably more useful as-is */
1583 copy_m4_m4(obmat, cob->matrix);
1584
1585 /* get scaling of object before applying constraint */
1586 mat4_to_size(size, cob->matrix);
1587
1588 /* apply targetmat - containing location on path, and rotation */
1589 mul_m4_m4m4(cob->matrix, ct->matrix, obmat);
1590
1591 /* un-apply scaling caused by path */
1592 if ((data->followflag & FOLLOWPATH_RADIUS) == 0) {
1593 /* XXX(@ideasman42): Assume that scale correction means that radius
1594 * will have some scale error in it. */
1595 float obsize[3];
1596
1597 mat4_to_size(obsize, cob->matrix);
1598 if (obsize[0]) {
1599 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
1600 }
1601 if (obsize[1]) {
1602 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
1603 }
1604 if (obsize[2]) {
1605 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
1606 }
1607 }
1608 }
1609}
1610
1613 /*size*/ sizeof(bFollowPathConstraint),
1614 /*name*/ N_("Follow Path"),
1615 /*struct_name*/ "bFollowPathConstraint",
1616 /*free_data*/ nullptr,
1617 /*id_looper*/ followpath_id_looper,
1618 /*copy_data*/ nullptr,
1619 /*new_data*/ followpath_new_data,
1620 /*get_constraint_targets*/ followpath_get_tars,
1621 /*flush_constraint_targets*/ followpath_flush_tars,
1622 /*get_target_matrix*/ followpath_get_tarmat,
1623 /*evaluate_constraint*/ followpath_evaluate,
1624};
1625
1626/* --------- Limit Location --------- */
1627
1628static void loclimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
1629{
1630 bLocLimitConstraint *data = static_cast<bLocLimitConstraint *>(con->data);
1631
1632 if (data->flag & LIMIT_XMIN) {
1633 if (cob->matrix[3][0] < data->xmin) {
1634 cob->matrix[3][0] = data->xmin;
1635 }
1636 }
1637 if (data->flag & LIMIT_XMAX) {
1638 if (cob->matrix[3][0] > data->xmax) {
1639 cob->matrix[3][0] = data->xmax;
1640 }
1641 }
1642 if (data->flag & LIMIT_YMIN) {
1643 if (cob->matrix[3][1] < data->ymin) {
1644 cob->matrix[3][1] = data->ymin;
1645 }
1646 }
1647 if (data->flag & LIMIT_YMAX) {
1648 if (cob->matrix[3][1] > data->ymax) {
1649 cob->matrix[3][1] = data->ymax;
1650 }
1651 }
1652 if (data->flag & LIMIT_ZMIN) {
1653 if (cob->matrix[3][2] < data->zmin) {
1654 cob->matrix[3][2] = data->zmin;
1655 }
1656 }
1657 if (data->flag & LIMIT_ZMAX) {
1658 if (cob->matrix[3][2] > data->zmax) {
1659 cob->matrix[3][2] = data->zmax;
1660 }
1661 }
1662}
1663
1665 /*type*/ CONSTRAINT_TYPE_LOCLIMIT,
1666 /*size*/ sizeof(bLocLimitConstraint),
1667 /*name*/ N_("Limit Location"),
1668 /*struct_name*/ "bLocLimitConstraint",
1669 /*free_data*/ nullptr,
1670 /*id_looper*/ nullptr,
1671 /*copy_data*/ nullptr,
1672 /*new_data*/ nullptr,
1673 /*get_constraint_targets*/ nullptr,
1674 /*flush_constraint_targets*/ nullptr,
1675 /*get_target_matrix*/ nullptr,
1676 /*evaluate_constraint*/ loclimit_evaluate,
1677};
1678
1679/* -------- Limit Rotation --------- */
1680
1684static inline float wrap_rad_angle(const float angle)
1685{
1686 const float b = angle * (0.5 / M_PI) + 0.5;
1687 return ((b - std::floor(b)) - 0.5) * (2.0 * M_PI);
1688}
1689
1700static float clamp_angle(const float angle, const float min, const float max)
1701{
1702 /* If the allowed range exceeds 360 degrees no clamping can occur. */
1703 if ((max - min) >= (2 * M_PI)) {
1704 return angle;
1705 }
1706
1707 /* Invalid case, just return min. */
1708 if (max <= min) {
1709 return min;
1710 }
1711
1712 /* Move min and max into a space where `angle == 0.0`, and wrap them to
1713 * [-PI, +PI] in that space. This simplifies the cases below, as we can
1714 * just use 0.0 in place of `angle` and know that everything is in
1715 * [-PI, +PI]. */
1716 const float min_wrapped = wrap_rad_angle(min - angle);
1717 const float max_wrapped = wrap_rad_angle(max - angle);
1718
1719 /* If the range defined by `min`/`max` doesn't contain the boundary at
1720 * PI/-PI. This is the simple case, because it means we can do a simple
1721 * clamp. */
1722 if (min_wrapped < max_wrapped) {
1723 return angle + std::clamp(0.0f, min_wrapped, max_wrapped);
1724 }
1725
1726 /* At this point we know that `min_wrapped` >= `max_wrapped`, meaning the boundary is crossed.
1727 * With that we know that no clamping is needed in the following case. */
1728 if (max_wrapped >= 0.0 || min_wrapped <= 0.0) {
1729 return angle;
1730 }
1731
1732 /* If zero is outside of the range, we clamp to the closest of `min_wrapped` or `max_wrapped`. */
1733 if (std::fabs(max_wrapped) < std::fabs(min_wrapped)) {
1734 return angle + max_wrapped;
1735 }
1736 return angle + min_wrapped;
1737}
1738
1739static void rotlimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
1740{
1741 bRotLimitConstraint *data = static_cast<bRotLimitConstraint *>(con->data);
1742 float loc[3];
1743 float eul[3];
1744 float size[3];
1745
1746 /* This constraint is based on euler rotation math, which doesn't work well with shear.
1747 * The Y axis is chosen as the main one because constraints are most commonly used on bones.
1748 * This also allows using the constraint to simply remove shear. */
1749 orthogonalize_m4_stable(cob->matrix, 1, false);
1750
1751 /* Only do the complex processing if some limits are actually enabled. */
1752 if (!(data->flag & (LIMIT_XROT | LIMIT_YROT | LIMIT_ZROT))) {
1753 return;
1754 }
1755
1756 /* Select the Euler rotation order, defaulting to the owner value. */
1757 short rot_order = cob->rotOrder;
1758
1759 if (data->euler_order != CONSTRAINT_EULER_AUTO) {
1760 rot_order = data->euler_order;
1761 }
1762
1763 /* Decompose the matrix using the specified order. */
1764 copy_v3_v3(loc, cob->matrix[3]);
1765 mat4_to_size(size, cob->matrix);
1766
1767 mat4_to_eulO(eul, rot_order, cob->matrix);
1768
1769 /* Limit the euler values. */
1770 if (data->flag & LIMIT_ROT_LEGACY_BEHAVIOR) {
1771 /* The legacy behavior, which just does a naive clamping of the angles as
1772 * simple numbers. Since the input angles are always in the range [-180,
1773 * 180] degrees due to being derived from matrix decomposition, this naive
1774 * approach causes problems when rotations cross 180 degrees. Specifically,
1775 * it results in unpredictable and unwanted rotation flips of the
1776 * constrained objects/bones, especially when the constraint isn't in local
1777 * space.
1778 *
1779 * The correct thing to do is a more sophisticated form of clamping that
1780 * treats the angles as existing on a continuous loop, which is what the
1781 * non-legacy behavior further below does. However, for backwards
1782 * compatibility we are preserving this old behavior behind an option.
1783 *
1784 * See issues #117927 and #123105 for additional background. */
1785 if (data->flag & LIMIT_XROT) {
1786 eul[0] = clamp_f(eul[0], data->xmin, data->xmax);
1787 }
1788 if (data->flag & LIMIT_YROT) {
1789 eul[1] = clamp_f(eul[1], data->ymin, data->ymax);
1790 }
1791 if (data->flag & LIMIT_ZROT) {
1792 eul[2] = clamp_f(eul[2], data->zmin, data->zmax);
1793 }
1794 }
1795 else {
1796 /* The correct, non-legacy behavior. */
1797 if (data->flag & LIMIT_XROT) {
1798 eul[0] = clamp_angle(eul[0], data->xmin, data->xmax);
1799 }
1800 if (data->flag & LIMIT_YROT) {
1801 eul[1] = clamp_angle(eul[1], data->ymin, data->ymax);
1802 }
1803 if (data->flag & LIMIT_ZROT) {
1804 eul[2] = clamp_angle(eul[2], data->zmin, data->zmax);
1805 }
1806 }
1807
1808 loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
1809}
1810
1812 /*type*/ CONSTRAINT_TYPE_ROTLIMIT,
1813 /*size*/ sizeof(bRotLimitConstraint),
1814 /*name*/ N_("Limit Rotation"),
1815 /*struct_name*/ "bRotLimitConstraint",
1816 /*free_data*/ nullptr,
1817 /*id_looper*/ nullptr,
1818 /*copy_data*/ nullptr,
1819 /*new_data*/ nullptr,
1820 /*get_constraint_targets*/ nullptr,
1821 /*flush_constraint_targets*/ nullptr,
1822 /*get_target_matrix*/ nullptr,
1823 /*evaluate_constraint*/ rotlimit_evaluate,
1824};
1825
1826/* --------- Limit Scale --------- */
1827
1828static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
1829{
1830 bSizeLimitConstraint *data = static_cast<bSizeLimitConstraint *>(con->data);
1831 float obsize[3], size[3];
1832
1833 mat4_to_size(size, cob->matrix);
1834
1835 copy_v3_v3(obsize, size);
1836
1837 if (data->flag & LIMIT_XMIN) {
1838 if (size[0] < data->xmin) {
1839 size[0] = data->xmin;
1840 }
1841 }
1842 if (data->flag & LIMIT_XMAX) {
1843 if (size[0] > data->xmax) {
1844 size[0] = data->xmax;
1845 }
1846 }
1847 if (data->flag & LIMIT_YMIN) {
1848 if (size[1] < data->ymin) {
1849 size[1] = data->ymin;
1850 }
1851 }
1852 if (data->flag & LIMIT_YMAX) {
1853 if (size[1] > data->ymax) {
1854 size[1] = data->ymax;
1855 }
1856 }
1857 if (data->flag & LIMIT_ZMIN) {
1858 if (size[2] < data->zmin) {
1859 size[2] = data->zmin;
1860 }
1861 }
1862 if (data->flag & LIMIT_ZMAX) {
1863 if (size[2] > data->zmax) {
1864 size[2] = data->zmax;
1865 }
1866 }
1867
1868 if (obsize[0]) {
1869 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
1870 }
1871 if (obsize[1]) {
1872 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
1873 }
1874 if (obsize[2]) {
1875 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
1876 }
1877}
1878
1881 /*size*/ sizeof(bSizeLimitConstraint),
1882 /*name*/ N_("Limit Scale"),
1883 /*struct_name*/ "bSizeLimitConstraint",
1884 /*free_data*/ nullptr,
1885 /*id_looper*/ nullptr,
1886 /*copy_data*/ nullptr,
1887 /*new_data*/ nullptr,
1888 /*get_constraint_targets*/ nullptr,
1889 /*flush_constraint_targets*/ nullptr,
1890 /*get_target_matrix*/ nullptr,
1891 /*evaluate_constraint*/ sizelimit_evaluate,
1892};
1893
1894/* ----------- Copy Location ------------- */
1895
1896static void loclike_new_data(void *cdata)
1897{
1899
1900 data->flag = LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z;
1901}
1902
1903static void loclike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
1904{
1905 bLocateLikeConstraint *data = static_cast<bLocateLikeConstraint *>(con->data);
1906
1907 /* target only */
1908 func(con, (ID **)&data->tar, false, userdata);
1909}
1910
1912{
1913 if (con && list) {
1914 bLocateLikeConstraint *data = static_cast<bLocateLikeConstraint *>(con->data);
1916
1917 /* standard target-getting macro for single-target constraints */
1918 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
1919
1920 return 1;
1921 }
1922
1923 return 0;
1924}
1925
1926static void loclike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
1927{
1928 if (con && list) {
1929 bLocateLikeConstraint *data = static_cast<bLocateLikeConstraint *>(con->data);
1930 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
1931
1932 /* the following macro is used for all standard single-target constraints */
1933 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
1934 }
1935}
1936
1937static void loclike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
1938{
1939 bLocateLikeConstraint *data = static_cast<bLocateLikeConstraint *>(con->data);
1940 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
1941
1942 if (VALID_CONS_TARGET(ct)) {
1943 float offset[3] = {0.0f, 0.0f, 0.0f};
1944
1945 if (data->flag & LOCLIKE_OFFSET) {
1946 copy_v3_v3(offset, cob->matrix[3]);
1947 }
1948
1949 if (data->flag & LOCLIKE_X) {
1950 cob->matrix[3][0] = ct->matrix[3][0];
1951
1952 if (data->flag & LOCLIKE_X_INVERT) {
1953 cob->matrix[3][0] *= -1;
1954 }
1955 cob->matrix[3][0] += offset[0];
1956 }
1957 if (data->flag & LOCLIKE_Y) {
1958 cob->matrix[3][1] = ct->matrix[3][1];
1959
1960 if (data->flag & LOCLIKE_Y_INVERT) {
1961 cob->matrix[3][1] *= -1;
1962 }
1963 cob->matrix[3][1] += offset[1];
1964 }
1965 if (data->flag & LOCLIKE_Z) {
1966 cob->matrix[3][2] = ct->matrix[3][2];
1967
1968 if (data->flag & LOCLIKE_Z_INVERT) {
1969 cob->matrix[3][2] *= -1;
1970 }
1971 cob->matrix[3][2] += offset[2];
1972 }
1973 }
1974}
1975
1977 /*type*/ CONSTRAINT_TYPE_LOCLIKE,
1978 /*size*/ sizeof(bLocateLikeConstraint),
1979 /*name*/ N_("Copy Location"),
1980 /*struct_name*/ "bLocateLikeConstraint",
1981 /*free_data*/ nullptr,
1982 /*id_looper*/ loclike_id_looper,
1983 /*copy_data*/ nullptr,
1984 /*new_data*/ loclike_new_data,
1985 /*get_constraint_targets*/ loclike_get_tars,
1986 /*flush_constraint_targets*/ loclike_flush_tars,
1987 /*get_target_matrix*/ default_get_tarmat,
1988 /*evaluate_constraint*/ loclike_evaluate,
1989};
1990
1991/* ----------- Copy Rotation ------------- */
1992
1993static void rotlike_new_data(void *cdata)
1994{
1996
1997 data->flag = ROTLIKE_X | ROTLIKE_Y | ROTLIKE_Z;
1998}
1999
2000static void rotlike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
2001{
2002 bRotateLikeConstraint *data = static_cast<bRotateLikeConstraint *>(con->data);
2003
2004 /* target only */
2005 func(con, (ID **)&data->tar, false, userdata);
2006}
2007
2009{
2010 if (con && list) {
2011 bRotateLikeConstraint *data = static_cast<bRotateLikeConstraint *>(con->data);
2013
2014 /* standard target-getting macro for single-target constraints */
2015 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
2016
2017 return 1;
2018 }
2019
2020 return 0;
2021}
2022
2023static void rotlike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
2024{
2025 if (con && list) {
2026 bRotateLikeConstraint *data = static_cast<bRotateLikeConstraint *>(con->data);
2027 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
2028
2029 /* the following macro is used for all standard single-target constraints */
2030 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
2031 }
2032}
2033
2034static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
2035{
2036 bRotateLikeConstraint *data = static_cast<bRotateLikeConstraint *>(con->data);
2037 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
2038
2039 if (VALID_CONS_TARGET(ct)) {
2040 float loc[3], size[3], oldrot[3][3], newrot[3][3];
2041 float eul[3], obeul[3], defeul[3];
2042
2043 mat4_to_loc_rot_size(loc, oldrot, size, cob->matrix);
2044
2045 /* Select the Euler rotation order, defaulting to the owner. */
2046 short rot_order = cob->rotOrder;
2047
2048 if (data->euler_order != CONSTRAINT_EULER_AUTO) {
2049 rot_order = data->euler_order;
2050 }
2051
2052 /* To allow compatible rotations, must get both rotations in the order of the owner... */
2053 mat4_to_eulO(obeul, rot_order, cob->matrix);
2054 /* We must get compatible eulers from the beginning because
2055 * some of them can be modified below (see bug #21875).
2056 * Additionally, since this constraint is based on euler rotation math, it doesn't work well
2057 * with shear. The Y axis is chosen as the main axis when we orthogonalize the matrix because
2058 * constraints are used most commonly on bones. */
2059 float mat[4][4];
2060 copy_m4_m4(mat, ct->matrix);
2061 orthogonalize_m4_stable(mat, 1, true);
2062 mat4_to_compatible_eulO(eul, obeul, rot_order, mat);
2063
2064 /* Prepare the copied euler rotation. */
2065 bool legacy_offset = false;
2066
2067 switch (data->mix_mode) {
2068 case ROTLIKE_MIX_OFFSET:
2069 legacy_offset = true;
2070 copy_v3_v3(defeul, obeul);
2071 break;
2072
2074 copy_v3_v3(defeul, obeul);
2075 break;
2076
2077 default:
2078 zero_v3(defeul);
2079 }
2080
2081 if ((data->flag & ROTLIKE_X) == 0) {
2082 eul[0] = defeul[0];
2083 }
2084 else {
2085 if (legacy_offset) {
2086 rotate_eulO(eul, rot_order, 'X', obeul[0]);
2087 }
2088
2089 if (data->flag & ROTLIKE_X_INVERT) {
2090 eul[0] *= -1;
2091 }
2092 }
2093
2094 if ((data->flag & ROTLIKE_Y) == 0) {
2095 eul[1] = defeul[1];
2096 }
2097 else {
2098 if (legacy_offset) {
2099 rotate_eulO(eul, rot_order, 'Y', obeul[1]);
2100 }
2101
2102 if (data->flag & ROTLIKE_Y_INVERT) {
2103 eul[1] *= -1;
2104 }
2105 }
2106
2107 if ((data->flag & ROTLIKE_Z) == 0) {
2108 eul[2] = defeul[2];
2109 }
2110 else {
2111 if (legacy_offset) {
2112 rotate_eulO(eul, rot_order, 'Z', obeul[2]);
2113 }
2114
2115 if (data->flag & ROTLIKE_Z_INVERT) {
2116 eul[2] *= -1;
2117 }
2118 }
2119
2120 /* Add the euler components together if needed. */
2121 if (data->mix_mode == ROTLIKE_MIX_ADD) {
2122 add_v3_v3(eul, obeul);
2123 }
2124
2125 /* Good to make eulers compatible again,
2126 * since we don't know how much they were changed above. */
2127 compatible_eul(eul, obeul);
2128 eulO_to_mat3(newrot, eul, rot_order);
2129
2130 /* Mix the rotation matrices: */
2131 switch (data->mix_mode) {
2133 case ROTLIKE_MIX_OFFSET:
2134 case ROTLIKE_MIX_ADD:
2135 break;
2136
2137 case ROTLIKE_MIX_BEFORE:
2138 mul_m3_m3m3(newrot, newrot, oldrot);
2139 break;
2140
2141 case ROTLIKE_MIX_AFTER:
2142 mul_m3_m3m3(newrot, oldrot, newrot);
2143 break;
2144
2145 default:
2146 BLI_assert(false);
2147 }
2148
2149 loc_rot_size_to_mat4(cob->matrix, loc, newrot, size);
2150 }
2151}
2152
2154 /*type*/ CONSTRAINT_TYPE_ROTLIKE,
2155 /*size*/ sizeof(bRotateLikeConstraint),
2156 /*name*/ N_("Copy Rotation"),
2157 /*struct_name*/ "bRotateLikeConstraint",
2158 /*free_data*/ nullptr,
2159 /*id_looper*/ rotlike_id_looper,
2160 /*copy_data*/ nullptr,
2161 /*new_data*/ rotlike_new_data,
2162 /*get_constraint_targets*/ rotlike_get_tars,
2163 /*flush_constraint_targets*/ rotlike_flush_tars,
2164 /*get_target_matrix*/ default_get_tarmat,
2165 /*evaluate_constraint*/ rotlike_evaluate,
2166};
2167
2168/* ---------- Copy Scale ---------- */
2169
2170static void sizelike_new_data(void *cdata)
2171{
2173
2175 data->power = 1.0f;
2176}
2177
2178static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
2179{
2180 bSizeLikeConstraint *data = static_cast<bSizeLikeConstraint *>(con->data);
2181
2182 /* target only */
2183 func(con, (ID **)&data->tar, false, userdata);
2184}
2185
2187{
2188 if (con && list) {
2189 bSizeLikeConstraint *data = static_cast<bSizeLikeConstraint *>(con->data);
2191
2192 /* standard target-getting macro for single-target constraints */
2193 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
2194
2195 return 1;
2196 }
2197
2198 return 0;
2199}
2200
2201static void sizelike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
2202{
2203 if (con && list) {
2204 bSizeLikeConstraint *data = static_cast<bSizeLikeConstraint *>(con->data);
2205 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
2206
2207 /* the following macro is used for all standard single-target constraints */
2208 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
2209 }
2210}
2211
2212static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
2213{
2214 bSizeLikeConstraint *data = static_cast<bSizeLikeConstraint *>(con->data);
2215 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
2216
2217 if (VALID_CONS_TARGET(ct)) {
2218 float obsize[3], size[3];
2219
2220 mat4_to_size(obsize, cob->matrix);
2221
2222 /* Compute one uniform scale factor to apply to all three axes. */
2223 if (data->flag & SIZELIKE_UNIFORM) {
2224 const int all_axes = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z;
2225 float total = 1.0f;
2226
2227 /* If all axes are selected, use the determinant. */
2228 if ((data->flag & all_axes) == all_axes) {
2229 total = fabsf(mat4_to_volume_scale(ct->matrix));
2230 }
2231 /* Otherwise multiply individual values. */
2232 else {
2233 mat4_to_size(size, ct->matrix);
2234
2235 if (data->flag & SIZELIKE_X) {
2236 total *= size[0];
2237 }
2238 if (data->flag & SIZELIKE_Y) {
2239 total *= size[1];
2240 }
2241 if (data->flag & SIZELIKE_Z) {
2242 total *= size[2];
2243 }
2244 }
2245
2246 copy_v3_fl(size, cbrt(total));
2247 }
2248 /* Regular per-axis scaling. */
2249 else {
2250 mat4_to_size(size, ct->matrix);
2251 }
2252
2253 for (int i = 0; i < 3; i++) {
2254 size[i] = powf(size[i], data->power);
2255 }
2256
2257 if (data->flag & SIZELIKE_OFFSET) {
2258 /* Scale is a multiplicative quantity, so adding it makes no sense.
2259 * However, the additive mode has to stay for backward compatibility. */
2260 if (data->flag & SIZELIKE_MULTIPLY) {
2261 /* size[i] *= obsize[i] */
2262 mul_v3_v3(size, obsize);
2263 }
2264 else {
2265 /* 2.7 compatibility mode: size[i] += (obsize[i] - 1.0f) */
2266 add_v3_v3(size, obsize);
2267 add_v3_fl(size, -1.0f);
2268 }
2269 }
2270
2271 if ((data->flag & (SIZELIKE_X | SIZELIKE_UNIFORM)) && (obsize[0] != 0)) {
2272 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
2273 }
2274 if ((data->flag & (SIZELIKE_Y | SIZELIKE_UNIFORM)) && (obsize[1] != 0)) {
2275 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
2276 }
2277 if ((data->flag & (SIZELIKE_Z | SIZELIKE_UNIFORM)) && (obsize[2] != 0)) {
2278 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
2279 }
2280 }
2281}
2282
2284 /*type*/ CONSTRAINT_TYPE_SIZELIKE,
2285 /*size*/ sizeof(bSizeLikeConstraint),
2286 /*name*/ N_("Copy Scale"),
2287 /*struct_name*/ "bSizeLikeConstraint",
2288 /*free_data*/ nullptr,
2289 /*id_looper*/ sizelike_id_looper,
2290 /*copy_data*/ nullptr,
2291 /*new_data*/ sizelike_new_data,
2292 /*get_constraint_targets*/ sizelike_get_tars,
2293 /*flush_constraint_targets*/ sizelike_flush_tars,
2294 /*get_target_matrix*/ default_get_tarmat,
2295 /*evaluate_constraint*/ sizelike_evaluate,
2296};
2297
2298/* ----------- Copy Transforms ------------- */
2299
2300static void translike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
2301{
2302 bTransLikeConstraint *data = static_cast<bTransLikeConstraint *>(con->data);
2303
2304 /* target only */
2305 func(con, (ID **)&data->tar, false, userdata);
2306}
2307
2309{
2310 if (con && list) {
2311 bTransLikeConstraint *data = static_cast<bTransLikeConstraint *>(con->data);
2313
2314 /* standard target-getting macro for single-target constraints */
2315 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
2316
2317 return 1;
2318 }
2319
2320 return 0;
2321}
2322
2323static void translike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
2324{
2325 if (con && list) {
2326 bTransLikeConstraint *data = static_cast<bTransLikeConstraint *>(con->data);
2327 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
2328
2329 /* the following macro is used for all standard single-target constraints */
2330 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
2331 }
2332}
2333
2334static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
2335{
2336 bTransLikeConstraint *data = static_cast<bTransLikeConstraint *>(con->data);
2337 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
2338
2339 if (VALID_CONS_TARGET(ct)) {
2340 float target_mat[4][4];
2341
2342 copy_m4_m4(target_mat, ct->matrix);
2343
2344 /* Remove the shear of the target matrix if enabled.
2345 * Use Y as the axis since it's the natural default for bones. */
2346 if (data->flag & TRANSLIKE_REMOVE_TARGET_SHEAR) {
2347 orthogonalize_m4_stable(target_mat, 1, false);
2348 }
2349
2350 /* Finally, combine the matrices. */
2351 switch (data->mix_mode) {
2353 copy_m4_m4(cob->matrix, target_mat);
2354 break;
2355
2356 /* Simple matrix multiplication. */
2358 mul_m4_m4m4(cob->matrix, target_mat, cob->matrix);
2359 break;
2360
2362 mul_m4_m4m4(cob->matrix, cob->matrix, target_mat);
2363 break;
2364
2365 /* Aligned Inherit Scale emulation. */
2367 mul_m4_m4m4_aligned_scale(cob->matrix, target_mat, cob->matrix);
2368 break;
2369
2371 mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, target_mat);
2372 break;
2373
2374 /* Fully separate handling of channels. */
2376 mul_m4_m4m4_split_channels(cob->matrix, target_mat, cob->matrix);
2377 break;
2378
2380 mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, target_mat);
2381 break;
2382
2383 default:
2384 BLI_assert_msg(0, "Unknown Copy Transforms mix mode");
2385 }
2386 }
2387}
2388
2391 /*size*/ sizeof(bTransLikeConstraint),
2392 /*name*/ N_("Copy Transforms"),
2393 /*struct_name*/ "bTransLikeConstraint",
2394 /*free_data*/ nullptr,
2395 /*id_looper*/ translike_id_looper,
2396 /*copy_data*/ nullptr,
2397 /*new_data*/ nullptr,
2398 /*get_constraint_targets*/ translike_get_tars,
2399 /*flush_constraint_targets*/ translike_flush_tars,
2400 /*get_target_matrix*/ default_get_tarmat_full_bbone,
2401 /*evaluate_constraint*/ translike_evaluate,
2402};
2403
2404/* ---------- Maintain Volume ---------- */
2405
2406static void samevolume_new_data(void *cdata)
2407{
2409
2410 data->free_axis = SAMEVOL_Y;
2411 data->volume = 1.0f;
2412}
2413
2414static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
2415{
2416 bSameVolumeConstraint *data = static_cast<bSameVolumeConstraint *>(con->data);
2417
2418 float volume = data->volume;
2419 float fac = 1.0f, total_scale = 1.0f;
2420 float obsize[3];
2421
2422 mat4_to_size(obsize, cob->matrix);
2423
2424 /* calculate normalizing scale factor for non-essential values */
2425 switch (data->mode) {
2426 case SAMEVOL_STRICT:
2427 total_scale = obsize[0] * obsize[1] * obsize[2];
2428 break;
2429 case SAMEVOL_UNIFORM:
2430 total_scale = pow3f(obsize[data->free_axis]);
2431 break;
2433 total_scale = obsize[data->free_axis];
2434 break;
2435 }
2436
2437 if (total_scale != 0) {
2438 fac = sqrtf(volume / total_scale);
2439 }
2440
2441 /* apply scaling factor to the channels not being kept */
2442 switch (data->free_axis) {
2443 case SAMEVOL_X:
2444 mul_v3_fl(cob->matrix[1], fac);
2445 mul_v3_fl(cob->matrix[2], fac);
2446 break;
2447 case SAMEVOL_Y:
2448 mul_v3_fl(cob->matrix[0], fac);
2449 mul_v3_fl(cob->matrix[2], fac);
2450 break;
2451 case SAMEVOL_Z:
2452 mul_v3_fl(cob->matrix[0], fac);
2453 mul_v3_fl(cob->matrix[1], fac);
2454 break;
2455 }
2456}
2457
2459 /*type*/ CONSTRAINT_TYPE_SAMEVOL,
2460 /*size*/ sizeof(bSameVolumeConstraint),
2461 /*name*/ N_("Maintain Volume"),
2462 /*struct_name*/ "bSameVolumeConstraint",
2463 /*free_data*/ nullptr,
2464 /*id_looper*/ nullptr,
2465 /*copy_data*/ nullptr,
2466 /*new_data*/ samevolume_new_data,
2467 /*get_constraint_targets*/ nullptr,
2468 /*flush_constraint_targets*/ nullptr,
2469 /*get_target_matrix*/ nullptr,
2470 /*evaluate_constraint*/ samevolume_evaluate,
2471};
2472
2473/* ----------- Python Constraint -------------- */
2474
2475static void pycon_free(bConstraint *con)
2476{
2477 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
2478
2479 /* id-properties */
2480 IDP_FreeProperty(data->prop);
2481
2482 /* multiple targets */
2483 BLI_freelistN(&data->targets);
2484}
2485
2486static void pycon_copy(bConstraint *con, bConstraint *srccon)
2487{
2488 bPythonConstraint *pycon = (bPythonConstraint *)con->data;
2489 bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
2490
2491 pycon->prop = IDP_CopyProperty(opycon->prop);
2492 BLI_duplicatelist(&pycon->targets, &opycon->targets);
2493}
2494
2495static void pycon_new_data(void *cdata)
2496{
2497 bPythonConstraint *data = (bPythonConstraint *)cdata;
2498
2499 /* Everything should be set correctly by calloc, except for the prop->type constant. */
2500 data->prop = static_cast<IDProperty *>(MEM_callocN(sizeof(IDProperty), "PyConstraintProps"));
2501 data->prop->type = IDP_GROUP;
2502}
2503
2504static int pycon_get_tars(bConstraint *con, ListBase *list)
2505{
2506 if (con && list) {
2507 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
2508
2509 list->first = data->targets.first;
2510 list->last = data->targets.last;
2511
2512 return data->tarnum;
2513 }
2514
2515 return 0;
2516}
2517
2518static void pycon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
2519{
2520 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
2521
2522 /* targets */
2523 LISTBASE_FOREACH (bConstraintTarget *, ct, &data->targets) {
2524 func(con, (ID **)&ct->tar, false, userdata);
2525 }
2526
2527 /* script */
2528 func(con, (ID **)&data->text, true, userdata);
2529}
2530
2531/* Whether this approach is maintained remains to be seen (aligorith) */
2532static void pycon_get_tarmat(Depsgraph * /*depsgraph*/,
2533 bConstraint *con,
2534 bConstraintOb *cob,
2536 float /*ctime*/)
2537{
2538#ifdef WITH_PYTHON
2539 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
2540#endif
2541
2542 if (VALID_CONS_TARGET(ct)) {
2543 if (ct->tar->type == OB_CURVES_LEGACY && ct->tar->runtime->curve_cache == nullptr) {
2544 unit_m4(ct->matrix);
2545 return;
2546 }
2547
2548 /* firstly calculate the matrix the normal way, then let the py-function override
2549 * this matrix if it needs to do so
2550 */
2552 ct->subtarget,
2553 cob,
2554 ct->matrix,
2556 ct->space,
2557 con->flag,
2558 con->headtail);
2559
2560/* only execute target calculation if allowed */
2561#ifdef WITH_PYTHON
2562 if (G.f & G_FLAG_SCRIPT_AUTOEXEC) {
2563 BPY_pyconstraint_target(data, ct);
2564 }
2565#endif
2566 }
2567 else if (ct) {
2568 unit_m4(ct->matrix);
2569 }
2570}
2571
2572static void pycon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
2573{
2574#ifndef WITH_PYTHON
2575 UNUSED_VARS(con, cob, targets);
2576 return;
2577#else
2578 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
2579
2580 /* only evaluate in python if we're allowed to do so */
2581 if ((G.f & G_FLAG_SCRIPT_AUTOEXEC) == 0) {
2582 return;
2583 }
2584
2585 /* Now, run the actual 'constraint' function, which should only access the matrices */
2586 BPY_pyconstraint_exec(data, cob, targets);
2587#endif /* WITH_PYTHON */
2588}
2589
2591 /*type*/ CONSTRAINT_TYPE_PYTHON,
2592 /*size*/ sizeof(bPythonConstraint),
2593 /*name*/ N_("Script"),
2594 /*struct_name*/ "bPythonConstraint",
2595 /*free_data*/ pycon_free,
2596 /*id_looper*/ pycon_id_looper,
2597 /*copy_data*/ pycon_copy,
2598 /*new_data*/ pycon_new_data,
2599 /*get_constraint_targets*/ pycon_get_tars,
2600 /*flush_constraint_targets*/ nullptr,
2601 /*get_target_matrix*/ pycon_get_tarmat,
2602 /*evaluate_constraint*/ pycon_evaluate,
2603};
2604
2605/* ----------- Armature Constraint -------------- */
2606
2607static void armdef_free(bConstraint *con)
2608{
2609 bArmatureConstraint *data = static_cast<bArmatureConstraint *>(con->data);
2610
2611 /* Target list. */
2612 BLI_freelistN(&data->targets);
2613}
2614
2615static void armdef_copy(bConstraint *con, bConstraint *srccon)
2616{
2618 bArmatureConstraint *opcon = (bArmatureConstraint *)srccon->data;
2619
2620 BLI_duplicatelist(&pcon->targets, &opcon->targets);
2621}
2622
2623static int armdef_get_tars(bConstraint *con, ListBase *list)
2624{
2625 if (con && list) {
2626 bArmatureConstraint *data = static_cast<bArmatureConstraint *>(con->data);
2627
2628 *list = data->targets;
2629
2630 return BLI_listbase_count(&data->targets);
2631 }
2632
2633 return 0;
2634}
2635
2636static void armdef_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
2637{
2638 bArmatureConstraint *data = static_cast<bArmatureConstraint *>(con->data);
2639
2640 /* Target list. */
2641 LISTBASE_FOREACH (bConstraintTarget *, ct, &data->targets) {
2642 func(con, (ID **)&ct->tar, false, userdata);
2643 }
2644}
2645
2646/* Compute the world space pose matrix of the target bone. */
2647static void armdef_get_tarmat(Depsgraph * /*depsgraph*/,
2648 bConstraint * /*con*/,
2649 bConstraintOb * /*cob*/,
2651 float /*ctime*/)
2652{
2653 if (ct != nullptr) {
2654 if (ct->tar && ct->tar->type == OB_ARMATURE) {
2656
2657 if (pchan != nullptr) {
2658 mul_m4_m4m4(ct->matrix, ct->tar->object_to_world().ptr(), pchan->pose_mat);
2659 return;
2660 }
2661 }
2662
2663 unit_m4(ct->matrix);
2664 }
2665}
2666
2667static void armdef_accumulate_matrix(const float obmat[4][4],
2668 const float iobmat[4][4],
2669 const float basemat[4][4],
2670 const float bonemat[4][4],
2671 const float pivot[3],
2672 const float weight,
2673 float r_sum_mat[4][4],
2674 DualQuat *r_sum_dq)
2675{
2676 if (weight == 0.0f) {
2677 return;
2678 }
2679
2680 /* Convert the selected matrix into object space. */
2681 float mat[4][4];
2682 mul_m4_series(mat, obmat, bonemat, iobmat);
2683
2684 /* Accumulate the transformation. */
2685 if (r_sum_dq != nullptr) {
2686 float basemat_world[4][4];
2687 DualQuat tmpdq;
2688
2689 /* Compute the orthonormal rest matrix in world space. */
2690 mul_m4_m4m4(basemat_world, obmat, basemat);
2691 orthogonalize_m4_stable(basemat_world, 1, true);
2692
2693 mat4_to_dquat(&tmpdq, basemat_world, mat);
2694 add_weighted_dq_dq_pivot(r_sum_dq, &tmpdq, pivot, weight, true);
2695 }
2696 else {
2697 madd_m4_m4m4fl(r_sum_mat, r_sum_mat, mat, weight);
2698 }
2699}
2700
2701/* Compute and accumulate transformation for a single target bone. */
2703 const bPoseChannel *pchan,
2704 const float wco[3],
2705 const bool force_envelope,
2706 float *r_totweight,
2707 float r_sum_mat[4][4],
2708 DualQuat *r_sum_dq)
2709{
2710 float iobmat[4][4], co[3];
2711 const Bone *bone = pchan->bone;
2712 float weight = ct->weight;
2713
2714 /* Our object's location in target pose space. */
2715 invert_m4_m4(iobmat, ct->tar->object_to_world().ptr());
2716 mul_v3_m4v3(co, iobmat, wco);
2717
2718 /* Multiply by the envelope weight when appropriate. */
2719 if (force_envelope || (bone->flag & BONE_MULT_VG_ENV)) {
2720 weight *= distfactor_to_bone(
2721 co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
2722 }
2723
2724 /* Find the correct bone transform matrix in world space. */
2725 if (bone->segments > 1 && bone->segments == pchan->runtime.bbone_segments) {
2726 const Mat4 *b_bone_mats = pchan->runtime.bbone_deform_mats;
2727 const Mat4 *b_bone_rest_mats = pchan->runtime.bbone_rest_mats;
2728 float basemat[4][4];
2729
2730 /* Blend the matrix. */
2731 int index;
2732 float blend;
2733 BKE_pchan_bbone_deform_segment_index(pchan, co, &index, &blend);
2734
2735 if (r_sum_dq != nullptr) {
2736 /* Compute the object space rest matrix of the segment. */
2737 mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index].mat);
2738 }
2739
2740 armdef_accumulate_matrix(ct->tar->object_to_world().ptr(),
2741 iobmat,
2742 basemat,
2743 b_bone_mats[index + 1].mat,
2744 wco,
2745 weight * (1.0f - blend),
2746 r_sum_mat,
2747 r_sum_dq);
2748
2749 if (r_sum_dq != nullptr) {
2750 /* Compute the object space rest matrix of the segment. */
2751 mul_m4_m4m4(basemat, bone->arm_mat, b_bone_rest_mats[index + 1].mat);
2752 }
2753
2754 armdef_accumulate_matrix(ct->tar->object_to_world().ptr(),
2755 iobmat,
2756 basemat,
2757 b_bone_mats[index + 2].mat,
2758 wco,
2759 weight * blend,
2760 r_sum_mat,
2761 r_sum_dq);
2762 }
2763 else {
2764 /* Simple bone. This requires DEG_OPCODE_BONE_DONE dependency due to chan_mat. */
2765 armdef_accumulate_matrix(ct->tar->object_to_world().ptr(),
2766 iobmat,
2767 bone->arm_mat,
2768 pchan->chan_mat,
2769 wco,
2770 weight,
2771 r_sum_mat,
2772 r_sum_dq);
2773 }
2774
2775 /* Accumulate the weight. */
2776 *r_totweight += weight;
2777}
2778
2779static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
2780{
2781 bArmatureConstraint *data = static_cast<bArmatureConstraint *>(con->data);
2782
2783 float sum_mat[4][4], input_co[3];
2784 DualQuat sum_dq;
2785 float weight = 0.0f;
2786
2787 /* Prepare for blending. */
2788 zero_m4(sum_mat);
2789 memset(&sum_dq, 0, sizeof(sum_dq));
2790
2791 DualQuat *pdq = (data->flag & CONSTRAINT_ARMATURE_QUATERNION) ? &sum_dq : nullptr;
2792 bool use_envelopes = (data->flag & CONSTRAINT_ARMATURE_ENVELOPE) != 0;
2793
2794 if (cob->pchan && cob->pchan->bone && !(data->flag & CONSTRAINT_ARMATURE_CUR_LOCATION)) {
2795 /* For constraints on bones, use the rest position to bind b-bone segments
2796 * and envelopes, to allow safely changing the bone location as if parented. */
2797 copy_v3_v3(input_co, cob->pchan->bone->arm_head);
2798 mul_m4_v3(cob->ob->object_to_world().ptr(), input_co);
2799 }
2800 else {
2801 copy_v3_v3(input_co, cob->matrix[3]);
2802 }
2803
2804 /* Process all targets. This can't use ct->matrix, as armdef_get_tarmat is not
2805 * called in solve for efficiency because the constraint needs bone data anyway. */
2806 LISTBASE_FOREACH (bConstraintTarget *, ct, targets) {
2807 if (ct->weight <= 0.0f) {
2808 continue;
2809 }
2810
2811 /* Lookup the bone and abort if failed. */
2812 if (!VALID_CONS_TARGET(ct) || ct->tar->type != OB_ARMATURE) {
2813 return;
2814 }
2815
2816 bPoseChannel *pchan = BKE_pose_channel_find_name(ct->tar->pose, ct->subtarget);
2817
2818 if (pchan == nullptr || pchan->bone == nullptr) {
2819 return;
2820 }
2821
2822 armdef_accumulate_bone(ct, pchan, input_co, use_envelopes, &weight, sum_mat, pdq);
2823 }
2824
2825 /* Compute the final transform. */
2826 if (weight > 0.0f) {
2827 if (pdq != nullptr) {
2828 normalize_dq(pdq, weight);
2829 dquat_to_mat4(sum_mat, pdq);
2830 }
2831 else {
2832 mul_m4_fl(sum_mat, 1.0f / weight);
2833 }
2834
2835 /* Apply the transform to the result matrix. */
2836 mul_m4_m4m4(cob->matrix, sum_mat, cob->matrix);
2837 }
2838}
2839
2841 /*type*/ CONSTRAINT_TYPE_ARMATURE,
2842 /*size*/ sizeof(bArmatureConstraint),
2843 /*name*/ N_("Armature"),
2844 /*struct_name*/ "bArmatureConstraint",
2845 /*free_data*/ armdef_free,
2846 /*id_looper*/ armdef_id_looper,
2847 /*copy_data*/ armdef_copy,
2848 /*new_data*/ nullptr,
2849 /*get_constraint_targets*/ armdef_get_tars,
2850 /*flush_constraint_targets*/ nullptr,
2851 /*get_target_matrix*/ armdef_get_tarmat,
2852 /*evaluate_constraint*/ armdef_evaluate,
2853};
2854
2855/* -------- Action Constraint ----------- */
2856
2857static void actcon_new_data(void *cdata)
2858{
2859 bActionConstraint *data = (bActionConstraint *)cdata;
2860
2861 /* set type to 20 (Loc X), as 0 is Rot X for backwards compatibility */
2862 data->type = 20;
2863
2864 /* Set the mix mode to After Original with anti-shear scale handling. */
2865 data->mix_mode = ACTCON_MIX_AFTER;
2866}
2867
2868static void actcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
2869{
2870 bActionConstraint *data = static_cast<bActionConstraint *>(con->data);
2871
2872 /* target */
2873 func(con, (ID **)&data->tar, false, userdata);
2874
2875 /* action */
2876 func(con, (ID **)&data->act, true, userdata);
2877}
2878
2879static int actcon_get_tars(bConstraint *con, ListBase *list)
2880{
2881 if (con && list) {
2882 bActionConstraint *data = static_cast<bActionConstraint *>(con->data);
2884
2885 /* standard target-getting macro for single-target constraints */
2886 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
2887
2888 return 1;
2889 }
2890
2891 return 0;
2892}
2893
2894static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
2895{
2896 if (con && list) {
2897 bActionConstraint *data = static_cast<bActionConstraint *>(con->data);
2898 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
2899
2900 /* the following macro is used for all standard single-target constraints */
2901 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
2902 }
2903}
2904
2905static void actcon_get_tarmat(Depsgraph *depsgraph,
2906 bConstraint *con,
2907 bConstraintOb *cob,
2909 float /*ctime*/)
2910{
2911 bActionConstraint *data = static_cast<bActionConstraint *>(con->data);
2912
2913 if (!data->act) {
2914 /* Without an Action, this constraint cannot do anything. */
2915 return;
2916 }
2917
2918 if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) {
2919 float tempmat[4][4], vec[3];
2920 float s, t;
2921 short axis;
2922
2923 /* initialize return matrix */
2924 unit_m4(ct->matrix);
2925
2926 /* Skip targets if we're using local float property to set action time */
2927 if (data->flag & ACTCON_USE_EVAL_TIME) {
2928 s = data->eval_time;
2929 }
2930 else {
2931 /* get the transform matrix of the target */
2933 ct->subtarget,
2934 cob,
2935 tempmat,
2937 ct->space,
2938 con->flag,
2939 con->headtail);
2940
2941 /* determine where in transform range target is */
2942 /* data->type is mapped as follows for backwards compatibility:
2943 * 00,01,02 - rotation (it used to be like this)
2944 * 10,11,12 - scaling
2945 * 20,21,22 - location
2946 */
2947 if (data->type < 10) {
2948 /* extract rotation (is in whatever space target should be in) */
2949 mat4_to_eul(vec, tempmat);
2950 mul_v3_fl(vec, RAD2DEGF(1.0f)); /* rad -> deg */
2951 axis = data->type;
2952 }
2953 else if (data->type < 20) {
2954 /* extract scaling (is in whatever space target should be in) */
2955 mat4_to_size(vec, tempmat);
2956 axis = data->type - 10;
2957 }
2958 else {
2959 /* extract location */
2960 copy_v3_v3(vec, tempmat[3]);
2961 axis = data->type - 20;
2962 }
2963
2964 BLI_assert(uint(axis) < 3);
2965
2966 /* Convert the target's value into a [0, 1] value that's later used to find the Action frame
2967 * to apply. This compares to the min/max boundary values first, before doing the
2968 * normalization by the (max-min) range, to get predictable, valid values when that range is
2969 * zero. */
2970 const float range = data->max - data->min;
2971 if ((range == 0.0f) || (ushort(axis) > 2)) {
2972 s = 0.0f;
2973 }
2974 else {
2975 s = (vec[axis] - data->min) / range;
2976 }
2977 }
2978
2979 CLAMP(s, 0, 1);
2980 t = (s * (data->end - data->start)) + data->start;
2982 t);
2983
2984 if (G.debug & G_DEBUG) {
2985 printf("do Action Constraint %s - Ob %s Pchan %s\n",
2986 con->name,
2987 cob->ob->id.name + 2,
2988 (cob->pchan) ? cob->pchan->name : nullptr);
2989 }
2990
2991 /* Get the appropriate information from the action */
2992 if (cob->type == CONSTRAINT_OBTYPE_OBJECT || (data->flag & ACTCON_BONE_USE_OBJECT_ACTION)) {
2993 Object workob;
2994
2995 /* evaluate using workob */
2996 /* FIXME: we don't have any consistent standards on limiting effects on object... */
2998 &workob,
2999 nullptr,
3000 data->act,
3001 data->action_slot_handle,
3002 nullptr,
3003 &anim_eval_context);
3004 BKE_object_to_mat4(&workob, ct->matrix);
3005 }
3006 else if (cob->type == CONSTRAINT_OBTYPE_BONE) {
3007 Object workob;
3008 bPose pose = {{nullptr}};
3009 bPoseChannel *pchan, *tchan;
3010
3011 /* make a copy of the bone of interest in the temp pose before evaluating action,
3012 * so that it can get set - we need to manually copy over a few settings,
3013 * including rotation order, otherwise this fails. */
3014 pchan = cob->pchan;
3015
3016 tchan = BKE_pose_channel_ensure(&pose, pchan->name);
3017 tchan->rotmode = pchan->rotmode;
3018
3019 /* evaluate action using workob (it will only set the PoseChannel in question) */
3021 &workob,
3022 &pose,
3023 data->act,
3024 data->action_slot_handle,
3025 pchan->name,
3026 &anim_eval_context);
3027
3028 /* convert animation to matrices for use here */
3029 BKE_pchan_calc_mat(tchan);
3030 copy_m4_m4(ct->matrix, tchan->chan_mat);
3031
3032 /* Clean up */
3033 BKE_pose_free_data(&pose);
3034 }
3035 else {
3036 /* behavior undefined... */
3037 puts("Error: unknown owner type for Action Constraint");
3038 }
3039 }
3040}
3041
3042static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
3043{
3044 bActionConstraint *data = static_cast<bActionConstraint *>(con->data);
3045 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
3046
3047 if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) {
3048 switch (data->mix_mode) {
3049 /* Simple matrix multiplication. */
3051 mul_m4_m4m4(cob->matrix, ct->matrix, cob->matrix);
3052 break;
3053
3055 mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix);
3056 break;
3057
3058 /* Aligned Inherit Scale emulation. */
3059 case ACTCON_MIX_BEFORE:
3061 break;
3062
3063 case ACTCON_MIX_AFTER:
3065 break;
3066
3067 /* Fully separate handling of channels. */
3070 break;
3071
3074 break;
3075
3076 default:
3077 BLI_assert_msg(0, "Unknown Action mix mode");
3078 }
3079 }
3080}
3081
3083 /*type*/ CONSTRAINT_TYPE_ACTION,
3084 /*size*/ sizeof(bActionConstraint),
3085 /*name*/ N_("Action"),
3086 /*struct_name*/ "bActionConstraint",
3087 /*free_data*/ nullptr,
3088 /*id_looper*/ actcon_id_looper,
3089 /*copy_data*/ nullptr,
3090 /*new_data*/ actcon_new_data,
3091 /*get_constraint_targets*/ actcon_get_tars,
3092 /*flush_constraint_targets*/ actcon_flush_tars,
3093 /*get_target_matrix*/ actcon_get_tarmat,
3094 /*evaluate_constraint*/ actcon_evaluate,
3095};
3096
3097/* --------- Locked Track ---------- */
3098
3099static void locktrack_new_data(void *cdata)
3100{
3102
3103 data->trackflag = TRACK_Y;
3104 data->lockflag = LOCK_Z;
3105}
3106
3107static void locktrack_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
3108{
3109 bLockTrackConstraint *data = static_cast<bLockTrackConstraint *>(con->data);
3110
3111 /* target only */
3112 func(con, (ID **)&data->tar, false, userdata);
3113}
3114
3116{
3117 if (con && list) {
3118 bLockTrackConstraint *data = static_cast<bLockTrackConstraint *>(con->data);
3120
3121 /* the following macro is used for all standard single-target constraints */
3122 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
3123
3124 return 1;
3125 }
3126
3127 return 0;
3128}
3129
3130static void locktrack_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
3131{
3132 if (con && list) {
3133 bLockTrackConstraint *data = static_cast<bLockTrackConstraint *>(con->data);
3134 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
3135
3136 /* the following macro is used for all standard single-target constraints */
3137 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
3138 }
3139}
3140
3141static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
3142{
3143 bLockTrackConstraint *data = static_cast<bLockTrackConstraint *>(con->data);
3144 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
3145
3146 if (VALID_CONS_TARGET(ct)) {
3147 float vec[3], vec2[3];
3148 float totmat[3][3];
3149 float tmpmat[3][3];
3150 float invmat[3][3];
3151 float mdet;
3152
3153 /* Vector object -> target */
3154 sub_v3_v3v3(vec, ct->matrix[3], cob->matrix[3]);
3155 switch (data->lockflag) {
3156 case LOCK_X: /* LOCK X */
3157 {
3158 switch (data->trackflag) {
3159 case TRACK_Y: /* LOCK X TRACK Y */
3160 {
3161 /* Projection of Vector on the plane */
3162 project_v3_v3v3(vec2, vec, cob->matrix[0]);
3163 sub_v3_v3v3(totmat[1], vec, vec2);
3164 normalize_v3(totmat[1]);
3165
3166 /* the x axis is fixed */
3167 normalize_v3_v3(totmat[0], cob->matrix[0]);
3168
3169 /* the z axis gets mapped onto a third orthogonal vector */
3170 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
3171 break;
3172 }
3173 case TRACK_Z: /* LOCK X TRACK Z */
3174 {
3175 /* Projection of Vector on the plane */
3176 project_v3_v3v3(vec2, vec, cob->matrix[0]);
3177 sub_v3_v3v3(totmat[2], vec, vec2);
3178 normalize_v3(totmat[2]);
3179
3180 /* the x axis is fixed */
3181 normalize_v3_v3(totmat[0], cob->matrix[0]);
3182
3183 /* the z axis gets mapped onto a third orthogonal vector */
3184 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
3185 break;
3186 }
3187 case TRACK_nY: /* LOCK X TRACK -Y */
3188 {
3189 /* Projection of Vector on the plane */
3190 project_v3_v3v3(vec2, vec, cob->matrix[0]);
3191 sub_v3_v3v3(totmat[1], vec, vec2);
3192 normalize_v3(totmat[1]);
3193 negate_v3(totmat[1]);
3194
3195 /* the x axis is fixed */
3196 normalize_v3_v3(totmat[0], cob->matrix[0]);
3197
3198 /* the z axis gets mapped onto a third orthogonal vector */
3199 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
3200 break;
3201 }
3202 case TRACK_nZ: /* LOCK X TRACK -Z */
3203 {
3204 /* Projection of Vector on the plane */
3205 project_v3_v3v3(vec2, vec, cob->matrix[0]);
3206 sub_v3_v3v3(totmat[2], vec, vec2);
3207 normalize_v3(totmat[2]);
3208 negate_v3(totmat[2]);
3209
3210 /* the x axis is fixed */
3211 normalize_v3_v3(totmat[0], cob->matrix[0]);
3212
3213 /* the z axis gets mapped onto a third orthogonal vector */
3214 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
3215 break;
3216 }
3217 default: {
3218 unit_m3(totmat);
3219 break;
3220 }
3221 }
3222 break;
3223 }
3224 case LOCK_Y: /* LOCK Y */
3225 {
3226 switch (data->trackflag) {
3227 case TRACK_X: /* LOCK Y TRACK X */
3228 {
3229 /* Projection of Vector on the plane */
3230 project_v3_v3v3(vec2, vec, cob->matrix[1]);
3231 sub_v3_v3v3(totmat[0], vec, vec2);
3232 normalize_v3(totmat[0]);
3233
3234 /* the y axis is fixed */
3235 normalize_v3_v3(totmat[1], cob->matrix[1]);
3236
3237 /* the z axis gets mapped onto a third orthogonal vector */
3238 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
3239 break;
3240 }
3241 case TRACK_Z: /* LOCK Y TRACK Z */
3242 {
3243 /* Projection of Vector on the plane */
3244 project_v3_v3v3(vec2, vec, cob->matrix[1]);
3245 sub_v3_v3v3(totmat[2], vec, vec2);
3246 normalize_v3(totmat[2]);
3247
3248 /* the y axis is fixed */
3249 normalize_v3_v3(totmat[1], cob->matrix[1]);
3250
3251 /* the z axis gets mapped onto a third orthogonal vector */
3252 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
3253 break;
3254 }
3255 case TRACK_nX: /* LOCK Y TRACK -X */
3256 {
3257 /* Projection of Vector on the plane */
3258 project_v3_v3v3(vec2, vec, cob->matrix[1]);
3259 sub_v3_v3v3(totmat[0], vec, vec2);
3260 normalize_v3(totmat[0]);
3261 negate_v3(totmat[0]);
3262
3263 /* the y axis is fixed */
3264 normalize_v3_v3(totmat[1], cob->matrix[1]);
3265
3266 /* the z axis gets mapped onto a third orthogonal vector */
3267 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
3268 break;
3269 }
3270 case TRACK_nZ: /* LOCK Y TRACK -Z */
3271 {
3272 /* Projection of Vector on the plane */
3273 project_v3_v3v3(vec2, vec, cob->matrix[1]);
3274 sub_v3_v3v3(totmat[2], vec, vec2);
3275 normalize_v3(totmat[2]);
3276 negate_v3(totmat[2]);
3277
3278 /* the y axis is fixed */
3279 normalize_v3_v3(totmat[1], cob->matrix[1]);
3280
3281 /* the z axis gets mapped onto a third orthogonal vector */
3282 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
3283 break;
3284 }
3285 default: {
3286 unit_m3(totmat);
3287 break;
3288 }
3289 }
3290 break;
3291 }
3292 case LOCK_Z: /* LOCK Z */
3293 {
3294 switch (data->trackflag) {
3295 case TRACK_X: /* LOCK Z TRACK X */
3296 {
3297 /* Projection of Vector on the plane */
3298 project_v3_v3v3(vec2, vec, cob->matrix[2]);
3299 sub_v3_v3v3(totmat[0], vec, vec2);
3300 normalize_v3(totmat[0]);
3301
3302 /* the z axis is fixed */
3303 normalize_v3_v3(totmat[2], cob->matrix[2]);
3304
3305 /* the x axis gets mapped onto a third orthogonal vector */
3306 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
3307 break;
3308 }
3309 case TRACK_Y: /* LOCK Z TRACK Y */
3310 {
3311 /* Projection of Vector on the plane */
3312 project_v3_v3v3(vec2, vec, cob->matrix[2]);
3313 sub_v3_v3v3(totmat[1], vec, vec2);
3314 normalize_v3(totmat[1]);
3315
3316 /* the z axis is fixed */
3317 normalize_v3_v3(totmat[2], cob->matrix[2]);
3318
3319 /* the x axis gets mapped onto a third orthogonal vector */
3320 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
3321 break;
3322 }
3323 case TRACK_nX: /* LOCK Z TRACK -X */
3324 {
3325 /* Projection of Vector on the plane */
3326 project_v3_v3v3(vec2, vec, cob->matrix[2]);
3327 sub_v3_v3v3(totmat[0], vec, vec2);
3328 normalize_v3(totmat[0]);
3329 negate_v3(totmat[0]);
3330
3331 /* the z axis is fixed */
3332 normalize_v3_v3(totmat[2], cob->matrix[2]);
3333
3334 /* the x axis gets mapped onto a third orthogonal vector */
3335 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
3336 break;
3337 }
3338 case TRACK_nY: /* LOCK Z TRACK -Y */
3339 {
3340 /* Projection of Vector on the plane */
3341 project_v3_v3v3(vec2, vec, cob->matrix[2]);
3342 sub_v3_v3v3(totmat[1], vec, vec2);
3343 normalize_v3(totmat[1]);
3344 negate_v3(totmat[1]);
3345
3346 /* the z axis is fixed */
3347 normalize_v3_v3(totmat[2], cob->matrix[2]);
3348
3349 /* the x axis gets mapped onto a third orthogonal vector */
3350 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
3351 break;
3352 }
3353 default: {
3354 unit_m3(totmat);
3355 break;
3356 }
3357 }
3358 break;
3359 }
3360 default: {
3361 unit_m3(totmat);
3362 break;
3363 }
3364 }
3365 /* Block to keep matrix heading */
3366 copy_m3_m4(tmpmat, cob->matrix);
3367 normalize_m3(tmpmat);
3368 invert_m3_m3(invmat, tmpmat);
3369 mul_m3_m3m3(tmpmat, totmat, invmat);
3370 totmat[0][0] = tmpmat[0][0];
3371 totmat[0][1] = tmpmat[0][1];
3372 totmat[0][2] = tmpmat[0][2];
3373 totmat[1][0] = tmpmat[1][0];
3374 totmat[1][1] = tmpmat[1][1];
3375 totmat[1][2] = tmpmat[1][2];
3376 totmat[2][0] = tmpmat[2][0];
3377 totmat[2][1] = tmpmat[2][1];
3378 totmat[2][2] = tmpmat[2][2];
3379
3380 mdet = determinant_m3(totmat[0][0],
3381 totmat[0][1],
3382 totmat[0][2],
3383 totmat[1][0],
3384 totmat[1][1],
3385 totmat[1][2],
3386 totmat[2][0],
3387 totmat[2][1],
3388 totmat[2][2]);
3389 if (mdet == 0) {
3390 unit_m3(totmat);
3391 }
3392
3393 /* apply out transformation to the object */
3394 mul_m4_m3m4(cob->matrix, totmat, cob->matrix);
3395 }
3396}
3397
3400 /*size*/ sizeof(bLockTrackConstraint),
3401 /*name*/ N_("Locked Track"),
3402 /*struct_name*/ "bLockTrackConstraint",
3403 /*free_data*/ nullptr,
3404 /*id_looper*/ locktrack_id_looper,
3405 /*copy_data*/ nullptr,
3406 /*new_data*/ locktrack_new_data,
3407 /*get_constraint_targets*/ locktrack_get_tars,
3408 /*flush_constraint_targets*/ locktrack_flush_tars,
3409 /*get_target_matrix*/ default_get_tarmat,
3410 /*evaluate_constraint*/ locktrack_evaluate,
3411};
3412
3413/* ---------- Limit Distance Constraint ----------- */
3414
3415static void distlimit_new_data(void *cdata)
3416{
3418
3419 data->dist = 0.0f;
3420}
3421
3422static void distlimit_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
3423{
3424 bDistLimitConstraint *data = static_cast<bDistLimitConstraint *>(con->data);
3425
3426 /* target only */
3427 func(con, (ID **)&data->tar, false, userdata);
3428}
3429
3431{
3432 if (con && list) {
3433 bDistLimitConstraint *data = static_cast<bDistLimitConstraint *>(con->data);
3435
3436 /* standard target-getting macro for single-target constraints */
3437 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
3438
3439 return 1;
3440 }
3441
3442 return 0;
3443}
3444
3445static void distlimit_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
3446{
3447 if (con && list) {
3448 bDistLimitConstraint *data = static_cast<bDistLimitConstraint *>(con->data);
3449 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
3450
3451 /* the following macro is used for all standard single-target constraints */
3452 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
3453 }
3454}
3455
3456static void distlimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
3457{
3458 bDistLimitConstraint *data = static_cast<bDistLimitConstraint *>(con->data);
3459 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
3460
3461 /* only evaluate if there is a target */
3462 if (VALID_CONS_TARGET(ct)) {
3463 float dvec[3], dist, sfac = 1.0f;
3464 short clamp_surf = 0;
3465
3466 /* calculate our current distance from the target */
3467 dist = len_v3v3(cob->matrix[3], ct->matrix[3]);
3468
3469 /* set distance (flag is only set when user demands it) */
3470 if (data->dist == 0) {
3471 data->dist = dist;
3472
3473 /* Write the computed distance back to the master copy if in copy-on-eval evaluation. */
3475
3476 if (orig_con != nullptr) {
3477 bDistLimitConstraint *orig_data = static_cast<bDistLimitConstraint *>(orig_con->data);
3478
3479 orig_data->dist = data->dist;
3480 }
3481 }
3482
3483 /* check if we're which way to clamp from, and calculate interpolation factor (if needed) */
3484 if (data->mode == LIMITDIST_OUTSIDE) {
3485 /* if inside, then move to surface */
3486 if (dist <= data->dist) {
3487 clamp_surf = 1;
3488 if (dist != 0.0f) {
3489 sfac = data->dist / dist;
3490 }
3491 }
3492 /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */
3493 else if (data->flag & LIMITDIST_USESOFT) {
3494 if (dist <= (data->dist + data->soft)) {
3495 /* pass */
3496 }
3497 }
3498 }
3499 else if (data->mode == LIMITDIST_INSIDE) {
3500 /* if outside, then move to surface */
3501 if (dist >= data->dist) {
3502 clamp_surf = 1;
3503 if (dist != 0.0f) {
3504 sfac = data->dist / dist;
3505 }
3506 }
3507 /* if soft-distance is enabled, start fading once owner is dist-soft from the target */
3508 else if (data->flag & LIMITDIST_USESOFT) {
3509 /* FIXME: there's a problem with "jumping" when this kicks in */
3510 if (dist >= (data->dist - data->soft)) {
3511 sfac = float(data->soft * (1.0f - expf(-(dist - data->dist) / data->soft)) + data->dist);
3512 if (dist != 0.0f) {
3513 sfac /= dist;
3514 }
3515
3516 clamp_surf = 1;
3517 }
3518 }
3519 }
3520 else {
3521 if (IS_EQF(dist, data->dist) == 0) {
3522 clamp_surf = 1;
3523 if (dist != 0.0f) {
3524 sfac = data->dist / dist;
3525 }
3526 }
3527 }
3528
3529 /* clamp to 'surface' (i.e. move owner so that dist == data->dist) */
3530 if (clamp_surf) {
3531 /* simply interpolate along line formed by target -> owner */
3532 interp_v3_v3v3(dvec, ct->matrix[3], cob->matrix[3], sfac);
3533
3534 /* copy new vector onto owner */
3535 copy_v3_v3(cob->matrix[3], dvec);
3536 }
3537 }
3538}
3539
3542 /*size*/ sizeof(bDistLimitConstraint),
3543 /*name*/ N_("Limit Distance"),
3544 /*struct_name*/ "bDistLimitConstraint",
3545 /*free_data*/ nullptr,
3546 /*id_looper*/ distlimit_id_looper,
3547 /*copy_data*/ nullptr,
3548 /*new_data*/ distlimit_new_data,
3549 /*get_constraint_targets*/ distlimit_get_tars,
3550 /*flush_constraint_targets*/ distlimit_flush_tars,
3551 /*get_target_matrix*/ default_get_tarmat,
3552 /*evaluate_constraint*/ distlimit_evaluate,
3553};
3554
3555/* ---------- Stretch To ------------ */
3556
3557static void stretchto_new_data(void *cdata)
3558{
3560
3561 data->volmode = 0;
3562 data->plane = SWING_Y;
3563 data->orglength = 0.0;
3564 data->bulge = 1.0;
3565 data->bulge_max = 1.0f;
3566 data->bulge_min = 1.0f;
3567}
3568
3569static void stretchto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
3570{
3571 bStretchToConstraint *data = static_cast<bStretchToConstraint *>(con->data);
3572
3573 /* target only */
3574 func(con, (ID **)&data->tar, false, userdata);
3575}
3576
3578{
3579 if (con && list) {
3580 bStretchToConstraint *data = static_cast<bStretchToConstraint *>(con->data);
3582
3583 /* standard target-getting macro for single-target constraints */
3584 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
3585
3586 return 1;
3587 }
3588
3589 return 0;
3590}
3591
3592static void stretchto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
3593{
3594 if (con && list) {
3595 bStretchToConstraint *data = static_cast<bStretchToConstraint *>(con->data);
3596 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
3597
3598 /* the following macro is used for all standard single-target constraints */
3599 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
3600 }
3601}
3602
3603static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
3604{
3605 bStretchToConstraint *data = static_cast<bStretchToConstraint *>(con->data);
3606 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
3607
3608 /* only evaluate if there is a target */
3609 if (VALID_CONS_TARGET(ct)) {
3610 float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
3611 float dist, bulge;
3612
3613 /* Remove shear if using the Damped Track mode; the other modes
3614 * do it as a side effect, which is relied on by rigs. */
3615 if (data->plane == SWING_Y) {
3616 orthogonalize_m4_stable(cob->matrix, 1, false);
3617 }
3618
3619 /* store scaling before destroying obmat */
3620 normalize_m4_ex(cob->matrix, size);
3621
3622 /* store X orientation before destroying obmat */
3623 copy_v3_v3(xx, cob->matrix[0]);
3624
3625 /* store Z orientation before destroying obmat */
3626 copy_v3_v3(zz, cob->matrix[2]);
3627
3628 /* Compute distance and direction to target. */
3629 sub_v3_v3v3(vec, ct->matrix[3], cob->matrix[3]);
3630
3631 dist = normalize_v3(vec);
3632
3633 /* Only Y constrained object axis scale should be used, to keep same length when scaling it. */
3634 dist /= size[1];
3635
3636 /* data->orglength==0 occurs on first run, and after 'R' button is clicked */
3637 if (data->orglength == 0) {
3638 data->orglength = dist;
3639
3640 /* Write the computed length back to the master copy if in copy-on-eval evaluation. */
3642
3643 if (orig_con != nullptr) {
3644 bStretchToConstraint *orig_data = static_cast<bStretchToConstraint *>(orig_con->data);
3645
3646 orig_data->orglength = data->orglength;
3647 }
3648 }
3649
3650 scale[1] = dist / data->orglength;
3651
3652 bulge = powf(data->orglength / dist, data->bulge);
3653
3654 if (bulge > 1.0f) {
3655 if (data->flag & STRETCHTOCON_USE_BULGE_MAX) {
3656 float bulge_max = max_ff(data->bulge_max, 1.0f);
3657 float hard = min_ff(bulge, bulge_max);
3658
3659 float range = bulge_max - 1.0f;
3660 float scale_fac = (range > 0.0f) ? 1.0f / range : 0.0f;
3661 float soft = 1.0f + range * atanf((bulge - 1.0f) * scale_fac) / float(M_PI_2);
3662
3663 bulge = interpf(soft, hard, data->bulge_smooth);
3664 }
3665 }
3666 if (bulge < 1.0f) {
3667 if (data->flag & STRETCHTOCON_USE_BULGE_MIN) {
3668 float bulge_min = std::clamp(data->bulge_min, 0.0f, 1.0f);
3669 float hard = max_ff(bulge, bulge_min);
3670
3671 float range = 1.0f - bulge_min;
3672 float scale_fac = (range > 0.0f) ? 1.0f / range : 0.0f;
3673 float soft = 1.0f - range * atanf((1.0f - bulge) * scale_fac) / float(M_PI_2);
3674
3675 bulge = interpf(soft, hard, data->bulge_smooth);
3676 }
3677 }
3678
3679 switch (data->volmode) {
3680 /* volume preserving scaling */
3681 case VOLUME_XZ:
3682 scale[0] = sqrtf(bulge);
3683 scale[2] = scale[0];
3684 break;
3685 case VOLUME_X:
3686 scale[0] = bulge;
3687 scale[2] = 1.0;
3688 break;
3689 case VOLUME_Z:
3690 scale[0] = 1.0;
3691 scale[2] = bulge;
3692 break;
3693 /* don't care for volume */
3694 case NO_VOLUME:
3695 scale[0] = 1.0;
3696 scale[2] = 1.0;
3697 break;
3698 default: /* Should not happen, but in case. */
3699 return;
3700 } /* switch (data->volmode) */
3701
3702 /* Compute final scale. */
3703 mul_v3_v3(size, scale);
3704
3705 switch (data->plane) {
3706 case SWING_Y:
3707 /* Point the Y axis using Damped Track math. */
3709 break;
3710 case PLANE_X:
3711 /* New Y aligns object target connection. */
3712 copy_v3_v3(cob->matrix[1], vec);
3713
3714 /* Build new Z vector. */
3715 /* Orthogonal to "new Y" "old X! plane. */
3716 cross_v3_v3v3(orth, xx, vec);
3718
3719 /* New Z. */
3720 copy_v3_v3(cob->matrix[2], orth);
3721
3722 /* We decided to keep X plane. */
3723 cross_v3_v3v3(xx, vec, orth);
3724 normalize_v3_v3(cob->matrix[0], xx);
3725 break;
3726 case PLANE_Z:
3727 /* New Y aligns object target connection. */
3728 copy_v3_v3(cob->matrix[1], vec);
3729
3730 /* Build new X vector. */
3731 /* Orthogonal to "new Y" "old Z! plane. */
3732 cross_v3_v3v3(orth, zz, vec);
3734
3735 /* New X. */
3736 negate_v3_v3(cob->matrix[0], orth);
3737
3738 /* We decided to keep Z. */
3739 cross_v3_v3v3(zz, vec, orth);
3740 normalize_v3_v3(cob->matrix[2], zz);
3741 break;
3742 } /* switch (data->plane) */
3743
3744 rescale_m4(cob->matrix, size);
3745 }
3746}
3747
3750 /*size*/ sizeof(bStretchToConstraint),
3751 /*name*/ N_("Stretch To"),
3752 /*struct_name*/ "bStretchToConstraint",
3753 /*free_data*/ nullptr,
3754 /*id_looper*/ stretchto_id_looper,
3755 /*copy_data*/ nullptr,
3756 /*new_data*/ stretchto_new_data,
3757 /*get_constraint_targets*/ stretchto_get_tars,
3758 /*flush_constraint_targets*/ stretchto_flush_tars,
3759 /*get_target_matrix*/ default_get_tarmat,
3760 /*evaluate_constraint*/ stretchto_evaluate,
3761};
3762
3763/* ---------- Floor ------------ */
3764
3765static void minmax_new_data(void *cdata)
3766{
3767 bMinMaxConstraint *data = (bMinMaxConstraint *)cdata;
3768
3769 data->minmaxflag = TRACK_Z;
3770 data->offset = 0.0f;
3771 data->flag = 0;
3772}
3773
3774static void minmax_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
3775{
3776 bMinMaxConstraint *data = static_cast<bMinMaxConstraint *>(con->data);
3777
3778 /* target only */
3779 func(con, (ID **)&data->tar, false, userdata);
3780}
3781
3782static int minmax_get_tars(bConstraint *con, ListBase *list)
3783{
3784 if (con && list) {
3785 bMinMaxConstraint *data = static_cast<bMinMaxConstraint *>(con->data);
3787
3788 /* standard target-getting macro for single-target constraints */
3789 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
3790
3791 return 1;
3792 }
3793
3794 return 0;
3795}
3796
3797static void minmax_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
3798{
3799 if (con && list) {
3800 bMinMaxConstraint *data = static_cast<bMinMaxConstraint *>(con->data);
3801 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
3802
3803 /* the following macro is used for all standard single-target constraints */
3804 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
3805 }
3806}
3807
3808static void minmax_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
3809{
3810 bMinMaxConstraint *data = static_cast<bMinMaxConstraint *>(con->data);
3811 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
3812
3813 /* only evaluate if there is a target */
3814 if (VALID_CONS_TARGET(ct)) {
3815 float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
3816 float val1, val2;
3817 int index;
3818
3819 copy_m4_m4(obmat, cob->matrix);
3820 copy_m4_m4(tarmat, ct->matrix);
3821
3822 if (data->flag & MINMAX_USEROT) {
3823 /* Take rotation of target into account by doing the transaction in target's local-space. */
3824 invert_m4_m4(imat, tarmat);
3825 mul_m4_m4m4(tmat, imat, obmat);
3826 copy_m4_m4(obmat, tmat);
3827 unit_m4(tarmat);
3828 }
3829
3830 switch (data->minmaxflag) {
3831 case TRACK_Z:
3832 val1 = tarmat[3][2];
3833 val2 = obmat[3][2] - data->offset;
3834 index = 2;
3835 break;
3836 case TRACK_Y:
3837 val1 = tarmat[3][1];
3838 val2 = obmat[3][1] - data->offset;
3839 index = 1;
3840 break;
3841 case TRACK_X:
3842 val1 = tarmat[3][0];
3843 val2 = obmat[3][0] - data->offset;
3844 index = 0;
3845 break;
3846 case TRACK_nZ:
3847 val2 = tarmat[3][2];
3848 val1 = obmat[3][2] - data->offset;
3849 index = 2;
3850 break;
3851 case TRACK_nY:
3852 val2 = tarmat[3][1];
3853 val1 = obmat[3][1] - data->offset;
3854 index = 1;
3855 break;
3856 case TRACK_nX:
3857 val2 = tarmat[3][0];
3858 val1 = obmat[3][0] - data->offset;
3859 index = 0;
3860 break;
3861 default:
3862 return;
3863 }
3864
3865 if (val1 > val2) {
3866 obmat[3][index] = tarmat[3][index] + data->offset;
3867 if (data->flag & MINMAX_USEROT) {
3868 /* Get out of local-space. */
3869 mul_m4_m4m4(tmat, ct->matrix, obmat);
3870 copy_m4_m4(cob->matrix, tmat);
3871 }
3872 else {
3873 copy_v3_v3(cob->matrix[3], obmat[3]);
3874 }
3875 }
3876 }
3877}
3878
3880 /*type*/ CONSTRAINT_TYPE_MINMAX,
3881 /*size*/ sizeof(bMinMaxConstraint),
3882 /*name*/ N_("Floor"),
3883 /*struct_name*/ "bMinMaxConstraint",
3884 /*free_data*/ nullptr,
3885 /*id_looper*/ minmax_id_looper,
3886 /*copy_data*/ nullptr,
3887 /*new_data*/ minmax_new_data,
3888 /*get_constraint_targets*/ minmax_get_tars,
3889 /*flush_constraint_targets*/ minmax_flush_tars,
3890 /*get_target_matrix*/ default_get_tarmat,
3891 /*evaluate_constraint*/ minmax_evaluate,
3892};
3893
3894/* -------- Clamp To ---------- */
3895
3896static void clampto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
3897{
3898 bClampToConstraint *data = static_cast<bClampToConstraint *>(con->data);
3899
3900 /* target only */
3901 func(con, (ID **)&data->tar, false, userdata);
3902}
3903
3905{
3906 if (con && list) {
3907 bClampToConstraint *data = static_cast<bClampToConstraint *>(con->data);
3909
3910 /* Standard target-getting macro for single-target constraints without sub-targets. */
3911 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list);
3912
3913 return 1;
3914 }
3915
3916 return 0;
3917}
3918
3919static void clampto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
3920{
3921 if (con && list) {
3922 bClampToConstraint *data = static_cast<bClampToConstraint *>(con->data);
3923 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
3924
3925 /* the following macro is used for all standard single-target constraints */
3926 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, no_copy);
3927 }
3928}
3929
3930static void clampto_get_tarmat(Depsgraph * /*depsgraph*/,
3931 bConstraint * /*con*/,
3932 bConstraintOb * /*cob*/,
3934 float /*ctime*/)
3935{
3936 /* technically, this isn't really needed for evaluation, but we don't know what else
3937 * might end up calling this...
3938 */
3939 if (ct) {
3940 unit_m4(ct->matrix);
3941 }
3942}
3943
3944static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
3945{
3946 using namespace blender;
3947 bClampToConstraint *data = static_cast<bClampToConstraint *>(con->data);
3948 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
3949
3950 /* only evaluate if there is a target and it is a curve */
3951 if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVES_LEGACY)) {
3952 float obmat[4][4], ownLoc[3];
3953 float curveMin[3], curveMax[3];
3954 float targetMatrix[4][4];
3955
3956 copy_m4_m4(obmat, cob->matrix);
3957 copy_v3_v3(ownLoc, obmat[3]);
3958
3959 unit_m4(targetMatrix);
3960 INIT_MINMAX(curveMin, curveMax);
3961 if (const std::optional<Bounds<float3>> bounds = BKE_object_boundbox_get(ct->tar)) {
3962 copy_v3_v3(curveMin, bounds->min);
3963 copy_v3_v3(curveMax, bounds->max);
3964 }
3965
3966 /* Get target-matrix. */
3967 if (data->tar->runtime->curve_cache && data->tar->runtime->curve_cache->anim_path_accum_length)
3968 {
3969 float vec[4], totmat[4][4];
3970 float curvetime;
3971 short clamp_axis;
3972
3973 /* find best position on curve */
3974 /* 1. determine which axis to sample on? */
3975 if (data->flag == CLAMPTO_AUTO) {
3976 float size[3];
3977 sub_v3_v3v3(size, curveMax, curveMin);
3978
3979 /* find axis along which the bounding box has the greatest
3980 * extent. Otherwise, default to the x-axis, as that is quite
3981 * frequently used.
3982 */
3983 if ((size[2] > size[0]) && (size[2] > size[1])) {
3984 clamp_axis = CLAMPTO_Z - 1;
3985 }
3986 else if ((size[1] > size[0]) && (size[1] > size[2])) {
3987 clamp_axis = CLAMPTO_Y - 1;
3988 }
3989 else {
3990 clamp_axis = CLAMPTO_X - 1;
3991 }
3992 }
3993 else {
3994 clamp_axis = data->flag - 1;
3995 }
3996
3997 /* 2. determine position relative to curve on a 0-1 scale based on bounding box */
3998 if (data->flag2 & CLAMPTO_CYCLIC) {
3999 /* cyclic, so offset within relative bounding box is used */
4000 float len = (curveMax[clamp_axis] - curveMin[clamp_axis]);
4001 float offset;
4002
4003 /* check to make sure len is not so close to zero that it'll cause errors */
4004 if (IS_EQF(len, 0.0f) == false) {
4005 /* find bounding-box range where target is located */
4006 if (ownLoc[clamp_axis] < curveMin[clamp_axis]) {
4007 /* bounding-box range is before */
4008 offset = curveMin[clamp_axis] -
4009 ceilf((curveMin[clamp_axis] - ownLoc[clamp_axis]) / len) * len;
4010
4011 /* Now, we calculate as per normal,
4012 * except using offset instead of curveMin[clamp_axis]. */
4013 curvetime = (ownLoc[clamp_axis] - offset) / (len);
4014 }
4015 else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) {
4016 /* bounding-box range is after */
4017 offset = curveMax[clamp_axis] +
4018 int((ownLoc[clamp_axis] - curveMax[clamp_axis]) / len) * len;
4019
4020 /* Now, we calculate as per normal,
4021 * except using offset instead of curveMax[clamp_axis]. */
4022 curvetime = (ownLoc[clamp_axis] - offset) / (len);
4023 }
4024 else {
4025 /* as the location falls within bounds, just calculate */
4026 curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len);
4027 }
4028 }
4029 else {
4030 /* as length is close to zero, curvetime by default should be 0 (i.e. the start) */
4031 curvetime = 0.0f;
4032 }
4033 }
4034 else {
4035 /* no cyclic, so position is clamped to within the bounding box */
4036 if (ownLoc[clamp_axis] <= curveMin[clamp_axis]) {
4037 curvetime = 0.0f;
4038 }
4039 else if (ownLoc[clamp_axis] >= curveMax[clamp_axis]) {
4040 curvetime = 1.0f;
4041 }
4042 else if (IS_EQF((curveMax[clamp_axis] - curveMin[clamp_axis]), 0.0f) == false) {
4043 curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) /
4044 (curveMax[clamp_axis] - curveMin[clamp_axis]);
4045 }
4046 else {
4047 curvetime = 0.0f;
4048 }
4049 }
4050
4051 /* 3. position on curve */
4052 if (BKE_where_on_path(ct->tar, curvetime, vec, nullptr, nullptr, nullptr, nullptr)) {
4053 unit_m4(totmat);
4054 copy_v3_v3(totmat[3], vec);
4055
4056 mul_m4_m4m4(targetMatrix, ct->tar->object_to_world().ptr(), totmat);
4057 }
4058 }
4059
4060 /* obtain final object position */
4061 copy_v3_v3(cob->matrix[3], targetMatrix[3]);
4062 }
4063}
4064
4066 /*type*/ CONSTRAINT_TYPE_CLAMPTO,
4067 /*size*/ sizeof(bClampToConstraint),
4068 /*name*/ N_("Clamp To"),
4069 /*struct_name*/ "bClampToConstraint",
4070 /*free_data*/ nullptr,
4071 /*id_looper*/ clampto_id_looper,
4072 /*copy_data*/ nullptr,
4073 /*new_data*/ nullptr,
4074 /*get_constraint_targets*/ clampto_get_tars,
4075 /*flush_constraint_targets*/ clampto_flush_tars,
4076 /*get_target_matrix*/ clampto_get_tarmat,
4077 /*evaluate_constraint*/ clampto_evaluate,
4078};
4079
4080/* ---------- Transform Constraint ----------- */
4081
4082static void transform_new_data(void *cdata)
4083{
4085
4086 data->map[0] = 0;
4087 data->map[1] = 1;
4088 data->map[2] = 2;
4089
4090 for (int i = 0; i < 3; i++) {
4091 data->from_min_scale[i] = data->from_max_scale[i] = 1.0f;
4092 data->to_min_scale[i] = data->to_max_scale[i] = 1.0f;
4093 }
4094}
4095
4096static void transform_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
4097{
4098 bTransformConstraint *data = static_cast<bTransformConstraint *>(con->data);
4099
4100 /* target only */
4101 func(con, (ID **)&data->tar, false, userdata);
4102}
4103
4105{
4106 if (con && list) {
4107 bTransformConstraint *data = static_cast<bTransformConstraint *>(con->data);
4109
4110 /* standard target-getting macro for single-target constraints */
4111 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
4112
4113 return 1;
4114 }
4115
4116 return 0;
4117}
4118
4119static void transform_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
4120{
4121 if (con && list) {
4122 bTransformConstraint *data = static_cast<bTransformConstraint *>(con->data);
4123 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
4124
4125 /* the following macro is used for all standard single-target constraints */
4126 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
4127 }
4128}
4129
4130static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
4131{
4132 bTransformConstraint *data = static_cast<bTransformConstraint *>(con->data);
4133 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
4134
4135 /* only evaluate if there is a target */
4136 if (VALID_CONS_TARGET(ct)) {
4137 float *from_min, *from_max, *to_min, *to_max;
4138 float loc[3], rot[3][3], oldeul[3], size[3];
4139 float newloc[3], newrot[3][3], neweul[3], newsize[3];
4140 float dbuf[4], sval[3];
4141 float *const dvec = dbuf + 1;
4142
4143 /* obtain target effect */
4144 switch (data->from) {
4145 case TRANS_SCALE:
4146 mat4_to_size(dvec, ct->matrix);
4147
4148 if (is_negative_m4(ct->matrix)) {
4149 /* Bug-fix #27886: (this is a limitation that riggers will have to live with for now).
4150 * We can't be sure which axis/axes are negative,
4151 * though we know that something is negative.
4152 * Assume we don't care about negativity of separate axes. */
4153 negate_v3(dvec);
4154 }
4155 from_min = data->from_min_scale;
4156 from_max = data->from_max_scale;
4157 break;
4158 case TRANS_ROTATION:
4160 ct->matrix, cob->rotOrder, data->from_rotation_mode, -1, true, dbuf);
4161 from_min = data->from_min_rot;
4162 from_max = data->from_max_rot;
4163 break;
4164 case TRANS_LOCATION:
4165 default:
4166 copy_v3_v3(dvec, ct->matrix[3]);
4167 from_min = data->from_min;
4168 from_max = data->from_max;
4169 break;
4170 }
4171
4172 /* Select the output Euler rotation order, defaulting to the owner. */
4173 short rot_order = cob->rotOrder;
4174
4175 if (data->to == TRANS_ROTATION && data->to_euler_order != CONSTRAINT_EULER_AUTO) {
4176 rot_order = data->to_euler_order;
4177 }
4178
4179 /* extract components of owner's matrix */
4180 mat4_to_loc_rot_size(loc, rot, size, cob->matrix);
4181
4182 /* determine where in range current transforms lie */
4183 if (data->expo) {
4184 for (int i = 0; i < 3; i++) {
4185 if (from_max[i] - from_min[i]) {
4186 sval[i] = (dvec[i] - from_min[i]) / (from_max[i] - from_min[i]);
4187 }
4188 else {
4189 sval[i] = 0.0f;
4190 }
4191 }
4192 }
4193 else {
4194 /* clamp transforms out of range */
4195 for (int i = 0; i < 3; i++) {
4196 CLAMP(dvec[i], from_min[i], from_max[i]);
4197 if (from_max[i] - from_min[i]) {
4198 sval[i] = (dvec[i] - from_min[i]) / (from_max[i] - from_min[i]);
4199 }
4200 else {
4201 sval[i] = 0.0f;
4202 }
4203 }
4204 }
4205
4206 /* apply transforms */
4207 switch (data->to) {
4208 case TRANS_SCALE:
4209 to_min = data->to_min_scale;
4210 to_max = data->to_max_scale;
4211 for (int i = 0; i < 3; i++) {
4212 newsize[i] = to_min[i] + (sval[int(data->map[i])] * (to_max[i] - to_min[i]));
4213 }
4214 switch (data->mix_mode_scale) {
4216 mul_v3_v3(size, newsize);
4217 break;
4219 default:
4220 copy_v3_v3(size, newsize);
4221 break;
4222 }
4223 break;
4224 case TRANS_ROTATION:
4225 to_min = data->to_min_rot;
4226 to_max = data->to_max_rot;
4227 for (int i = 0; i < 3; i++) {
4228 neweul[i] = to_min[i] + (sval[int(data->map[i])] * (to_max[i] - to_min[i]));
4229 }
4230 switch (data->mix_mode_rot) {
4232 eulO_to_mat3(rot, neweul, rot_order);
4233 break;
4235 eulO_to_mat3(newrot, neweul, rot_order);
4236 mul_m3_m3m3(rot, newrot, rot);
4237 break;
4238 case TRANS_MIXROT_AFTER:
4239 eulO_to_mat3(newrot, neweul, rot_order);
4240 mul_m3_m3m3(rot, rot, newrot);
4241 break;
4242 case TRANS_MIXROT_ADD:
4243 default:
4244 mat3_to_eulO(oldeul, rot_order, rot);
4245 add_v3_v3(neweul, oldeul);
4246 eulO_to_mat3(rot, neweul, rot_order);
4247 break;
4248 }
4249 break;
4250 case TRANS_LOCATION:
4251 default:
4252 to_min = data->to_min;
4253 to_max = data->to_max;
4254 for (int i = 0; i < 3; i++) {
4255 newloc[i] = (to_min[i] + (sval[int(data->map[i])] * (to_max[i] - to_min[i])));
4256 }
4257 switch (data->mix_mode_loc) {
4259 copy_v3_v3(loc, newloc);
4260 break;
4261 case TRANS_MIXLOC_ADD:
4262 default:
4263 add_v3_v3(loc, newloc);
4264 break;
4265 }
4266 break;
4267 }
4268
4269 /* apply to matrix */
4270 loc_rot_size_to_mat4(cob->matrix, loc, rot, size);
4271 }
4272}
4273
4276 /*size*/ sizeof(bTransformConstraint),
4277 /*name*/ N_("Transformation"),
4278 /*struct_name*/ "bTransformConstraint",
4279 /*free_data*/ nullptr,
4280 /*id_looper*/ transform_id_looper,
4281 /*copy_data*/ nullptr,
4282 /*new_data*/ transform_new_data,
4283 /*get_constraint_targets*/ transform_get_tars,
4284 /*flush_constraint_targets*/ transform_flush_tars,
4285 /*get_target_matrix*/ default_get_tarmat,
4286 /*evaluate_constraint*/ transform_evaluate,
4287};
4288
4289/* ---------- Shrinkwrap Constraint ----------- */
4290
4291static void shrinkwrap_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
4292{
4293 bShrinkwrapConstraint *data = static_cast<bShrinkwrapConstraint *>(con->data);
4294
4295 /* target only */
4296 func(con, (ID **)&data->target, false, userdata);
4297}
4298
4299static void shrinkwrap_new_data(void *cdata)
4300{
4302
4303 data->projAxis = OB_POSZ;
4304 data->projAxisSpace = CONSTRAINT_SPACE_LOCAL;
4305}
4306
4308{
4309 if (con && list) {
4310 bShrinkwrapConstraint *data = static_cast<bShrinkwrapConstraint *>(con->data);
4312
4313 SINGLETARGETNS_GET_TARS(con, data->target, ct, list);
4314
4315 return 1;
4316 }
4317
4318 return 0;
4319}
4320
4321static void shrinkwrap_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
4322{
4323 if (con && list) {
4324 bShrinkwrapConstraint *data = static_cast<bShrinkwrapConstraint *>(con->data);
4325 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
4326
4327 SINGLETARGETNS_FLUSH_TARS(con, data->target, ct, list, no_copy);
4328 }
4329}
4330
4331static void shrinkwrap_get_tarmat(Depsgraph * /*depsgraph*/,
4332 bConstraint *con,
4333 bConstraintOb *cob,
4335 float /*ctime*/)
4336{
4338
4339 if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH)) {
4340
4341 bool fail = false;
4342 float co[3] = {0.0f, 0.0f, 0.0f};
4343 bool track_normal = false;
4344 float track_no[3] = {0.0f, 0.0f, 0.0f};
4345
4347 Mesh *target_eval = BKE_object_get_evaluated_mesh(ct->tar);
4348
4349 copy_m4_m4(ct->matrix, cob->matrix);
4350
4351 bool do_track_normal = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
4353
4355 &tree, target_eval, scon->shrinkType, scon->shrinkMode, do_track_normal))
4356 {
4357 BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->object_to_world().ptr());
4358
4359 switch (scon->shrinkType) {
4363 BVHTreeNearest nearest;
4364
4365 nearest.index = -1;
4366 nearest.dist_sq = FLT_MAX;
4367
4368 BLI_space_transform_apply(&transform, co);
4369
4371
4372 if (nearest.index < 0) {
4373 fail = true;
4374 break;
4375 }
4376
4378 if (do_track_normal) {
4379 track_normal = true;
4381 &tree, nullptr, nearest.index, nearest.co, nearest.no, track_no);
4382 BLI_space_transform_invert_normal(&transform, track_no);
4383 }
4384
4386 nullptr,
4387 scon->shrinkMode,
4388 nearest.index,
4389 nearest.co,
4390 nearest.no,
4391 scon->dist,
4392 co,
4393 co);
4394 }
4395 else {
4396 const float dist = len_v3v3(co, nearest.co);
4397
4398 if (dist != 0.0f) {
4400 co, co, nearest.co, (dist - scon->dist) / dist); /* linear interpolation */
4401 }
4402 }
4403
4404 BLI_space_transform_invert(&transform, co);
4405 break;
4406 }
4408 BVHTreeRayHit hit;
4409
4410 float mat[4][4];
4411 float no[3] = {0.0f, 0.0f, 0.0f};
4412
4413 /* TODO: should use FLT_MAX.. but normal projection doesn't yet supports it. */
4414 hit.index = -1;
4415 hit.dist = (scon->projLimit == 0.0f) ? BVH_RAYCAST_DIST_MAX : scon->projLimit;
4416
4417 switch (scon->projAxis) {
4418 case OB_POSX:
4419 case OB_POSY:
4420 case OB_POSZ:
4421 no[scon->projAxis - OB_POSX] = 1.0f;
4422 break;
4423 case OB_NEGX:
4424 case OB_NEGY:
4425 case OB_NEGZ:
4426 no[scon->projAxis - OB_NEGX] = -1.0f;
4427 break;
4428 }
4429
4430 /* Transform normal into requested space */
4431 /* Note that in this specific case, we need to keep scaling in non-parented 'local2world'
4432 * object case, because SpaceTransform also takes it into account when handling normals.
4433 * See #42447. */
4434 unit_m4(mat);
4436 cob->ob, cob->pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true);
4437 invert_m4(mat);
4438 mul_mat3_m4_v3(mat, no);
4439
4440 if (normalize_v3(no) < FLT_EPSILON) {
4441 fail = true;
4442 break;
4443 }
4444
4445 char cull_mode = scon->flag & CON_SHRINKWRAP_PROJECT_CULL_MASK;
4446
4447 BKE_shrinkwrap_project_normal(cull_mode, co, no, 0.0f, &transform, &tree, &hit);
4448
4450 float inv_no[3];
4451 negate_v3_v3(inv_no, no);
4452
4453 if ((scon->flag & CON_SHRINKWRAP_PROJECT_INVERT_CULL) && (cull_mode != 0)) {
4455 }
4456
4457 BKE_shrinkwrap_project_normal(cull_mode, co, inv_no, 0.0f, &transform, &tree, &hit);
4458 }
4459
4460 if (hit.index < 0) {
4461 fail = true;
4462 break;
4463 }
4464
4465 if (do_track_normal) {
4466 track_normal = true;
4468 &tree, &transform, hit.index, hit.co, hit.no, track_no);
4469 }
4470
4472 &tree, &transform, scon->shrinkMode, hit.index, hit.co, hit.no, scon->dist, co, co);
4473 break;
4474 }
4475 }
4476
4478
4479 if (fail == true) {
4480 /* Don't move the point */
4481 zero_v3(co);
4482 }
4483
4484 /* co is in local object coordinates, change it to global and update target position */
4485 mul_m4_v3(cob->matrix, co);
4486 copy_v3_v3(ct->matrix[3], co);
4487
4488 if (track_normal) {
4489 mul_mat3_m4_v3(cob->matrix, track_no);
4490 damptrack_do_transform(ct->matrix, track_no, scon->trackAxis);
4491 }
4492 }
4493 }
4494}
4495
4496static void shrinkwrap_evaluate(bConstraint * /*con*/, bConstraintOb *cob, ListBase *targets)
4497{
4498 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
4499
4500 /* only evaluate if there is a target */
4501 if (VALID_CONS_TARGET(ct)) {
4502 copy_m4_m4(cob->matrix, ct->matrix);
4503 }
4504}
4505
4508 /*size*/ sizeof(bShrinkwrapConstraint),
4509 /*name*/ N_("Shrinkwrap"),
4510 /*struct_name*/ "bShrinkwrapConstraint",
4511 /*free_data*/ nullptr,
4512 /*id_looper*/ shrinkwrap_id_looper,
4513 /*copy_data*/ nullptr,
4514 /*new_data*/ shrinkwrap_new_data,
4515 /*get_constraint_targets*/ shrinkwrap_get_tars,
4516 /*flush_constraint_targets*/ shrinkwrap_flush_tars,
4517 /*get_target_matrix*/ shrinkwrap_get_tarmat,
4518 /*evaluate_constraint*/ shrinkwrap_evaluate,
4519};
4520
4521/* --------- Damped Track ---------- */
4522
4523static void damptrack_new_data(void *cdata)
4524{
4526
4527 data->trackflag = TRACK_Y;
4528}
4529
4530static void damptrack_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
4531{
4532 bDampTrackConstraint *data = static_cast<bDampTrackConstraint *>(con->data);
4533
4534 /* target only */
4535 func(con, (ID **)&data->tar, false, userdata);
4536}
4537
4539{
4540 if (con && list) {
4541 bDampTrackConstraint *data = static_cast<bDampTrackConstraint *>(con->data);
4543
4544 /* the following macro is used for all standard single-target constraints */
4545 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
4546
4547 return 1;
4548 }
4549
4550 return 0;
4551}
4552
4553static void damptrack_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
4554{
4555 if (con && list) {
4556 bDampTrackConstraint *data = static_cast<bDampTrackConstraint *>(con->data);
4557 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
4558
4559 /* the following macro is used for all standard single-target constraints */
4560 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
4561 }
4562}
4563
4564/* array of direction vectors for the tracking flags */
4565static const float track_dir_vecs[6][3] = {
4566 {+1, 0, 0},
4567 {0, +1, 0},
4568 {0, 0, +1}, /* TRACK_X, TRACK_Y, TRACK_Z */
4569 {-1, 0, 0},
4570 {0, -1, 0},
4571 {0, 0, -1} /* TRACK_NX, TRACK_NY, TRACK_NZ */
4572};
4573
4574static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
4575{
4576 bDampTrackConstraint *data = static_cast<bDampTrackConstraint *>(con->data);
4577 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
4578
4579 if (VALID_CONS_TARGET(ct)) {
4580 float tarvec[3];
4581
4582 /* find the (unit) direction vector going from the owner to the target */
4583 sub_v3_v3v3(tarvec, ct->matrix[3], cob->matrix[3]);
4584
4585 damptrack_do_transform(cob->matrix, tarvec, data->trackflag);
4586 }
4587}
4588
4589static void damptrack_do_transform(float matrix[4][4], const float tarvec_in[3], int track_axis)
4590{
4591 /* find the (unit) direction vector going from the owner to the target */
4592 float tarvec[3];
4593
4594 if (normalize_v3_v3(tarvec, tarvec_in) != 0.0f) {
4595 float obvec[3], obloc[3];
4596 float raxis[3], rangle;
4597 float rmat[3][3], tmat[4][4];
4598
4599 /* find the (unit) direction that the axis we're interested in currently points
4600 * - mul_mat3_m4_v3() only takes the 3x3 (rotation+scaling) components of the 4x4 matrix
4601 * - the normalization step at the end should take care of any unwanted scaling
4602 * left over in the 3x3 matrix we used
4603 */
4604 copy_v3_v3(obvec, track_dir_vecs[track_axis]);
4605 mul_mat3_m4_v3(matrix, obvec);
4606
4607 if (normalize_v3(obvec) == 0.0f) {
4608 /* exceptional case - just use the track vector as appropriate */
4609 copy_v3_v3(obvec, track_dir_vecs[track_axis]);
4610 }
4611
4612 copy_v3_v3(obloc, matrix[3]);
4613
4614 /* determine the axis-angle rotation, which represents the smallest possible rotation
4615 * between the two rotation vectors (i.e. the 'damping' referred to in the name)
4616 * - we take this to be the rotation around the normal axis/vector to the plane defined
4617 * by the current and destination vectors, which will 'map' the current axis to the
4618 * destination vector
4619 * - the min/max wrappers around (obvec . tarvec) result (stored temporarily in rangle)
4620 * are used to ensure that the smallest angle is chosen
4621 */
4622 cross_v3_v3v3_hi_prec(raxis, obvec, tarvec);
4623
4624 rangle = dot_v3v3(obvec, tarvec);
4625 rangle = acosf(max_ff(-1.0f, min_ff(1.0f, rangle)));
4626
4627 /* construct rotation matrix from the axis-angle rotation found above
4628 * - this call takes care to make sure that the axis provided is a unit vector first
4629 */
4630 float norm = normalize_v3(raxis);
4631
4632 if (norm < FLT_EPSILON) {
4633 /* if dot product is nonzero, while cross is zero, we have two opposite vectors!
4634 * - this is an ambiguity in the math that needs to be resolved arbitrarily,
4635 * or there will be a case where damped track strangely does nothing
4636 * - to do that, rotate around a different local axis
4637 */
4638 float tmpvec[3];
4639
4640 if (fabsf(rangle) < M_PI - 0.01f) {
4641 return;
4642 }
4643
4644 rangle = M_PI;
4645 copy_v3_v3(tmpvec, track_dir_vecs[(track_axis + 1) % 6]);
4646 mul_mat3_m4_v3(matrix, tmpvec);
4647 cross_v3_v3v3(raxis, obvec, tmpvec);
4648
4649 if (normalize_v3(raxis) == 0.0f) {
4650 return;
4651 }
4652 }
4653 else if (norm < 0.1f) {
4654 /* Near 0 and Pi `arcsin` has way better precision than `arccos`. */
4655 rangle = (rangle > M_PI_2) ? M_PI - asinf(norm) : asinf(norm);
4656 }
4657
4658 axis_angle_normalized_to_mat3(rmat, raxis, rangle);
4659
4660 /* rotate the owner in the way defined by this rotation matrix, then reapply the location since
4661 * we may have destroyed that in the process of multiplying the matrix
4662 */
4663 unit_m4(tmat);
4664 mul_m4_m3m4(tmat, rmat, matrix); /* m1, m3, m2 */
4665
4666 copy_m4_m4(matrix, tmat);
4667 copy_v3_v3(matrix[3], obloc);
4668 }
4669}
4670
4673 /*size*/ sizeof(bDampTrackConstraint),
4674 /*name*/ N_("Damped Track"),
4675 /*struct_name*/ "bDampTrackConstraint",
4676 /*free_data*/ nullptr,
4677 /*id_looper*/ damptrack_id_looper,
4678 /*copy_data*/ nullptr,
4679 /*new_data*/ damptrack_new_data,
4680 /*get_constraint_targets*/ damptrack_get_tars,
4681 /*flush_constraint_targets*/ damptrack_flush_tars,
4682 /*get_target_matrix*/ default_get_tarmat,
4683 /*evaluate_constraint*/ damptrack_evaluate,
4684};
4685
4686/* ----------- Spline IK ------------ */
4687
4689{
4690 bSplineIKConstraint *data = static_cast<bSplineIKConstraint *>(con->data);
4691
4692 /* binding array */
4693 MEM_SAFE_FREE(data->points);
4694}
4695
4696static void splineik_copy(bConstraint *con, bConstraint *srccon)
4697{
4698 bSplineIKConstraint *src = static_cast<bSplineIKConstraint *>(srccon->data);
4699 bSplineIKConstraint *dst = static_cast<bSplineIKConstraint *>(con->data);
4700
4701 /* copy the binding array */
4702 dst->points = static_cast<float *>(MEM_dupallocN(src->points));
4703}
4704
4705static void splineik_new_data(void *cdata)
4706{
4708
4709 data->chainlen = 1;
4710 data->bulge = 1.0;
4711 data->bulge_max = 1.0f;
4712 data->bulge_min = 1.0f;
4713
4714 data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE;
4716}
4717
4718static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
4719{
4720 bSplineIKConstraint *data = static_cast<bSplineIKConstraint *>(con->data);
4721
4722 /* target only */
4723 func(con, (ID **)&data->tar, false, userdata);
4724}
4725
4727{
4728 if (con && list) {
4729 bSplineIKConstraint *data = static_cast<bSplineIKConstraint *>(con->data);
4731
4732 /* Standard target-getting macro for single-target constraints without sub-targets. */
4733 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list);
4734
4735 return 1;
4736 }
4737
4738 return 0;
4739}
4740
4741static void splineik_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
4742{
4743 if (con && list) {
4744 bSplineIKConstraint *data = static_cast<bSplineIKConstraint *>(con->data);
4745 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
4746
4747 /* the following macro is used for all standard single-target constraints */
4748 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, no_copy);
4749 }
4750}
4751
4752static void splineik_get_tarmat(Depsgraph * /*depsgraph*/,
4753 bConstraint * /*con*/,
4754 bConstraintOb * /*cob*/,
4756 float /*ctime*/)
4757{
4758 /* technically, this isn't really needed for evaluation, but we don't know what else
4759 * might end up calling this...
4760 */
4761 if (ct) {
4762 unit_m4(ct->matrix);
4763 }
4764}
4765
4767 /*type*/ CONSTRAINT_TYPE_SPLINEIK,
4768 /*size*/ sizeof(bSplineIKConstraint),
4769 /*name*/ N_("Spline IK"),
4770 /*struct_name*/ "bSplineIKConstraint",
4771 /*free_data*/ splineik_free,
4772 /*id_looper*/ splineik_id_looper,
4773 /*copy_data*/ splineik_copy,
4774 /*new_data*/ splineik_new_data,
4775 /*get_constraint_targets*/ splineik_get_tars,
4776 /*flush_constraint_targets*/ splineik_flush_tars,
4777 /*get_target_matrix*/ splineik_get_tarmat,
4778 /*evaluate_constraint*/ nullptr,
4779};
4780
4781/* ----------- Pivot ------------- */
4782
4783static void pivotcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
4784{
4785 bPivotConstraint *data = static_cast<bPivotConstraint *>(con->data);
4786
4787 /* target only */
4788 func(con, (ID **)&data->tar, false, userdata);
4789}
4790
4792{
4793 if (con && list) {
4794 bPivotConstraint *data = static_cast<bPivotConstraint *>(con->data);
4796
4797 /* standard target-getting macro for single-target constraints */
4798 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list);
4799
4800 return 1;
4801 }
4802
4803 return 0;
4804}
4805
4806static void pivotcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
4807{
4808 if (con && list) {
4809 bPivotConstraint *data = static_cast<bPivotConstraint *>(con->data);
4810 bConstraintTarget *ct = static_cast<bConstraintTarget *>(list->first);
4811
4812 /* the following macro is used for all standard single-target constraints */
4813 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy);
4814 }
4815}
4816
4817static void pivotcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
4818{
4819 bPivotConstraint *data = static_cast<bPivotConstraint *>(con->data);
4820 bConstraintTarget *ct = static_cast<bConstraintTarget *>(targets->first);
4821
4822 float pivot[3], vec[3];
4823 float rotMat[3][3];
4824
4825 /* pivot correction */
4826 float axis[3], angle;
4827
4828 const int rot_axis = std::clamp(
4829 int(data->rotAxis), int(PIVOTCON_AXIS_NONE), int(PIVOTCON_AXIS_Z));
4830
4831 /* firstly, check if pivoting should take place based on the current rotation */
4832 if (rot_axis != PIVOTCON_AXIS_NONE) {
4833
4834 float rot[3];
4835
4836 /* extract euler-rotation of target */
4837 mat4_to_eulO(rot, cob->rotOrder, cob->matrix);
4838
4839 /* check which range might be violated */
4840 if (rot_axis < PIVOTCON_AXIS_X) {
4841 /* Negative rotations (`rot_axis = 0 -> 2`). */
4842 if (rot[rot_axis] > 0.0f) {
4843 return;
4844 }
4845 }
4846 else {
4847 /* Positive rotations (`rot_axis = 3 -> 5`). */
4848 if (rot[rot_axis - PIVOTCON_AXIS_X] < 0.0f) {
4849 return;
4850 }
4851 }
4852 }
4853
4854 /* Find the pivot-point to use. */
4855 if (VALID_CONS_TARGET(ct)) {
4856 /* apply offset to target location */
4857 add_v3_v3v3(pivot, ct->matrix[3], data->offset);
4858 }
4859 else {
4860 /* no targets to worry about... */
4861 if ((data->flag & PIVOTCON_FLAG_OFFSET_ABS) == 0) {
4862 /* offset is relative to owner */
4863 add_v3_v3v3(pivot, cob->matrix[3], data->offset);
4864 }
4865 else {
4866 /* directly use the 'offset' specified as an absolute position instead */
4867 copy_v3_v3(pivot, data->offset);
4868 }
4869 }
4870
4871 /* get rotation matrix representing the rotation of the owner */
4872 /* TODO: perhaps we might want to include scaling based on the pivot too? */
4873 copy_m3_m4(rotMat, cob->matrix);
4874 normalize_m3(rotMat);
4875
4876 /* correct the pivot by the rotation axis otherwise the pivot translates when it shouldn't */
4877 mat3_normalized_to_axis_angle(axis, &angle, rotMat);
4878 if (angle) {
4879 float dvec[3];
4880 sub_v3_v3v3(vec, pivot, cob->matrix[3]);
4881 project_v3_v3v3(dvec, vec, axis);
4882 sub_v3_v3(pivot, dvec);
4883 }
4884
4885 /* perform the pivoting... */
4886 /* 1. take the vector from owner to the pivot */
4887 sub_v3_v3v3(vec, cob->matrix[3], pivot);
4888 /* 2. rotate this vector by the rotation of the object... */
4889 mul_m3_v3(rotMat, vec);
4890 /* 3. make the rotation in terms of the pivot now */
4891 add_v3_v3v3(cob->matrix[3], pivot, vec);
4892}
4893
4895 /*type*/ CONSTRAINT_TYPE_PIVOT,
4896 /*size*/ sizeof(bPivotConstraint),
4897 /*name*/ N_("Pivot"),
4898 /*struct_name*/ "bPivotConstraint",
4899 /*free_data*/ nullptr,
4900 /*id_looper*/ pivotcon_id_looper,
4901 /*copy_data*/ nullptr,
4902 /*new_data*/ nullptr,
4903 /* XXX: might be needed to get 'normal' pivot behavior. */
4904 /*get_constraint_targets*/ pivotcon_get_tars,
4905 /*flush_constraint_targets*/ pivotcon_flush_tars,
4906 /*get_target_matrix*/ default_get_tarmat,
4907 /*evaluate_constraint*/ pivotcon_evaluate,
4908};
4909
4910/* ----------- Follow Track ------------- */
4911
4912static void followtrack_new_data(void *cdata)
4913{
4915
4916 data->clip = nullptr;
4918}
4919
4920static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
4921{
4922 bFollowTrackConstraint *data = static_cast<bFollowTrackConstraint *>(con->data);
4923
4924 func(con, (ID **)&data->clip, true, userdata);
4925 func(con, (ID **)&data->camera, false, userdata);
4926 func(con, (ID **)&data->depth_ob, false, userdata);
4927}
4928
4930{
4931 bFollowTrackConstraint *data = static_cast<bFollowTrackConstraint *>(con->data);
4932
4933 if (data->flag & FOLLOWTRACK_ACTIVECLIP) {
4934 Scene *scene = cob->scene;
4935 return scene->clip;
4936 }
4937
4938 return data->clip;
4939}
4940
4942{
4943 MovieClip *clip = followtrack_tracking_clip_get(con, cob);
4944 MovieTracking *tracking = &clip->tracking;
4945 bFollowTrackConstraint *data = static_cast<bFollowTrackConstraint *>(con->data);
4946
4947 if (data->object[0]) {
4948 return BKE_tracking_object_get_named(tracking, data->object);
4949 }
4950 return BKE_tracking_object_get_camera(tracking);
4951}
4952
4954{
4955 bFollowTrackConstraint *data = static_cast<bFollowTrackConstraint *>(con->data);
4956
4957 if (data->camera == nullptr) {
4958 Scene *scene = cob->scene;
4959 return scene->camera;
4960 }
4961
4962 return data->camera;
4963}
4964
4983
4985 bConstraint *con,
4986 bConstraintOb *cob)
4987{
4988 bFollowTrackConstraint *data = static_cast<bFollowTrackConstraint *>(con->data);
4989
4990 context->flag = data->flag;
4991 context->frame_method = data->frame_method;
4992
4993 context->depsgraph = cob->depsgraph;
4994 context->scene = cob->scene;
4995
4996 context->clip = followtrack_tracking_clip_get(con, cob);
4997 context->camera_object = followtrack_camera_object_get(con, cob);
4998 if (context->clip == nullptr || context->camera_object == nullptr) {
4999 return false;
5000 }
5001 context->depth_object = data->depth_ob;
5002
5003 context->tracking = &context->clip->tracking;
5004 context->tracking_object = followtrack_tracking_object_get(con, cob);
5005 if (context->tracking_object == nullptr) {
5006 return false;
5007 }
5008
5009 context->track = BKE_tracking_object_find_track_with_name(context->tracking_object, data->track);
5010 if (context->track == nullptr) {
5011 return false;
5012 }
5013
5014 context->depsgraph_time = DEG_get_ctime(context->depsgraph);
5015 context->clip_frame = BKE_movieclip_remap_scene_to_clip_frame(context->clip,
5016 context->depsgraph_time);
5017
5018 return true;
5019}
5020
5022 bConstraintOb *cob)
5023{
5024 Object *camera_object = context->camera_object;
5025 MovieTracking *tracking = context->tracking;
5026 MovieTrackingTrack *track = context->track;
5027 MovieTrackingObject *tracking_object = context->tracking_object;
5028
5029 /* Matrix of the object which is being solved prior to this constraint. */
5030 float obmat[4][4];
5031 copy_m4_m4(obmat, cob->matrix);
5032
5033 /* Object matrix of the camera. */
5034 float camera_obmat[4][4];
5035 copy_m4_m4(camera_obmat, camera_object->object_to_world().ptr());
5036
5037 /* Calculate inverted matrix of the solved camera at the current time. */
5038 float reconstructed_camera_mat[4][4];
5040 tracking, tracking_object, context->clip_frame, reconstructed_camera_mat);
5041 float reconstructed_camera_mat_inv[4][4];
5042 invert_m4_m4(reconstructed_camera_mat_inv, reconstructed_camera_mat);
5043
5044 mul_m4_series(cob->matrix, obmat, camera_obmat, reconstructed_camera_mat_inv);
5045 translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
5046}
5047
5049 bConstraintOb *cob)
5050{
5051 Object *camera_object = context->camera_object;
5052 MovieTrackingTrack *track = context->track;
5053
5054 /* Matrix of the object which is being solved prior to this constraint. */
5055 float obmat[4][4];
5056 copy_m4_m4(obmat, cob->matrix);
5057
5058 float reconstructed_camera_mat[4][4];
5059 BKE_tracking_get_camera_object_matrix(camera_object, reconstructed_camera_mat);
5060
5061 mul_m4_m4m4(cob->matrix, obmat, reconstructed_camera_mat);
5062 translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
5063}
5064
5066{
5067 MovieTrackingTrack *track = context->track;
5068 if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
5069 return;
5070 }
5071
5072 if ((context->tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
5074 return;
5075 }
5076
5078}
5079
5080/* Apply undistortion if it is enabled in constraint settings. */
5082 const int clip_width,
5083 const int clip_height,
5084 float marker_position[2])
5085{
5086 if ((context->flag & FOLLOWTRACK_USE_UNDISTORTION) == 0) {
5087 return;
5088 }
5089
5090 /* Undistortion need to happen in pixel space. */
5091 marker_position[0] *= clip_width;
5092 marker_position[1] *= clip_height;
5093
5095 context->tracking, clip_width, clip_height, marker_position, marker_position);
5096
5097 /* Normalize pixel coordinates back. */
5098 marker_position[0] /= clip_width;
5099 marker_position[1] /= clip_height;
5100}
5101
5102/* Modify the marker position matching the frame fitting method. */
5104 const int clip_width,
5105 const int clip_height,
5106 float marker_position[2])
5107{
5108 if (context->frame_method == FOLLOWTRACK_FRAME_STRETCH) {
5109 return;
5110 }
5111
5112 Scene *scene = context->scene;
5113 MovieClip *clip = context->clip;
5114
5115 /* apply clip display aspect */
5116 const float w_src = clip_width * clip->aspx;
5117 const float h_src = clip_height * clip->aspy;
5118
5119 const float w_dst = scene->r.xsch * scene->r.xasp;
5120 const float h_dst = scene->r.ysch * scene->r.yasp;
5121
5122 const float asp_src = w_src / h_src;
5123 const float asp_dst = w_dst / h_dst;
5124
5125 if (fabsf(asp_src - asp_dst) < FLT_EPSILON) {
5126 return;
5127 }
5128
5129 if ((asp_src > asp_dst) == (context->frame_method == FOLLOWTRACK_FRAME_CROP)) {
5130 /* fit X */
5131 float div = asp_src / asp_dst;
5132 float cent = float(clip_width) / 2.0f;
5133
5134 marker_position[0] = (((marker_position[0] * clip_width - cent) * div) + cent) / clip_width;
5135 }
5136 else {
5137 /* fit Y */
5138 float div = asp_dst / asp_src;
5139 float cent = float(clip_height) / 2.0f;
5140
5141 marker_position[1] = (((marker_position[1] * clip_height - cent) * div) + cent) / clip_height;
5142 }
5143}
5144
5145/* Effectively this is a Z-depth of the object form the movie clip camera.
5146 * The idea is to preserve this depth while moving the object in 2D. */
5148 bConstraintOb *cob)
5149{
5150 Object *camera_object = context->camera_object;
5151
5152 float camera_matrix[4][4];
5153 BKE_object_where_is_calc_mat4(camera_object, camera_matrix);
5154
5155 const float z_axis[3] = {0.0f, 0.0f, 1.0f};
5156
5157 /* Direction of camera's local Z axis in the world space. */
5158 float camera_axis[3];
5159 mul_v3_mat3_m4v3(camera_axis, camera_matrix, z_axis);
5160
5161 /* Distance to projection plane. */
5162 float vec[3];
5163 copy_v3_v3(vec, cob->matrix[3]);
5164 sub_v3_v3(vec, camera_matrix[3]);
5165
5166 float projection[3];
5167 project_v3_v3v3(projection, vec, camera_axis);
5168
5169 return len_v3(projection);
5170}
5171
5172/* For the evaluated constraint object project it to the surface of the depth object. */
5174 bConstraintOb *cob)
5175{
5176 if (context->depth_object == nullptr) {
5177 return;
5178 }
5179
5180 Object *depth_object = context->depth_object;
5181 const Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object);
5182 if (depth_mesh == nullptr) {
5183 return;
5184 }
5185
5186 float depth_object_mat_inv[4][4];
5187 invert_m4_m4(depth_object_mat_inv, depth_object->object_to_world().ptr());
5188
5189 float ray_start[3], ray_end[3];
5191 ray_start, depth_object_mat_inv, context->camera_object->object_to_world().location());
5192 mul_v3_m4v3(ray_end, depth_object_mat_inv, cob->matrix[3]);
5193
5194 float ray_direction[3];
5195 sub_v3_v3v3(ray_direction, ray_end, ray_start);
5196 normalize_v3(ray_direction);
5197
5199 BKE_bvhtree_from_mesh_get(&tree_data, depth_mesh, BVHTREE_FROM_CORNER_TRIS, 4);
5200
5201 BVHTreeRayHit hit;
5203 hit.index = -1;
5204
5205 const int result = BLI_bvhtree_ray_cast(tree_data.tree,
5206 ray_start,
5207 ray_direction,
5208 0.0f,
5209 &hit,
5210 tree_data.raycast_callback,
5211 &tree_data);
5212
5213 if (result != -1) {
5214 mul_v3_m4v3(cob->matrix[3], depth_object->object_to_world().ptr(), hit.co);
5215 }
5216
5217 free_bvhtree_from_mesh(&tree_data);
5218}
5219
5221{
5222 Scene *scene = context->scene;
5223 MovieClip *clip = context->clip;
5224 MovieTrackingTrack *track = context->track;
5225 Object *camera_object = context->camera_object;
5226 const float clip_frame = context->clip_frame;
5227 const float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp);
5228
5229 const float object_depth = followtrack_distance_from_viewplane_get(context, cob);
5230 if (object_depth < FLT_EPSILON) {
5231 return;
5232 }
5233
5234 int clip_width, clip_height;
5235 BKE_movieclip_get_size(clip, nullptr, &clip_width, &clip_height);
5236
5237 float marker_position[2];
5238 BKE_tracking_marker_get_subframe_position(track, clip_frame, marker_position);
5239
5240 followtrack_undistort_if_needed(context, clip_width, clip_height, marker_position);
5241 followtrack_fit_frame(context, clip_width, clip_height, marker_position);
5242
5243 float rmat[4][4];
5246 BKE_camera_params_from_object(&params, camera_object);
5247
5248 if (params.is_ortho) {
5249 float vec[3];
5250 vec[0] = params.ortho_scale * (marker_position[0] - 0.5f + params.shiftx);
5251 vec[1] = params.ortho_scale * (marker_position[1] - 0.5f + params.shifty);
5252 vec[2] = -object_depth;
5253
5254 if (aspect > 1.0f) {
5255 vec[1] /= aspect;
5256 }
5257 else {
5258 vec[0] *= aspect;
5259 }
5260
5261 float disp[3];
5262 mul_v3_m4v3(disp, camera_object->object_to_world().ptr(), vec);
5263
5264 copy_m4_m4(rmat, camera_object->object_to_world().ptr());
5265 zero_v3(rmat[3]);
5266 mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
5267
5268 copy_v3_v3(cob->matrix[3], disp);
5269 }
5270 else {
5271 const float d = (object_depth * params.sensor_x) / (2.0f * params.lens);
5272
5273 float vec[3];
5274 vec[0] = d * (2.0f * (marker_position[0] + params.shiftx) - 1.0f);
5275 vec[1] = d * (2.0f * (marker_position[1] + params.shifty) - 1.0f);
5276 vec[2] = -object_depth;
5277
5278 if (aspect > 1.0f) {
5279 vec[1] /= aspect;
5280 }
5281 else {
5282 vec[0] *= aspect;
5283 }
5284
5285 float disp[3];
5286 mul_v3_m4v3(disp, camera_object->object_to_world().ptr(), vec);
5287
5288 /* apply camera rotation so Z-axis would be co-linear */
5289 copy_m4_m4(rmat, camera_object->object_to_world().ptr());
5290 zero_v3(rmat[3]);
5291 mul_m4_m4m4(cob->matrix, cob->matrix, rmat);
5292
5293 copy_v3_v3(cob->matrix[3], disp);
5294 }
5295
5297}
5298
5299static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
5300{
5301 FollowTrackContext context;
5302 if (!followtrack_context_init(&context, con, cob)) {
5303 return;
5304 }
5305
5306 bFollowTrackConstraint *data = static_cast<bFollowTrackConstraint *>(con->data);
5307 if (data->flag & FOLLOWTRACK_USE_3D_POSITION) {
5309 return;
5310 }
5311
5313}
5314
5317 /*size*/ sizeof(bFollowTrackConstraint),
5318 /*name*/ N_("Follow Track"),
5319 /*struct_name*/ "bFollowTrackConstraint",
5320 /*free_data*/ nullptr,
5321 /*id_looper*/ followtrack_id_looper,
5322 /*copy_data*/ nullptr,
5323 /*new_data*/ followtrack_new_data,
5324 /*get_constraint_targets*/ nullptr,
5325 /*flush_constraint_targets*/ nullptr,
5326 /*get_target_matrix*/ nullptr,
5327 /*evaluate_constraint*/ followtrack_evaluate,
5328};
5329
5330/* ----------- Camera Solver ------------- */
5331
5332static void camerasolver_new_data(void *cdata)
5333{
5335
5336 data->clip = nullptr;
5338}
5339
5340static void camerasolver_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
5341{
5342 bCameraSolverConstraint *data = static_cast<bCameraSolverConstraint *>(con->data);
5343
5344 func(con, (ID **)&data->clip, true, userdata);
5345}
5346
5347static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
5348{
5349 Depsgraph *depsgraph = cob->depsgraph;
5350 Scene *scene = cob->scene;
5351 bCameraSolverConstraint *data = static_cast<bCameraSolverConstraint *>(con->data);
5352 MovieClip *clip = data->clip;
5353
5354 if (data->flag & CAMERASOLVER_ACTIVECLIP) {
5355 clip = scene->clip;
5356 }
5357
5358 if (clip) {
5359 float mat[4][4], obmat[4][4];
5360 MovieTracking *tracking = &clip->tracking;
5361 MovieTrackingObject *tracking_object = BKE_tracking_object_get_camera(tracking);
5362 const float ctime = DEG_get_ctime(depsgraph);
5363 const float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
5364
5365 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, mat);
5366
5367 copy_m4_m4(obmat, cob->matrix);
5368
5369 mul_m4_m4m4(cob->matrix, obmat, mat);
5370 }
5371}
5372
5375 /*size*/ sizeof(bCameraSolverConstraint),
5376 /*name*/ N_("Camera Solver"),
5377 /*struct_name*/ "bCameraSolverConstraint",
5378 /*free_data*/ nullptr,
5379 /*id_looper*/ camerasolver_id_looper,
5380 /*copy_data*/ nullptr,
5381 /*new_data*/ camerasolver_new_data,
5382 /*get_constraint_targets*/ nullptr,
5383 /*flush_constraint_targets*/ nullptr,
5384 /*get_target_matrix*/ nullptr,
5385 /*evaluate_constraint*/ camerasolver_evaluate,
5386};
5387
5388/* ----------- Object Solver ------------- */
5389
5390static void objectsolver_new_data(void *cdata)
5391{
5393
5394 data->clip = nullptr;
5396 unit_m4(data->invmat);
5397}
5398
5399static void objectsolver_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
5400{
5401 bObjectSolverConstraint *data = static_cast<bObjectSolverConstraint *>(con->data);
5402
5403 func(con, (ID **)&data->clip, false, userdata);
5404 func(con, (ID **)&data->camera, false, userdata);
5405}
5406
5407static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
5408{
5409 Depsgraph *depsgraph = cob->depsgraph;
5410 Scene *scene = cob->scene;
5411 bObjectSolverConstraint *data = static_cast<bObjectSolverConstraint *>(con->data);
5412 MovieClip *clip = data->clip;
5413 Object *camob = data->camera ? data->camera : scene->camera;
5414
5415 if (data->flag & OBJECTSOLVER_ACTIVECLIP) {
5416 clip = scene->clip;
5417 }
5418 if (!camob || !clip) {
5419 return;
5420 }
5421
5422 MovieTracking *tracking = &clip->tracking;
5423 MovieTrackingObject *tracking_object = BKE_tracking_object_get_named(tracking, data->object);
5424 if (!tracking_object) {
5425 return;
5426 }
5427
5428 float mat[4][4], obmat[4][4], imat[4][4], parmat[4][4];
5429 float ctime = DEG_get_ctime(depsgraph);
5430 float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
5431
5432 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, mat);
5433
5434 invert_m4_m4(imat, mat);
5435 mul_m4_m4m4(parmat, camob->object_to_world().ptr(), imat);
5436
5437 copy_m4_m4(obmat, cob->matrix);
5438
5439 /* Recalculate the inverse matrix if requested. */
5440 if (data->flag & OBJECTSOLVER_SET_INVERSE) {
5441 invert_m4_m4(data->invmat, parmat);
5442
5443 data->flag &= ~OBJECTSOLVER_SET_INVERSE;
5444
5445 /* Write the computed matrix back to the master copy if in copy-on-eval evaluation. */
5447
5448 if (orig_con != nullptr) {
5449 bObjectSolverConstraint *orig_data = static_cast<bObjectSolverConstraint *>(orig_con->data);
5450
5451 copy_m4_m4(orig_data->invmat, data->invmat);
5452 orig_data->flag &= ~OBJECTSOLVER_SET_INVERSE;
5453 }
5454 }
5455
5456 mul_m4_series(cob->matrix, parmat, data->invmat, obmat);
5457}
5458
5461 /*size*/ sizeof(bObjectSolverConstraint),
5462 /*name*/ N_("Object Solver"),
5463 /*struct_name*/ "bObjectSolverConstraint",
5464 /*free_data*/ nullptr,
5465 /*id_looper*/ objectsolver_id_looper,
5466 /*copy_data*/ nullptr,
5467 /*new_data*/ objectsolver_new_data,
5468 /*get_constraint_targets*/ nullptr,
5469 /*flush_constraint_targets*/ nullptr,
5470 /*get_target_matrix*/ nullptr,
5471 /*evaluate_constraint*/ objectsolver_evaluate,
5472};
5473
5474/* ----------- Transform Cache ------------- */
5475
5476static void transformcache_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
5477{
5478 bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
5479 func(con, (ID **)&data->cache_file, true, userdata);
5480}
5481
5483{
5484#if defined(WITH_ALEMBIC) || defined(WITH_USD)
5485 bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
5486 Scene *scene = cob->scene;
5487
5488 CacheFile *cache_file = data->cache_file;
5489
5490 if (!cache_file) {
5491 return;
5492 }
5493
5494 /* Do not process data if using a render time procedural. */
5495 if (BKE_cache_file_uses_render_procedural(cache_file, scene)) {
5496 return;
5497 }
5498
5499 const float frame = DEG_get_ctime(cob->depsgraph);
5500 const double time = BKE_cachefile_time_offset(cache_file, double(frame), FPS);
5501
5502 if (!data->reader || !STREQ(data->reader_object_path, data->object_path)) {
5503 STRNCPY(data->reader_object_path, data->object_path);
5504 BKE_cachefile_reader_open(cache_file, &data->reader, cob->ob, data->object_path);
5505 }
5506
5507 switch (cache_file->type) {
5509# ifdef WITH_ALEMBIC
5510 ABC_get_transform(data->reader, cob->matrix, time, cache_file->scale);
5511# endif
5512 break;
5513 case CACHEFILE_TYPE_USD:
5514# ifdef WITH_USD
5516 data->reader, cob->matrix, time * FPS, cache_file->scale);
5517# endif
5518 break;
5520 break;
5521 }
5522#else
5523 UNUSED_VARS(con, cob);
5524#endif
5525
5526 UNUSED_VARS(targets);
5527}
5528
5530{
5531 bTransformCacheConstraint *src = static_cast<bTransformCacheConstraint *>(srccon->data);
5532 bTransformCacheConstraint *dst = static_cast<bTransformCacheConstraint *>(con->data);
5533
5534 STRNCPY(dst->object_path, src->object_path);
5535 dst->cache_file = src->cache_file;
5536 dst->reader = nullptr;
5537 dst->reader_object_path[0] = '\0';
5538}
5539
5541{
5542 bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
5543
5544 if (data->reader) {
5545 BKE_cachefile_reader_free(data->cache_file, &data->reader);
5546 data->reader_object_path[0] = '\0';
5547 }
5548}
5549
5550static void transformcache_new_data(void *cdata)
5551{
5553
5554 data->cache_file = nullptr;
5555}
5556
5559 /*size*/ sizeof(bTransformCacheConstraint),
5560 /*name*/ N_("Transform Cache"),
5561 /*struct_name*/ "bTransformCacheConstraint",
5562 /*free_data*/ transformcache_free,
5563 /*id_looper*/ transformcache_id_looper,
5564 /*copy_data*/ transformcache_copy,
5565 /*new_data*/ transformcache_new_data,
5566 /*get_constraint_targets*/ nullptr,
5567 /*flush_constraint_targets*/ nullptr,
5568 /*get_target_matrix*/ nullptr,
5569 /*evaluate_constraint*/ transformcache_evaluate,
5570};
5571
5572/* ************************* Constraints Type-Info *************************** */
5573/* All of the constraints api functions use bConstraintTypeInfo structs to carry out
5574 * and operations that involve constraint specific code.
5575 */
5576
5577/* These globals only ever get directly accessed in this file */
5579static short CTI_INIT = 1; /* when non-zero, the list needs to be updated */
5580
5581/* This function only gets called when CTI_INIT is non-zero */
5583{
5584 constraintsTypeInfo[0] = nullptr; /* 'Null' Constraint */
5585 constraintsTypeInfo[1] = &CTI_CHILDOF; /* ChildOf Constraint */
5586 constraintsTypeInfo[2] = &CTI_TRACKTO; /* TrackTo Constraint */
5587 constraintsTypeInfo[3] = &CTI_KINEMATIC; /* IK Constraint */
5588 constraintsTypeInfo[4] = &CTI_FOLLOWPATH; /* Follow-Path Constraint */
5589 constraintsTypeInfo[5] = &CTI_ROTLIMIT; /* Limit Rotation Constraint */
5590 constraintsTypeInfo[6] = &CTI_LOCLIMIT; /* Limit Location Constraint */
5591 constraintsTypeInfo[7] = &CTI_SIZELIMIT; /* Limit Scale Constraint */
5592 constraintsTypeInfo[8] = &CTI_ROTLIKE; /* Copy Rotation Constraint */
5593 constraintsTypeInfo[9] = &CTI_LOCLIKE; /* Copy Location Constraint */
5594 constraintsTypeInfo[10] = &CTI_SIZELIKE; /* Copy Scale Constraint */
5595 constraintsTypeInfo[11] = &CTI_PYTHON; /* Python/Script Constraint */
5596 constraintsTypeInfo[12] = &CTI_ACTION; /* Action Constraint */
5597 constraintsTypeInfo[13] = &CTI_LOCKTRACK; /* Locked-Track Constraint */
5598 constraintsTypeInfo[14] = &CTI_DISTLIMIT; /* Limit Distance Constraint */
5599 constraintsTypeInfo[15] = &CTI_STRETCHTO; /* StretchTo Constraint */
5600 constraintsTypeInfo[16] = &CTI_MINMAX; /* Floor Constraint */
5601 constraintsTypeInfo[17] = nullptr; /* RigidBody Constraint: DEPRECATED. */
5602 constraintsTypeInfo[18] = &CTI_CLAMPTO; /* ClampTo Constraint */
5603 constraintsTypeInfo[19] = &CTI_TRANSFORM; /* Transformation Constraint */
5604 constraintsTypeInfo[20] = &CTI_SHRINKWRAP; /* Shrinkwrap Constraint */
5605 constraintsTypeInfo[21] = &CTI_DAMPTRACK; /* Damped TrackTo Constraint */
5606 constraintsTypeInfo[22] = &CTI_SPLINEIK; /* Spline IK Constraint */
5607 constraintsTypeInfo[23] = &CTI_TRANSLIKE; /* Copy Transforms Constraint */
5608 constraintsTypeInfo[24] = &CTI_SAMEVOL; /* Maintain Volume Constraint */
5609 constraintsTypeInfo[25] = &CTI_PIVOT; /* Pivot Constraint */
5610 constraintsTypeInfo[26] = &CTI_FOLLOWTRACK; /* Follow Track Constraint */
5611 constraintsTypeInfo[27] = &CTI_CAMERASOLVER; /* Camera Solver Constraint */
5612 constraintsTypeInfo[28] = &CTI_OBJECTSOLVER; /* Object Solver Constraint */
5613 constraintsTypeInfo[29] = &CTI_TRANSFORM_CACHE; /* Transform Cache Constraint */
5614 constraintsTypeInfo[30] = &CTI_ARMATURE; /* Armature Constraint */
5615}
5616
5618{
5619 /* initialize the type-info list? */
5620 if (CTI_INIT) {
5622 CTI_INIT = 0;
5623 }
5624
5625 /* only return for valid types */
5626 if ((type >= CONSTRAINT_TYPE_NULL) && (type < NUM_CONSTRAINT_TYPES)) {
5627 /* there shouldn't be any segfaults here... */
5628 return constraintsTypeInfo[type];
5629 }
5630
5631 CLOG_WARN(&LOG, "No valid constraint type-info data available. Type = %i", type);
5632
5633 return nullptr;
5634}
5635
5637{
5638 /* only return typeinfo for valid constraints */
5639 if (con) {
5641 }
5642
5643 return nullptr;
5644}
5645
5646/* ************************* General Constraints API ************************** */
5647/* The functions here are called by various parts of Blender. Very few (should be none if possible)
5648 * constraint-specific code should occur here.
5649 */
5650
5651/* ---------- Data Management ------- */
5652
5656static void con_unlink_refs_cb(bConstraint * /*con*/,
5657 ID **idpoin,
5658 bool is_reference,
5659 void * /*user_data*/)
5660{
5661 if (*idpoin && is_reference) {
5662 id_us_min(*idpoin);
5663 }
5664}
5665
5668 bConstraint *con,
5669 ConstraintIDFunc func,
5670 const int flag,
5671 void *userdata)
5672{
5673 if (cti->id_looper) {
5674 cti->id_looper(con, func, userdata);
5675 }
5676
5677 func(con, (ID **)&con->space_object, false, userdata);
5678
5680 func(con, reinterpret_cast<ID **>(&con->ipo), false, userdata);
5681 }
5682}
5683
5684void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user)
5685{
5686 if (con->data) {
5688
5689 if (cti) {
5690 /* perform any special freeing constraint may have */
5691 if (cti->free_data) {
5692 cti->free_data(con);
5693 }
5694
5695 /* unlink the referenced resources it uses */
5696 if (do_id_user) {
5698 }
5699 }
5700
5701 /* free constraint data now */
5702 MEM_freeN(con->data);
5703 }
5704}
5705
5710
5711void BKE_constraints_free_ex(ListBase *list, bool do_id_user)
5712{
5713 /* Free constraint data and also any extra data */
5714 LISTBASE_FOREACH (bConstraint *, con, list) {
5715 BKE_constraint_free_data_ex(con, do_id_user);
5716 }
5717
5718 /* Free the whole list */
5719 BLI_freelistN(list);
5720}
5721
5723{
5724 BKE_constraints_free_ex(list, true);
5725}
5726
5728{
5729 if (con) {
5731 BLI_freelinkN(list, con);
5732 return true;
5733 }
5734
5735 return false;
5736}
5737
5739{
5740 const short type = con->type;
5741 if (BKE_constraint_remove(list, con)) {
5742 /* ITASC needs to be rebuilt once a constraint is removed #26920. */
5744 BIK_clear_data(ob->pose);
5745 }
5746 return true;
5747 }
5748
5749 return false;
5750}
5751
5753 Scene *scene,
5754 Object *ob,
5755 bConstraint *con)
5756{
5757 if (!con) {
5758 return false;
5759 }
5760
5761 const float ctime = BKE_scene_frame_get(scene);
5762
5763 /* Do this all in the evaluated domain (e.g. shrinkwrap needs to access evaluated constraint
5764 * target mesh). */
5767 bConstraint *con_eval = BKE_constraints_find_name(&ob_eval->constraints, con->name);
5768
5769 bConstraint *new_con = BKE_constraint_duplicate_ex(con_eval, 0, ID_IS_EDITABLE(ob));
5770 ListBase single_con = {new_con, new_con};
5771
5773 depsgraph, scene_eval, ob_eval, nullptr, CONSTRAINT_OBTYPE_OBJECT);
5774 /* Undo the effect of the current constraint stack evaluation. */
5775 mul_m4_m4m4(cob->matrix, ob_eval->constinv, cob->matrix);
5776
5777 /* Evaluate single constraint. */
5778 BKE_constraints_solve(depsgraph, &single_con, cob, ctime);
5779 /* Copy transforms back. This will leave the object in a bad state
5780 * as ob->constinv will be wrong until next evaluation. */
5782
5783 /* Free the copied constraint. */
5784 BKE_constraint_free_data(new_con);
5785 BLI_freelinkN(&single_con, new_con);
5786
5787 /* Apply transform from matrix. */
5788 BKE_object_apply_mat4(ob, ob_eval->object_to_world().ptr(), true, true);
5789
5790 return true;
5791}
5792
5794 Scene *scene,
5795 ListBase /*bConstraint*/ *constraints,
5796 Object *ob,
5797 bConstraint *con)
5798{
5799 if (!BKE_constraint_apply_for_object(depsgraph, scene, ob, con)) {
5800 return false;
5801 }
5802
5803 return BKE_constraint_remove_ex(constraints, ob, con);
5804}
5805
5807 Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
5808{
5809 if (!con) {
5810 return false;
5811 }
5812
5813 const float ctime = BKE_scene_frame_get(scene);
5814
5815 /* Do this all in the evaluated domain (e.g. shrinkwrap needs to access evaluated constraint
5816 * target mesh). */
5819 bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
5820 bConstraint *con_eval = BKE_constraints_find_name(&pchan_eval->constraints, con->name);
5821
5822 bConstraint *new_con = BKE_constraint_duplicate_ex(con_eval, 0, ID_IS_EDITABLE(ob));
5823 ListBase single_con;
5824 single_con.first = new_con;
5825 single_con.last = new_con;
5826
5827 float vec[3];
5828 copy_v3_v3(vec, pchan_eval->pose_mat[3]);
5829
5831 depsgraph, scene_eval, ob_eval, pchan_eval, CONSTRAINT_OBTYPE_BONE);
5832 /* Undo the effects of currently applied constraints. */
5833 mul_m4_m4m4(cob->matrix, pchan_eval->constinv, cob->matrix);
5834 /* Evaluate single constraint. */
5835 BKE_constraints_solve(depsgraph, &single_con, cob, ctime);
5837
5838 /* Free the copied constraint. */
5839 BKE_constraint_free_data(new_con);
5840 BLI_freelinkN(&single_con, new_con);
5841
5842 /* Prevent constraints breaking a chain. */
5843 if (pchan->bone->flag & BONE_CONNECTED) {
5844 copy_v3_v3(pchan_eval->pose_mat[3], vec);
5845 }
5846
5847 /* Apply transform from matrix. */
5848 float mat[4][4];
5849 BKE_armature_mat_pose_to_bone(pchan, pchan_eval->pose_mat, mat);
5850 BKE_pchan_apply_mat4(pchan, mat, true);
5851
5852 return true;
5853}
5854
5856 Scene *scene,
5857 ListBase /*bConstraint*/ *constraints,
5858 Object *ob,
5859 bConstraint *con,
5860 bPoseChannel *pchan)
5861{
5862 if (!BKE_constraint_apply_for_pose(depsgraph, scene, ob, pchan, con)) {
5863 return false;
5864 }
5865
5866 return BKE_constraint_remove_ex(constraints, ob, con);
5867}
5868
5873
5874/* ......... */
5875
5876/* Creates a new constraint, initializes its data, and returns it */
5877static bConstraint *add_new_constraint_internal(const char *name, short type)
5878{
5879 bConstraint *con = static_cast<bConstraint *>(MEM_callocN(sizeof(bConstraint), "Constraint"));
5881 const char *newName;
5882
5883 /* Set up a generic constraint data-block. */
5884 con->type = type;
5886 con->enforce = 1.0f;
5887
5888 /* Only open the main panel when constraints are created, not the sub-panels. */
5891 /* Expand the two sub-panels in the cases where the main panel barely has any properties. */
5893 }
5894
5895 /* Determine a basic name, and info */
5896 if (cti) {
5897 /* initialize constraint data */
5898 con->data = MEM_callocN(cti->size, cti->struct_name);
5899
5900 /* only constraints that change any settings need this */
5901 if (cti->new_data) {
5902 cti->new_data(con->data);
5903 }
5904
5905 /* if no name is provided, use the type of the constraint as the name */
5906 newName = (name && name[0]) ? name : DATA_(cti->name);
5907 }
5908 else {
5909 /* if no name is provided, use the generic "Const" name */
5910 /* NOTE: any constraint type that gets here really shouldn't get added... */
5911 newName = (name && name[0]) ? name : DATA_("Const");
5912 }
5913
5914 /* copy the name */
5915 STRNCPY(con->name, newName);
5916
5917 /* return the new constraint */
5918 return con;
5919}
5920
5921/* Add a newly created constraint to the constraint list. */
5923{
5924 ListBase *list;
5925
5926 /* find the constraint stack - bone or object? */
5927 list = (pchan) ? (&pchan->constraints) : (&ob->constraints);
5928
5929 if (list) {
5930 /* add new constraint to end of list of constraints before ensuring that it has a unique name
5931 * (otherwise unique-naming code will fail, since it assumes element exists in list)
5932 */
5933 BLI_addtail(list, con);
5934 BKE_constraint_unique_name(con, list);
5935
5936 /* make this constraint the active one */
5937 BKE_constraints_active_set(list, con);
5938 }
5939}
5940
5941/* if pchan is not nullptr then assume we're adding a pose constraint */
5943 bPoseChannel *pchan,
5944 const char *name,
5945 short type)
5946{
5947 bConstraint *con;
5948
5949 /* add the constraint */
5950 con = add_new_constraint_internal(name, type);
5951
5952 add_new_constraint_to_list(ob, pchan, con);
5953
5954 /* set type+owner specific immutable settings */
5955 /* TODO: does action constraint need anything here - i.e. spaceonce? */
5956 switch (type) {
5958 /* if this constraint is being added to a posechannel, make sure
5959 * the constraint gets evaluated in pose-space */
5960 if (pchan) {
5962 }
5963 break;
5964 }
5966 /* The Before or Split modes require computing in local space, but
5967 * for objects the Local space doesn't make sense (#78462, D6095 etc).
5968 * So only default to Before (Split) if the constraint is on a bone. */
5969 if (pchan) {
5970 bActionConstraint *data = static_cast<bActionConstraint *>(con->data);
5973 }
5974 break;
5975 }
5976 }
5977
5978 return con;
5979}
5980
5982{
5984 return false;
5985 }
5986
5987 return (con->flag & CONSTRAINT_BBONE_SHAPE) || (con->type == CONSTRAINT_TYPE_ARMATURE);
5988}
5989
5990/* ......... */
5991
5993 bPoseChannel *pchan,
5994 const char *name,
5995 short type)
5996{
5997 if (pchan == nullptr) {
5998 return nullptr;
5999 }
6000
6001 return add_new_constraint(ob, pchan, name, type);
6002}
6003
6004bConstraint *BKE_constraint_add_for_object(Object *ob, const char *name, short type)
6005{
6006 return add_new_constraint(ob, nullptr, name, type);
6007}
6008
6009/* ......... */
6010
6012 ConstraintIDFunc func,
6013 const int flag,
6014 void *userdata)
6015{
6016 LISTBASE_FOREACH (bConstraint *, con, conlist) {
6018
6019 if (cti) {
6020 con_invoke_id_looper(cti, con, func, flag, userdata);
6021 }
6022 }
6023}
6024
6025/* ......... */
6026
6027/* helper for BKE_constraints_copy(), to be used for making sure that ID's are valid */
6028static void con_extern_cb(bConstraint * /*con*/,
6029 ID **idpoin,
6030 bool /*is_reference*/,
6031 void * /*user_data*/)
6032{
6033 if (*idpoin && ID_IS_LINKED(*idpoin)) {
6034 id_lib_extern(*idpoin);
6035 }
6036}
6037
6043 ID **idpoin,
6044 bool is_reference,
6045 void * /*user_data*/)
6046{
6047 /* Increment user-count if this is a reference type. */
6048 if ((*idpoin) && (is_reference)) {
6049 id_us_plus(*idpoin);
6050 }
6051}
6052
6055 bConstraint *src,
6056 const int flag,
6057 const bool do_extern)
6058{
6060
6061 /* make a new copy of the constraint's data */
6062 dst->data = MEM_dupallocN(dst->data);
6063
6064 /* only do specific constraints if required */
6065 if (cti) {
6066 /* perform custom copying operations if needed */
6067 if (cti->copy_data) {
6068 cti->copy_data(dst, src);
6069 }
6070
6071 /* Fix user-counts for all referenced data that need it. */
6072 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
6074 }
6075
6076 /* For proxies we don't want to make external. */
6077 if (do_extern) {
6078 /* go over used ID-links for this constraint to ensure that they are valid for proxies */
6079 con_invoke_id_looper(cti, dst, con_extern_cb, IDWALK_NOP, nullptr);
6080 }
6081 }
6082}
6083
6084bConstraint *BKE_constraint_duplicate_ex(bConstraint *src, const int flag, const bool do_extern)
6085{
6086 bConstraint *dst = static_cast<bConstraint *>(MEM_dupallocN(src));
6087 constraint_copy_data_ex(dst, src, flag, do_extern);
6088 dst->next = dst->prev = nullptr;
6089 return dst;
6090}
6091
6093{
6094 if (pchan == nullptr) {
6095 return nullptr;
6096 }
6097
6099 add_new_constraint_to_list(ob, pchan, new_con);
6100 return new_con;
6101}
6102
6104{
6106 add_new_constraint_to_list(ob, nullptr, new_con);
6107 return new_con;
6108}
6109
6110void BKE_constraints_copy_ex(ListBase *dst, const ListBase *src, const int flag, bool do_extern)
6111{
6112 bConstraint *con, *srccon;
6113
6114 BLI_listbase_clear(dst);
6115 BLI_duplicatelist(dst, src);
6116
6117 for (con = static_cast<bConstraint *>(dst->first),
6118 srccon = static_cast<bConstraint *>(src->first);
6119 con && srccon;
6120 srccon = srccon->next, con = con->next)
6121 {
6122 constraint_copy_data_ex(con, srccon, flag, do_extern);
6125 }
6126 }
6127}
6128
6129void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern)
6130{
6131 BKE_constraints_copy_ex(dst, src, 0, do_extern);
6132}
6133
6134/* ......... */
6135
6137{
6138 return static_cast<bConstraint *>(BLI_findstring(list, name, offsetof(bConstraint, name)));
6139}
6140
6142{
6143
6144 /* search for the first constraint with the 'active' flag set */
6145 if (list) {
6146 LISTBASE_FOREACH (bConstraint *, con, list) {
6147 if (con->flag & CONSTRAINT_ACTIVE) {
6148 return con;
6149 }
6150 }
6151 }
6152
6153 /* no active constraint found */
6154 return nullptr;
6155}
6156
6158{
6159
6160 if (list) {
6161 LISTBASE_FOREACH (bConstraint *, con_iter, list) {
6162 if (con_iter == con) {
6163 con_iter->flag |= CONSTRAINT_ACTIVE;
6164 }
6165 else {
6166 con_iter->flag &= ~CONSTRAINT_ACTIVE;
6167 }
6168 }
6169 }
6170}
6171
6173{
6175 ListBase *targets = nullptr;
6176
6177 if (con->type == CONSTRAINT_TYPE_PYTHON) {
6178 targets = &((bPythonConstraint *)con->data)->targets;
6179 }
6180 else if (con->type == CONSTRAINT_TYPE_ARMATURE) {
6181 targets = &((bArmatureConstraint *)con->data)->targets;
6182 }
6183
6184 if (targets && BLI_findindex(targets, tgt) != -1) {
6185 return con;
6186 }
6187 }
6188
6189 return nullptr;
6190}
6191
6193 bConstraintTarget *tgt,
6194 bPoseChannel **r_pchan)
6195{
6196 if (r_pchan != nullptr) {
6197 *r_pchan = nullptr;
6198 }
6199
6201
6202 if (result != nullptr) {
6203 return result;
6204 }
6205
6206 if (ob->pose != nullptr) {
6207 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
6208 result = constraint_list_find_from_target(&pchan->constraints, tgt);
6209
6210 if (result != nullptr) {
6211 if (r_pchan != nullptr) {
6212 *r_pchan = pchan;
6213 }
6214
6215 return result;
6216 }
6217 }
6218 }
6219
6220 return nullptr;
6221}
6222
6223/* Finds the original copy of the constraint based on an evaluated copy. */
6225 bPoseChannel *pchan,
6226 bConstraint *con,
6227 Object **r_orig_ob)
6228{
6229 Object *orig_ob = (Object *)DEG_get_original_id(&ob->id);
6230
6231 if (ELEM(orig_ob, nullptr, ob)) {
6232 return nullptr;
6233 }
6234
6235 /* Find which constraint list to use. */
6236 ListBase *constraints, *orig_constraints;
6237
6238 if (pchan != nullptr) {
6239 bPoseChannel *orig_pchan = pchan->orig_pchan;
6240
6241 if (orig_pchan == nullptr) {
6242 return nullptr;
6243 }
6244
6245 constraints = &pchan->constraints;
6246 orig_constraints = &orig_pchan->constraints;
6247 }
6248 else {
6249 constraints = &ob->constraints;
6250 orig_constraints = &orig_ob->constraints;
6251 }
6252
6253 /* Lookup the original constraint by index. */
6254 int index = BLI_findindex(constraints, con);
6255
6256 if (index >= 0) {
6257 bConstraint *orig_con = static_cast<bConstraint *>(BLI_findlink(orig_constraints, index));
6258
6259 /* Verify it has correct type and name. */
6260 if (orig_con && orig_con->type == con->type && STREQ(orig_con->name, con->name)) {
6261 if (r_orig_ob != nullptr) {
6262 *r_orig_ob = orig_ob;
6263 }
6264
6265 return orig_con;
6266 }
6267 }
6268
6269 return nullptr;
6270}
6271
6273{
6274 /* Write the computed distance back to the master copy if in copy-on-eval evaluation. */
6275 if (!DEG_is_active(cob->depsgraph)) {
6276 return nullptr;
6277 }
6278
6279 Object *orig_ob = nullptr;
6280 bConstraint *orig_con = constraint_find_original(cob->ob, cob->pchan, con, &orig_ob);
6281
6282 if (orig_con != nullptr) {
6284 }
6285
6286 return orig_con;
6287}
6288
6290{
6291 return (ID_IS_OVERRIDE_LIBRARY(ob) &&
6292 (con == nullptr || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) == 0));
6293}
6294
6295/* -------- Target-Matrix Stuff ------- */
6296
6298{
6299 BLI_listbase_clear(r_targets);
6300
6302
6303 if (!cti) {
6304 return 0;
6305 }
6306
6307 int count = 0;
6308
6309 /* Constraint-specific targets. */
6310 if (cti->get_constraint_targets) {
6311 count = cti->get_constraint_targets(con, r_targets);
6312 }
6313
6314 /* Add the custom target. */
6315 if (is_custom_space_needed(con)) {
6317 SINGLETARGET_GET_TARS(con, con->space_object, con->space_subtarget, ct, r_targets);
6320 count++;
6321 }
6322
6323 return count;
6324}
6325
6326void BKE_constraint_targets_flush(bConstraint *con, ListBase *targets, bool no_copy)
6327{
6329
6330 if (!cti) {
6331 return;
6332 }
6333
6334 /* Remove the custom target. */
6335 bConstraintTarget *ct = (bConstraintTarget *)targets->last;
6336
6337 if (ct && (ct->flag & CONSTRAINT_TAR_CUSTOM_SPACE)) {
6339
6340 if (!no_copy) {
6341 con->space_object = ct->tar;
6343 }
6344
6345 BLI_freelinkN(targets, ct);
6346 }
6347
6348 /* Release the constraint-specific targets. */
6349 if (cti->flush_constraint_targets) {
6350 cti->flush_constraint_targets(con, targets, no_copy);
6351 }
6352}
6353
6355 Scene *scene,
6356 bConstraint *con,
6357 int index,
6358 short ownertype,
6359 void *ownerdata,
6360 float mat[4][4],
6361 float ctime)
6362{
6364 ListBase targets = {nullptr, nullptr};
6365 bConstraintOb *cob;
6367
6368 if (cti && cti->get_constraint_targets) {
6369 /* make 'constraint-ob' */
6370 cob = static_cast<bConstraintOb *>(MEM_callocN(sizeof(bConstraintOb), "tempConstraintOb"));
6371 cob->type = ownertype;
6372 cob->scene = scene;
6373 cob->depsgraph = depsgraph;
6374 switch (ownertype) {
6375 case CONSTRAINT_OBTYPE_OBJECT: /* it is usually this case */
6376 {
6377 cob->ob = (Object *)ownerdata;
6378 cob->pchan = nullptr;
6379 if (cob->ob) {
6380 copy_m4_m4(cob->matrix, cob->ob->object_to_world().ptr());
6381 copy_m4_m4(cob->startmat, cob->matrix);
6382 }
6383 else {
6384 unit_m4(cob->matrix);
6385 unit_m4(cob->startmat);
6386 }
6387 break;
6388 }
6389 case CONSTRAINT_OBTYPE_BONE: /* this may occur in some cases */
6390 {
6391 cob->ob = nullptr; /* this might not work at all :/ */
6392 cob->pchan = (bPoseChannel *)ownerdata;
6393 if (cob->pchan) {
6394 copy_m4_m4(cob->matrix, cob->pchan->pose_mat);
6395 copy_m4_m4(cob->startmat, cob->matrix);
6396 }
6397 else {
6398 unit_m4(cob->matrix);
6399 unit_m4(cob->startmat);
6400 }
6401 break;
6402 }
6403 }
6404
6405 /* Initialize the custom space for use in calculating the matrices. */
6407
6408 /* get targets - we only need the first one though (and there should only be one) */
6409 cti->get_constraint_targets(con, &targets);
6410
6411 /* only calculate the target matrix on the first target */
6412 ct = static_cast<bConstraintTarget *>(BLI_findlink(&targets, index));
6413
6414 if (ct) {
6415 if (cti->get_target_matrix) {
6416 cti->get_target_matrix(depsgraph, con, cob, ct, ctime);
6417 }
6418 copy_m4_m4(mat, ct->matrix);
6419 }
6420
6421 /* free targets + 'constraint-ob' */
6422 if (cti->flush_constraint_targets) {
6423 cti->flush_constraint_targets(con, &targets, true);
6424 }
6425 MEM_freeN(cob);
6426 }
6427 else {
6428 /* invalid constraint - perhaps... */
6429 unit_m4(mat);
6430 }
6431}
6432
6434 Depsgraph *depsgraph, bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
6435{
6437
6438 if (cti && cti->get_constraint_targets) {
6439 /* get targets
6440 * - constraints should use ct->matrix, not directly accessing values
6441 * - ct->matrix members have not yet been calculated here!
6442 */
6443 cti->get_constraint_targets(con, targets);
6444
6445 /* The Armature constraint doesn't need ct->matrix for evaluate at all. */
6446 if (ELEM(cti->type, CONSTRAINT_TYPE_ARMATURE)) {
6447 return;
6448 }
6449
6450 /* set matrices
6451 * - calculate if possible, otherwise just initialize as identity matrix
6452 */
6453 if (cti->get_target_matrix) {
6454 LISTBASE_FOREACH (bConstraintTarget *, ct, targets) {
6455 cti->get_target_matrix(depsgraph, con, cob, ct, ctime);
6456 }
6457 }
6458 else {
6459 LISTBASE_FOREACH (bConstraintTarget *, ct, targets) {
6460 unit_m4(ct->matrix);
6461 }
6462 }
6463 }
6464}
6465
6467{
6468 if (con && con->space_object && is_custom_space_needed(con)) {
6469 /* Basically default_get_tarmat but without the unused parameters. */
6471 con->space_subtarget,
6472 nullptr,
6476 0,
6477 0);
6478
6479 return;
6480 }
6481
6483}
6484
6485/* ---------- Evaluation ----------- */
6486
6488 ListBase *conlist,
6489 bConstraintOb *cob,
6490 float ctime)
6491{
6492 float oldmat[4][4];
6493 float enf;
6494
6495 /* check that there is a valid constraint object to evaluate */
6496 if (cob == nullptr) {
6497 return;
6498 }
6499
6500 /* loop over available constraints, solving and blending them */
6501 LISTBASE_FOREACH (bConstraint *, con, conlist) {
6503 ListBase targets = {nullptr, nullptr};
6504
6505 /* these we can skip completely (invalid constraints...) */
6506 if (cti == nullptr) {
6507 continue;
6508 }
6509 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
6510 continue;
6511 }
6512 /* these constraints can't be evaluated anyway */
6513 if (cti->evaluate_constraint == nullptr) {
6514 continue;
6515 }
6516 /* influence == 0 should be ignored */
6517 if (con->enforce == 0.0f) {
6518 continue;
6519 }
6520
6521 /* influence of constraint
6522 * - value should have been set from animation data already
6523 */
6524 enf = con->enforce;
6525
6526 /* Initialize the custom space for use in calculating the matrices. */
6528
6529 /* make copy of world-space matrix pre-constraint for use with blending later */
6530 copy_m4_m4(oldmat, cob->matrix);
6531
6532 /* move owner matrix into right space */
6534 cob->ob, cob->pchan, cob, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false);
6535
6536 /* prepare targets for constraint solving */
6537 BKE_constraint_targets_for_solving_get(depsgraph, con, cob, &targets, ctime);
6538
6539 /* Solve the constraint and put result in cob->matrix */
6540 cti->evaluate_constraint(con, cob, &targets);
6541
6542 /* clear targets after use
6543 * - this should free temp targets but no data should be copied back
6544 * as constraints may have done some nasty things to it...
6545 */
6546 if (cti->flush_constraint_targets) {
6547 cti->flush_constraint_targets(con, &targets, true);
6548 }
6549
6550 /* move owner back into world-space for next constraint/other business */
6551 if ((con->flag & CONSTRAINT_SPACEONCE) == 0) {
6553 cob->ob, cob->pchan, cob, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false);
6554 }
6555
6556 /* Interpolate the enforcement, to blend result of constraint into final owner transform
6557 * - all this happens in world-space to prevent any weirdness creeping in
6558 * (#26014 and #25725), since some constraints may not convert the solution back to the input
6559 * space before blending but all are guaranteed to end up in good "world-space" result.
6560 */
6561 /* NOTE: all kind of stuff here before (caused trouble), much easier to just interpolate,
6562 * or did I miss something? -jahka (r.32105) */
6563 if (enf < 1.0f) {
6564 float solution[4][4];
6565 copy_m4_m4(solution, cob->matrix);
6566 interp_m4_m4m4(cob->matrix, oldmat, solution, enf);
6567 }
6568 }
6569}
6570
6572{
6573 LISTBASE_FOREACH (bConstraint *, con, conlist) {
6575
6576 /* Write the specific data */
6577 if (cti && con->data) {
6578 /* firstly, just write the plain con->data struct */
6579 BLO_write_struct_by_name(writer, cti->struct_name, con->data);
6580
6581 /* do any constraint specific stuff */
6582 switch (con->type) {
6584 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
6585
6586 /* write targets */
6587 LISTBASE_FOREACH (bConstraintTarget *, ct, &data->targets) {
6589 }
6590
6591 /* Write ID Properties -- and copy this comment EXACTLY for easy finding
6592 * of library blocks that implement this. */
6593 IDP_BlendWrite(writer, data->prop);
6594
6595 break;
6596 }
6598 bArmatureConstraint *data = static_cast<bArmatureConstraint *>(con->data);
6599
6600 /* write targets */
6601 LISTBASE_FOREACH (bConstraintTarget *, ct, &data->targets) {
6603 }
6604
6605 break;
6606 }
6608 bSplineIKConstraint *data = static_cast<bSplineIKConstraint *>(con->data);
6609
6610 /* write points array */
6611 BLO_write_float_array(writer, data->numpoints, data->points);
6612
6613 break;
6614 }
6615 }
6616 }
6617
6618 /* Write the constraint */
6619 BLO_write_struct(writer, bConstraint, con);
6620 }
6621}
6622
6624{
6625 BLO_read_struct_list(reader, bConstraint, lb);
6626 LISTBASE_FOREACH (bConstraint *, con, lb) {
6628 if (cti) {
6629 con->data = BLO_read_struct_by_name_array(reader, cti->struct_name, 1, con->data);
6630 }
6631 else {
6632 /* No `BLI_assert_unreachable()` here, this code can be reached in some cases, like the
6633 * deprecated RigidBody constraint. */
6634 con->data = nullptr;
6635 }
6636
6637 /* Patch for error introduced by changing constraints (don't know how). */
6638 /* NOTE(@ton): If `con->data` type changes, DNA cannot resolve the pointer!. */
6639 /* FIXME This is likely dead code actually, since it used to be in
6640 * constraint 'read_lib', so it would have crashed on null pointer access in any of
6641 * the code below? But does not hurt to keep it around as a safety measure. */
6642 if (con->data == nullptr) {
6643 con->type = CONSTRAINT_TYPE_NULL;
6644 }
6645
6646 /* If linking from a library, clear 'local' library override flag. */
6647 if (ID_IS_LINKED(id_owner)) {
6648 con->flag &= ~CONSTRAINT_OVERRIDE_LIBRARY_LOCAL;
6649 }
6650
6651 switch (con->type) {
6653 bPythonConstraint *data = static_cast<bPythonConstraint *>(con->data);
6654
6655 BLO_read_struct_list(reader, bConstraintTarget, &data->targets);
6656
6657 BLO_read_struct(reader, IDProperty, &data->prop);
6658 IDP_BlendDataRead(reader, &data->prop);
6659 break;
6660 }
6662 bArmatureConstraint *data = static_cast<bArmatureConstraint *>(con->data);
6663
6664 BLO_read_struct_list(reader, bConstraintTarget, &data->targets);
6665
6666 break;
6667 }
6669 bSplineIKConstraint *data = static_cast<bSplineIKConstraint *>(con->data);
6670
6671 BLO_read_float_array(reader, data->numpoints, &data->points);
6672 break;
6673 }
6675 bKinematicConstraint *data = static_cast<bKinematicConstraint *>(con->data);
6676
6677 con->lin_error = 0.0f;
6678 con->rot_error = 0.0f;
6679
6680 /* version patch for runtime flag, was not cleared in some case */
6681 data->flag &= ~CONSTRAINT_IK_AUTO;
6682 break;
6683 }
6685 bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
6686 data->reader = nullptr;
6687 data->reader_object_path[0] = '\0';
6688 }
6689 }
6690 }
6691}
6692
6693/* Some static asserts to ensure that the bActionConstraint data is using the expected types for
6694 * some of the fields. This check is done here instead of in DNA_constraint_types.h to avoid the
6695 * inclusion of an DNA_anim_types.h in DNA_constraint_types.h just for this assert. */
6696static_assert(
6697 std::is_same_v<decltype(ActionSlot::handle), decltype(bActionConstraint::action_slot_handle)>);
6698static_assert(
6699 std::is_same_v<decltype(ActionSlot::name), decltype(bActionConstraint::action_slot_name)>);
void ABC_get_transform(struct CacheReader *reader, float r_mat_world[4][4], double time, float scale)
Functions and classes to work with Actions.
void BIK_clear_data(struct bPose *pose)
Blender kernel action and pose functionality.
void BKE_pose_free_data(bPose *pose) ATTR_NONNULL(1)
void what_does_obaction(Object *ob, Object *workob, bPose *pose, bAction *act, int32_t action_slot_handle, char groupname[], const AnimationEvalContext *anim_eval_context) ATTR_NONNULL(1
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
bPoseChannel * BKE_pose_channel_ensure(bPose *pose, const char *name) ATTR_NONNULL(2)
bool BKE_where_on_path(const struct Object *ob, float ctime, float r_vec[4], float r_dir[3], float r_quat[4], float *r_radius, float *r_weight)
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:734
void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan, const float *co, int *r_index, float *r_blend_next)
Definition armature.cc:1970
void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
Definition armature.cc:2260
void BKE_pchan_calc_mat(bPoseChannel *pchan)
Definition armature.cc:2860
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
Definition armature.cc:2358
float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, const float inmat[4][4], float outmat[4][4])
Definition armature.cc:2249
void BKE_pchan_bbone_deform_clamp_segment_index(const bPoseChannel *pchan, float head_tail, int *r_index, float *r_blend_next)
Definition armature.cc:1800
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
Definition bvhutils.cc:1160
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition bvhutils.cc:899
@ BVHTREE_FROM_CORNER_TRIS
bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, Scene *scene)
Definition cachefile.cc:418
void BKE_cachefile_reader_free(CacheFile *cache_file, CacheReader **reader)
Definition cachefile.cc:217
double BKE_cachefile_time_offset(const CacheFile *cache_file, double time, double fps)
Definition cachefile.cc:411
void BKE_cachefile_reader_open(CacheFile *cache_file, CacheReader **reader, Object *object, const char *object_path)
Definition cachefile.cc:166
Camera data-block and utility functions.
void BKE_camera_params_init(CameraParams *params)
void BKE_camera_params_from_object(CameraParams *params, const struct Object *cam_ob)
void(* ConstraintIDFunc)(struct bConstraint *con, struct ID **idpoin, bool is_reference, void *userdata)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
void * CustomData_bmesh_get(const CustomData *data, void *block, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dv, int defgroup)
Definition deform.cc:795
int BKE_object_defgroup_name_index(const Object *ob, blender::StringRef name)
Definition deform.cc:585
display list (or rather multi purpose list) stuff.
DispList * BKE_displist_find(struct ListBase *lb, int type)
Definition displist.cc:71
@ DL_VERTS
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
void BKE_driver_target_matrix_to_rot_channels(float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
@ G_FLAG_SCRIPT_AUTOEXEC
@ G_DEBUG
#define IDP_BlendDataRead(reader, prop)
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1227
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:861
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1437
void id_lib_extern(ID *id)
Definition lib_id.cc:283
@ LIB_ID_COPY_NO_LIB_OVERRIDE_LOCAL_DATA_FLAG
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void id_us_plus(ID *id)
Definition lib_id.cc:351
void id_us_min(ID *id)
Definition lib_id.cc:359
@ IDWALK_DO_DEPRECATED_POINTERS
@ IDWALK_NOP
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
General operations, lookup, etc. for blender objects.
void BKE_object_where_is_calc_mat4(const Object *ob, float r_obmat[4][4])
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
void BKE_object_to_mat4(const Object *ob, float r_mat[4][4])
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2331
bool BKE_shrinkwrap_project_normal(char options, const float vert[3], const float dir[3], float ray_radius, const SpaceTransform *transf, ShrinkwrapTreeData *tree, BVHTreeRayHit *hit)
void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
void BKE_shrinkwrap_snap_point_to_surface(const ShrinkwrapTreeData *tree, const SpaceTransform *transform, int mode, int hit_idx, const float hit_co[3], const float hit_no[3], float goal_dist, const float point_co[3], float r_point_co[3])
#define NULL_BVHTreeFromMesh
void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree, const SpaceTransform *transform, int tri_idx, const float hit_co[3], const float hit_no[3], float r_no[3])
bool BKE_shrinkwrap_init_tree(ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
Definition shrinkwrap.cc:96
void BKE_shrinkwrap_find_nearest_surface(ShrinkwrapTreeData *tree, BVHTreeNearest *nearest, float co[3], int type)
struct MovieTrackingObject * BKE_tracking_object_get_camera(const struct MovieTracking *tracking)
void BKE_tracking_get_camera_object_matrix(const struct Object *camera_object, float mat[4][4])
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition tracking.cc:1966
struct MovieTrackingTrack * BKE_tracking_object_find_track_with_name(struct MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:1993
void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track, float framenr, float pos[2])
Definition tracking.cc:1507
void BKE_tracking_undistort_v2(struct MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
Definition tracking.cc:2448
void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking, struct MovieTrackingObject *tracking_object, float framenr, float mat[4][4])
Definition tracking.cc:2146
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BVH_RAYCAST_DIST_MAX
Definition BLI_kdopbvh.h:92
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
#define M_PI_2
MINLINE float square_f(float a)
MINLINE float pow3f(float x)
MINLINE float interpf(float target, float origin, float t)
#define M_PI
float mat4_to_volume_scale(const float mat[4][4])
void BLI_space_transform_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4])
void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], float t)
void mul_m3_v3(const float M[3][3], float r[3])
void madd_m4_m4m4fl(float R[4][4], const float A[4][4], const float B[4][4], float f)
void zero_m4(float m[4][4])
void mul_m4_fl(float R[4][4], float f)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3])
void unit_m3(float m[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void loc_rot_size_to_mat4(float R[4][4], const float loc[3], const float rot[3][3], const float size[3])
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void rescale_m4(float mat[4][4], const float scale[3])
void loc_eulO_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3], short order)
void mul_m4_v3(const float M[4][4], float r[3])
void invert_m4_m4_safe(float inverse[4][4], const float mat[4][4])
void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize)
#define mul_m4_series(...)
void scale_m4_fl(float R[4][4], float scale)
void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4])
void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL()
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool is_negative_m4(const float mat[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4])
bool invert_m4(float mat[4][4])
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3])
void mat4_to_size(float size[3], const float M[4][4])
void transpose_m3(float R[3][3])
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3])
float determinant_m3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4])
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
void rotate_eulO(float beul[3], short order, char axis, float angle)
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
@ EULER_ORDER_DEFAULT
void mat4_to_eul(float eul[3], const float mat[4][4])
void quat_to_mat4(float m[4][4], const float q[4])
void dquat_to_mat4(float R[4][4], const DualQuat *dq)
void mat4_to_eulO(float eul[3], short order, const float m[4][4])
#define RAD2DEGF(_rad)
void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4])
void compatible_eul(float eul[3], const float oldrot[3])
void quat_apply_track(float quat[4], short axis, short upflag)
void eulO_to_mat3(float M[3][3], const float e[3], short order)
void add_weighted_dq_dq_pivot(DualQuat *dq_sum, const DualQuat *dq, const float pivot[3], float weight, bool compute_scale_matrix)
void normalize_dq(DualQuat *dq, float totweight)
void mat3_to_eulO(float eul[3], short order, const float m[3][3])
void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float mat[3][3])
void mat4_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float mat[4][4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_fl(float r[3], float f)
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define STRNCPY(dst, src)
Definition BLI_string.h:593
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
unsigned short ushort
unsigned int uint
#define CLAMP(a, b, c)
#define INIT_MINMAX(min, max)
#define UNUSED_VARS(...)
#define ELEM(...)
#define IS_EQF(a, b)
#define STREQ(a, b)
void * BLO_read_struct_by_name_array(BlendDataReader *reader, const char *struct_name, uint32_t items_num, const void *old_address)
Definition readfile.cc:4873
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition readfile.cc:4967
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define DATA_(msgid)
void BPY_pyconstraint_exec(bPythonConstraint *con, bConstraintOb *cob, ListBase *targets)
Definition stubs.cc:16
void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
Definition stubs.cc:21
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_id_tag_update(ID *id, unsigned int flags)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
float DEG_get_ctime(const Depsgraph *graph)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
ID * DEG_get_original_id(ID *id)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ IDP_GROUP
@ BONE_MULT_VG_ENV
@ BONE_CONNECTED
@ CACHE_FILE_TYPE_INVALID
@ CACHEFILE_TYPE_ALEMBIC
@ CACHEFILE_TYPE_USD
struct bStretchToConstraint bStretchToConstraint
@ CONSTRAINT_BBONE_SHAPE
@ CONSTRAINT_OFF
@ CONSTRAINT_OVERRIDE_LIBRARY_LOCAL
@ CONSTRAINT_SPACEONCE
@ CONSTRAINT_ACTIVE
@ CONSTRAINT_DISABLE
@ CONSTRAINT_BBONE_SHAPE_FULL
@ SIZELIKE_MULTIPLY
@ SIZELIKE_UNIFORM
@ SIZELIKE_OFFSET
struct bFollowTrackConstraint bFollowTrackConstraint
struct bActionConstraint bActionConstraint
@ CONSTRAINT_IK_POS
@ CONSTRAINT_IK_AUTO
@ CONSTRAINT_IK_STRETCH
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_TAR_CUSTOM_SPACE
@ ROTLIKE_MIX_OFFSET
@ ROTLIKE_MIX_BEFORE
@ ROTLIKE_MIX_AFTER
@ ROTLIKE_MIX_REPLACE
@ ROTLIKE_MIX_ADD
@ CONSTRAINT_TYPE_TRACKTO
@ CONSTRAINT_TYPE_PIVOT
@ CONSTRAINT_TYPE_CHILDOF
@ CONSTRAINT_TYPE_TRANSFORM
@ CONSTRAINT_TYPE_FOLLOWTRACK
@ CONSTRAINT_TYPE_OBJECTSOLVER
@ CONSTRAINT_TYPE_ARMATURE
@ CONSTRAINT_TYPE_LOCLIKE
@ CONSTRAINT_TYPE_SHRINKWRAP
@ CONSTRAINT_TYPE_MINMAX
@ CONSTRAINT_TYPE_ROTLIMIT
@ CONSTRAINT_TYPE_CAMERASOLVER
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_PYTHON
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_NULL
@ NUM_CONSTRAINT_TYPES
@ CONSTRAINT_TYPE_DISTLIMIT
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_LOCLIMIT
@ CONSTRAINT_TYPE_CLAMPTO
@ CONSTRAINT_TYPE_LOCKTRACK
@ CONSTRAINT_TYPE_SIZELIMIT
@ CONSTRAINT_TYPE_ACTION
@ CONSTRAINT_TYPE_FOLLOWPATH
@ CONSTRAINT_TYPE_STRETCHTO
@ CONSTRAINT_TYPE_SIZELIKE
@ CONSTRAINT_TYPE_SAMEVOL
@ CONSTRAINT_TYPE_DAMPTRACK
@ CONSTRAINT_TYPE_TRANSFORM_CACHE
@ CONSTRAINT_OBTYPE_OBJECT
@ CONSTRAINT_OBTYPE_BONE
struct bShrinkwrapConstraint bShrinkwrapConstraint
@ LIMITDIST_INSIDE
@ LIMITDIST_OUTSIDE
@ CONSTRAINT_ARMATURE_QUATERNION
@ CONSTRAINT_ARMATURE_ENVELOPE
@ CONSTRAINT_ARMATURE_CUR_LOCATION
struct bLocateLikeConstraint bLocateLikeConstraint
struct bChildOfConstraint bChildOfConstraint
@ CAMERASOLVER_ACTIVECLIP
struct bSplineIKConstraint bSplineIKConstraint
@ FOLLOWTRACK_USE_UNDISTORTION
@ FOLLOWTRACK_USE_3D_POSITION
@ FOLLOWTRACK_ACTIVECLIP
struct bLockTrackConstraint bLockTrackConstraint
@ ACTCON_BONE_USE_OBJECT_ACTION
@ ACTCON_USE_EVAL_TIME
struct bTransformConstraint bTransformConstraint
@ LIMIT_ROT_LEGACY_BEHAVIOR
struct bSizeLimitConstraint bSizeLimitConstraint
struct bArmatureConstraint bArmatureConstraint
struct bDistLimitConstraint bDistLimitConstraint
#define CON_SHRINKWRAP_PROJECT_CULL_MASK
struct bMinMaxConstraint bMinMaxConstraint
@ TRANS_MIXSCALE_MULTIPLY
@ TRANS_MIXSCALE_REPLACE
@ CONSTRAINT_SPLINEIK_YS_FIT_CURVE
@ TRANS_MIXLOC_ADD
@ TRANS_MIXLOC_REPLACE
@ CONSTRAINT_SPACE_CUSTOM
@ CONSTRAINT_SPACE_POSE
@ CONSTRAINT_SPACE_WORLD
@ CONSTRAINT_SPACE_OWNLOCAL
@ CONSTRAINT_SPACE_LOCAL
@ CONSTRAINT_SPACE_PARLOCAL
struct bTrackToConstraint bTrackToConstraint
@ ACTCON_MIX_BEFORE
@ ACTCON_MIX_BEFORE_SPLIT
@ ACTCON_MIX_BEFORE_FULL
@ ACTCON_MIX_AFTER_FULL
@ ACTCON_MIX_AFTER_SPLIT
@ ACTCON_MIX_AFTER
@ FOLLOWPATH_FOLLOW
@ FOLLOWPATH_RADIUS
@ FOLLOWPATH_STATIC
struct bSizeLikeConstraint bSizeLikeConstraint
struct bClampToConstraint bClampToConstraint
struct bSameVolumeConstraint bSameVolumeConstraint
@ CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE
struct bTransLikeConstraint bTransLikeConstraint
struct bLocLimitConstraint bLocLimitConstraint
@ TRANSLIKE_MIX_AFTER
@ TRANSLIKE_MIX_AFTER_FULL
@ TRANSLIKE_MIX_BEFORE
@ TRANSLIKE_MIX_BEFORE_SPLIT
@ TRANSLIKE_MIX_REPLACE
@ TRANSLIKE_MIX_BEFORE_FULL
@ TRANSLIKE_MIX_AFTER_SPLIT
struct bRotateLikeConstraint bRotateLikeConstraint
@ OBJECTSOLVER_ACTIVECLIP
@ OBJECTSOLVER_SET_INVERSE
@ CON_SHRINKWRAP_PROJECT_INVERT_CULL
@ CON_SHRINKWRAP_PROJECT_OPPOSITE
@ CON_SHRINKWRAP_TRACK_NORMAL
@ CLAMPTO_CYCLIC
struct bTransformCacheConstraint bTransformCacheConstraint
@ PIVOTCON_AXIS_X
@ PIVOTCON_AXIS_Z
@ PIVOTCON_AXIS_NONE
@ SAMEVOL_SINGLE_AXIS
@ SAMEVOL_STRICT
@ SAMEVOL_UNIFORM
@ PIVOTCON_FLAG_OFFSET_ABS
@ CONSTRAINT_EULER_AUTO
@ TRANSLIKE_REMOVE_TARGET_SHEAR
@ LIMITDIST_USESOFT
@ STRETCHTOCON_USE_BULGE_MAX
@ STRETCHTOCON_USE_BULGE_MIN
@ ROTLIKE_Y_INVERT
@ ROTLIKE_Z_INVERT
@ ROTLIKE_X_INVERT
struct bObjectSolverConstraint bObjectSolverConstraint
@ LOCLIKE_Z_INVERT
@ LOCLIKE_Y_INVERT
@ LOCLIKE_OFFSET
@ LOCLIKE_X_INVERT
struct bKinematicConstraint bKinematicConstraint
struct bRotLimitConstraint bRotLimitConstraint
struct bPythonConstraint bPythonConstraint
struct bFollowPathConstraint bFollowPathConstraint
struct bCameraSolverConstraint bCameraSolverConstraint
struct bPivotConstraint bPivotConstraint
@ CHILDOF_SET_INVERSE
@ TRANS_ROTATION
@ TRANS_LOCATION
@ TRANS_MIXROT_REPLACE
@ TRANS_MIXROT_ADD
@ TRANS_MIXROT_BEFORE
@ TRANS_MIXROT_AFTER
struct bDampTrackConstraint bDampTrackConstraint
@ FOLLOWTRACK_FRAME_CROP
@ FOLLOWTRACK_FRAME_STRETCH
@ CU_PATH_CLAMP
@ CU_NURB_CYCLIC
@ CD_MDEFORMVERT
@ MOD_SHRINKWRAP_TARGET_PROJECT
@ MOD_SHRINKWRAP_NEAREST_VERTEX
@ MOD_SHRINKWRAP_PROJECT
@ MOD_SHRINKWRAP_NEAREST_SURFACE
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_POSX
@ OB_NEGZ
@ OB_POSY
@ OB_NEGX
@ OB_POSZ
@ OB_NEGY
#define FPS
@ UI_PANEL_DATA_EXPAND_ROOT
@ UI_SUBPANEL_DATA_EXPAND_2
@ UI_SUBPANEL_DATA_EXPAND_1
@ TRACK_HAS_BUNDLE
@ TRACKING_OBJECT_CAMERA
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
btVector3 orth(const btVector3 &v)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint ** constraints
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
local_group_size(16, 16) .push_constant(Type b
static void followpath_get_tarmat(Depsgraph *, bConstraint *con, bConstraintOb *, bConstraintTarget *ct, float)
static void add_new_constraint_to_list(Object *ob, bPoseChannel *pchan, bConstraint *con)
static void minmax_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void minmax_new_data(void *cdata)
static bConstraint * constraint_find_original_for_update(bConstraintOb *cob, bConstraint *con)
static void stretchto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void minmax_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void followtrack_fit_frame(FollowTrackContext *context, const int clip_width, const int clip_height, float marker_position[2])
static void samevolume_new_data(void *cdata)
bool BKE_constraint_apply_and_remove_for_pose(Depsgraph *depsgraph, Scene *scene, ListBase *constraints, Object *ob, bConstraint *con, bPoseChannel *pchan)
static float followtrack_distance_from_viewplane_get(FollowTrackContext *context, bConstraintOb *cob)
void BKE_constraint_targets_for_solving_get(Depsgraph *depsgraph, bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
static void pycon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void damptrack_do_transform(float matrix[4][4], const float tarvec[3], int track_axis)
static int kinematic_get_tars(bConstraint *con, ListBase *list)
static bConstraintTypeInfo CTI_TRANSFORM_CACHE
static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
static void stretchto_new_data(void *cdata)
bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstraint *con)
void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern)
static bConstraintTypeInfo CTI_ROTLIKE
bool BKE_constraint_target_uses_bbone(bConstraint *con, bConstraintTarget *ct)
static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void transformcache_new_data(void *cdata)
static int followpath_get_tars(bConstraint *con, ListBase *list)
static void kinematic_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void loclike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
static bConstraintTypeInfo CTI_ROTLIMIT
static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *context, bConstraintOb *cob)
static void sizelike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static int loclike_get_tars(bConstraint *con, ListBase *list)
static void transform_new_data(void *cdata)
static void armdef_accumulate_bone(const bConstraintTarget *ct, const bPoseChannel *pchan, const float wco[3], const bool force_envelope, float *r_totweight, float r_sum_mat[4][4], DualQuat *r_sum_dq)
static void transformcache_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void translike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void transformcache_copy(bConstraint *con, bConstraint *srccon)
bConstraint * BKE_constraint_copy_for_object(Object *ob, bConstraint *src)
static int minmax_get_tars(bConstraint *con, ListBase *list)
static void followpath_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void followtrack_evaluate_using_3d_position_camera(FollowTrackContext *context, bConstraintOb *cob)
static bConstraintTypeInfo CTI_STRETCHTO
bConstraint * BKE_constraint_copy_for_pose(Object *ob, bPoseChannel *pchan, bConstraint *src)
static bConstraint * constraint_list_find_from_target(ListBase *constraints, bConstraintTarget *tgt)
static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
static bConstraintTypeInfo CTI_TRANSFORM
static void vectomat(const float vec[3], const float target_up[3], short axis, short upflag, short flags, float m[3][3])
static bConstraintTypeInfo CTI_DAMPTRACK
static int pycon_get_tars(bConstraint *con, ListBase *list)
static int stretchto_get_tars(bConstraint *con, ListBase *list)
static void rotlike_new_data(void *cdata)
static void clampto_get_tarmat(Depsgraph *, bConstraint *, bConstraintOb *, bConstraintTarget *ct, float)
static void followtrack_evaluate_using_3d_position(FollowTrackContext *context, bConstraintOb *cob)
static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void followpath_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void con_extern_cb(bConstraint *, ID **idpoin, bool, void *)
static bool is_custom_space_needed(bConstraint *con)
static bConstraintTypeInfo CTI_CLAMPTO
static void pivotcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static bConstraintTypeInfo CTI_SAMEVOL
static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
static void splineik_copy(bConstraint *con, bConstraint *srccon)
static void armdef_get_tarmat(Depsgraph *, bConstraint *, bConstraintOb *, bConstraintTarget *ct, float)
static int damptrack_get_tars(bConstraint *con, ListBase *list)
static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static int basis_cross(int n, int m)
static bConstraintTypeInfo CTI_TRACKTO
static void childof_new_data(void *cdata)
void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user)
static bConstraintTypeInfo CTI_KINEMATIC
static int splineik_get_tars(bConstraint *con, ListBase *list)
static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void distlimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void default_get_tarmat_full_bbone(Depsgraph *, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float)
void BKE_constraint_unique_name(bConstraint *con, ListBase *list)
static bConstraintTypeInfo CTI_TRANSLIKE
static bConstraintTypeInfo CTI_FOLLOWPATH
static void shrinkwrap_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void loclimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
void BKE_constraints_active_set(ListBase *list, bConstraint *con)
static bConstraintTypeInfo CTI_SIZELIKE
static void shrinkwrap_get_tarmat(Depsgraph *, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float)
bool BKE_constraint_apply_and_remove_for_object(Depsgraph *depsgraph, Scene *scene, ListBase *constraints, Object *ob, bConstraint *con)
static void actcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void splineik_new_data(void *cdata)
void BKE_constraints_clear_evalob(bConstraintOb *cob)
static void actcon_get_tarmat(Depsgraph *depsgraph, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float)
static void pycon_new_data(void *cdata)
static MovieClip * followtrack_tracking_clip_get(bConstraint *con, bConstraintOb *cob)
static void locktrack_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static bConstraintTypeInfo CTI_CHILDOF
static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void followpath_new_data(void *cdata)
static void pycon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void transform_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void camerasolver_new_data(void *cdata)
static int translike_get_tars(bConstraint *con, ListBase *list)
static bConstraintTypeInfo CTI_SIZELIMIT
static void armdef_accumulate_matrix(const float obmat[4][4], const float iobmat[4][4], const float basemat[4][4], const float bonemat[4][4], const float pivot[3], const float weight, float r_sum_mat[4][4], DualQuat *r_sum_dq)
void BKE_constraint_target_matrix_get(Depsgraph *depsgraph, Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
static void clampto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static bConstraintTypeInfo CTI_DISTLIMIT
static bConstraint * add_new_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type)
static bConstraintTypeInfo CTI_CAMERASOLVER
static bConstraintTypeInfo CTI_LOCLIKE
static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void trackto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void objectsolver_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static bConstraintTypeInfo CTI_LOCLIMIT
void BKE_constraints_solve(Depsgraph *depsgraph, ListBase *conlist, bConstraintOb *cob, float ctime)
static void trackto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void camerasolver_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void armdef_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
bConstraint * BKE_constraints_find_name(ListBase *list, const char *name)
static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static bConstraint * add_new_constraint_internal(const char *name, short type)
static void loclike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void constraint_copy_data_ex(bConstraint *dst, bConstraint *src, const int flag, const bool do_extern)
static bool followtrack_context_init(FollowTrackContext *context, bConstraint *con, bConstraintOb *cob)
void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, bConstraintOb *cob, float mat[4][4], short from, short to, const bool keep_scale)
bConstraint * BKE_constraint_duplicate_ex(bConstraint *src, const int flag, const bool do_extern)
static void con_unlink_refs_cb(bConstraint *, ID **idpoin, bool is_reference, void *)
static void loclike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static int childof_get_tars(bConstraint *con, ListBase *list)
void BKE_constraint_panel_expand(bConstraint *con)
static void splineik_get_tarmat(Depsgraph *, bConstraint *, bConstraintOb *, bConstraintTarget *ct, float)
static int actcon_get_tars(bConstraint *con, ListBase *list)
static void shrinkwrap_new_data(void *cdata)
static void objectsolver_new_data(void *cdata)
static void con_fix_copied_refs_cb(bConstraint *, ID **idpoin, bool is_reference, void *)
static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[4][4])
static void splineik_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void distlimit_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void rotlike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static bConstraintTypeInfo CTI_FOLLOWTRACK
static void armdef_copy(bConstraint *con, bConstraint *srccon)
static bConstraintTypeInfo CTI_SHRINKWRAP
static void kinematic_new_data(void *cdata)
static bConstraintTypeInfo CTI_ARMATURE
static void sizelike_new_data(void *cdata)
void BKE_constraints_copy_ex(ListBase *dst, const ListBase *src, const int flag, bool do_extern)
static void childof_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
bool BKE_constraint_apply_for_pose(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
static int sizelike_get_tars(bConstraint *con, ListBase *list)
static void stretchto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
bConstraint * BKE_constraint_add_for_pose(Object *ob, bPoseChannel *pchan, const char *name, short type)
void BKE_constraints_free_ex(ListBase *list, bool do_id_user)
static int rotlike_get_tars(bConstraint *con, ListBase *list)
static void translike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
bool BKE_constraint_remove(ListBase *list, bConstraint *con)
const bConstraintTypeInfo * BKE_constraint_typeinfo_get(bConstraint *con)
static void constraints_init_typeinfo()
static void pycon_get_tarmat(Depsgraph *, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float)
static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void rotlike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void followpath_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void pycon_copy(bConstraint *con, bConstraint *srccon)
static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void locktrack_new_data(void *cdata)
static int locktrack_get_tars(bConstraint *con, ListBase *list)
static void shrinkwrap_evaluate(bConstraint *, bConstraintOb *cob, ListBase *targets)
static void kinematic_get_tarmat(Depsgraph *, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float)
static void shrinkwrap_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
#define SINGLETARGETNS_GET_TARS(con, datatar, ct, list)
static float clamp_angle(const float angle, const float min, const float max)
void BKE_constraint_custom_object_space_init(bConstraintOb *cob, bConstraint *con)
static int distlimit_get_tars(bConstraint *con, ListBase *list)
static bConstraintTypeInfo CTI_SPLINEIK
static void splineik_free(bConstraint *con)
static int pivotcon_get_tars(bConstraint *con, ListBase *list)
static void trackto_new_data(void *cdata)
void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, const int flag, void *userdata)
static void followtrack_undistort_if_needed(FollowTrackContext *context, const int clip_width, const int clip_height, float marker_position[2])
bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con)
bConstraint * BKE_constraints_active_get(ListBase *list)
void BKE_constraint_targets_flush(bConstraint *con, ListBase *targets, bool no_copy)
static float wrap_rad_angle(const float angle)
static void damptrack_new_data(void *cdata)
static void damptrack_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
bConstraintOb * BKE_constraints_make_evalob(Depsgraph *depsgraph, Scene *scene, Object *ob, void *subdata, short datatype)
static Object * followtrack_camera_object_get(bConstraint *con, bConstraintOb *cob)
static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static void followtrack_evaluate_using_2d_position(FollowTrackContext *context, bConstraintOb *cob)
static void constraint_target_to_mat4(Object *ob, const char *substring, bConstraintOb *cob, float mat[4][4], short from, short to, short flag, float headtail)
static void contarget_get_lattice_mat(Object *ob, const char *substring, float mat[4][4])
static bConstraintTypeInfo CTI_MINMAX
static int shrinkwrap_get_tars(bConstraint *con, ListBase *list)
void BKE_constraints_free(ListBase *list)
static void pivotcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static short CTI_INIT
static bConstraint * constraint_find_original(Object *ob, bPoseChannel *pchan, bConstraint *con, Object **r_orig_ob)
static bConstraintTypeInfo * constraintsTypeInfo[NUM_CONSTRAINT_TYPES]
static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
static int armdef_get_tars(bConstraint *con, ListBase *list)
static void pycon_free(bConstraint *con)
static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *context, bConstraintOb *cob)
static void transformcache_free(bConstraint *con)
static void pivotcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static MovieTrackingObject * followtrack_tracking_object_get(bConstraint *con, bConstraintOb *cob)
static const float track_dir_vecs[6][3]
static CLG_LogRef LOG
static int trackto_get_tars(bConstraint *con, ListBase *list)
#define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, no_copy)
static void locktrack_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
int BKE_constraint_targets_get(bConstraint *con, ListBase *r_targets)
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void minmax_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
void BKE_constraint_free_data(bConstraint *con)
const bConstraintTypeInfo * BKE_constraint_typeinfo_from_type(int type)
bConstraint * BKE_constraint_find_from_target(Object *ob, bConstraintTarget *tgt, bPoseChannel **r_pchan)
#define VALID_CONS_TARGET(ct)
static void actcon_new_data(void *cdata)
static void loclike_new_data(void *cdata)
bConstraint * BKE_constraint_add_for_object(Object *ob, const char *name, short type)
static void armdef_free(bConstraint *con)
static void damptrack_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void con_invoke_id_looper(const bConstraintTypeInfo *cti, bConstraint *con, ConstraintIDFunc func, const int flag, void *userdata)
#define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list)
static bConstraintTypeInfo CTI_LOCKTRACK
void BKE_constraint_blend_write(BlendWriter *writer, ListBase *conlist)
static int transform_get_tars(bConstraint *con, ListBase *list)
void BKE_constraint_blend_read_data(BlendDataReader *reader, ID *id_owner, ListBase *lb)
static bConstraintTypeInfo CTI_OBJECTSOLVER
static bConstraintTypeInfo CTI_PIVOT
bool BKE_constraint_apply_for_object(Depsgraph *depsgraph, Scene *scene, Object *ob, bConstraint *con)
static bConstraintTypeInfo CTI_PYTHON
static bConstraintTypeInfo CTI_ACTION
static int clampto_get_tars(bConstraint *con, ListBase *list)
static void rotlimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *)
static void kinematic_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void distlimit_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
static void clampto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void followtrack_new_data(void *cdata)
#define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, no_copy)
static void childof_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
static void distlimit_new_data(void *cdata)
static void default_get_tarmat(Depsgraph *, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float)
static void transform_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
#define printf
const Depsgraph * depsgraph
#define expf(x)
#define powf(x, y)
#define asinf(x)
#define ceilf(x)
#define atanf(x)
#define acosf(x)
#define offsetof(t, d)
#define fabsf(x)
#define sqrtf(x)
int len
KDTree_3d * tree
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define rot(x, k)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
int count
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
#define G(x, y, z)
void USD_get_transform(CacheReader *reader, float r_mat_world[4][4], float time, float scale)
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
void * data
float co[3]
float no[3]
BMHeader head
CustomData vdata
float vec[4]
BVHTree_RayCastCallback raycast_callback
float arm_head[3]
float arm_tail[3]
float arm_mat[4][4]
ListBase nurb
float ctime
float * verts
MovieTracking * tracking
MovieTrackingObject * tracking_object
MovieTrackingTrack * track
Depsgraph * depsgraph
char type
Definition DNA_ID.h:154
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
struct MDeformVert * dvert
struct BPoint * def
void * last
void * first
float mat[4][4]
CustomData vert_data
short flagu
ListBase constraints
struct bPose * pose
ObjectRuntimeHandle * runtime
float constinv[4][4]
float parentinv[4][4]
struct Object * parent
struct MovieClip * clip
struct Object * camera
float startmat[4][4]
float matrix[4][4]
float space_obj_world_matrix[4][4]
struct bPoseChannel * pchan
struct Scene * scene
struct Object * ob
struct Depsgraph * depsgraph
void(* id_looper)(struct bConstraint *con, ConstraintIDFunc func, void *userdata)
int(* get_constraint_targets)(struct bConstraint *con, struct ListBase *list)
void(* evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets)
void(* flush_constraint_targets)(struct bConstraint *con, struct ListBase *list, bool no_copy)
void(* copy_data)(struct bConstraint *con, struct bConstraint *src)
void(* get_target_matrix)(struct Depsgraph *depsgraph, struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime)
void(* free_data)(struct bConstraint *con)
void(* new_data)(void *cdata)
struct Object * space_object
struct bConstraint * prev
struct bConstraint * next
struct Mat4 * bbone_deform_mats
struct Mat4 * bbone_pose_mats
struct Mat4 * bbone_rest_mats
struct Bone * bone
float chan_mat[4][4]
float constinv[4][4]
struct bPoseChannel_Runtime runtime
struct bPoseChannel * orig_pchan
float pose_mat[4][4]
ListBase chanbase
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:138