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