2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): 2007, Joshua Leung, major recode
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/constraint.c
39 #include "MEM_guardedalloc.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_listbase.h"
44 #include "BLI_editVert.h"
45 #include "BLI_utildefines.h"
47 #include "DNA_armature_types.h"
48 #include "DNA_constraint_types.h"
49 #include "DNA_modifier_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_action_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_lattice_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_text_types.h"
60 #include "BKE_action.h"
61 #include "BKE_anim.h" /* for the curve calculation part */
62 #include "BKE_armature.h"
63 #include "BKE_blender.h"
64 #include "BKE_constraint.h"
65 #include "BKE_displist.h"
66 #include "BKE_deform.h"
67 #include "BKE_DerivedMesh.h" /* for geometry targets */
68 #include "BKE_cdderivedmesh.h" /* for geometry targets */
69 #include "BKE_object.h"
71 #include "BKE_global.h"
72 #include "BKE_library.h"
73 #include "BKE_idprop.h"
75 #include "BKE_shrinkwrap.h"
77 #include "BKE_tessmesh.h"
80 #include "BPY_extern.h"
84 #define M_PI 3.14159265358979323846
89 /* ************************ Constraints - General Utilities *************************** */
90 /* These functions here don't act on any specific constraints, and are therefore should/will
91 * not require any of the special function-pointers afforded by the relevant constraint
95 /* -------------- Naming -------------- */
97 /* Find the first available, non-duplicate name for a given constraint */
98 void unique_constraint_name (bConstraint *con, ListBase *list)
100 BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), sizeof(con->name));
103 /* ----------------- Evaluation Loop Preparation --------------- */
105 /* package an object/bone for use in constraint evaluation */
106 /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
107 bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata, short datatype)
111 /* create regardless of whether we have any data! */
112 cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb");
114 /* for system time, part of deglobalization, code nicer later with local time (ton) */
117 /* based on type of available data */
119 case CONSTRAINT_OBTYPE_OBJECT:
121 /* disregard subdata... calloc should set other values right */
124 cob->type = datatype;
125 cob->rotOrder = EULER_ORDER_DEFAULT; // TODO: when objects have rotation order too, use that
126 copy_m4_m4(cob->matrix, ob->obmat);
129 unit_m4(cob->matrix);
131 copy_m4_m4(cob->startmat, cob->matrix);
134 case CONSTRAINT_OBTYPE_BONE:
136 /* only set if we have valid bone, otherwise default */
139 cob->pchan = (bPoseChannel *)subdata;
140 cob->type = datatype;
142 if (cob->pchan->rotmode > 0) {
143 /* should be some type of Euler order */
144 cob->rotOrder= cob->pchan->rotmode;
147 /* Quats, so eulers should just use default order */
148 cob->rotOrder= EULER_ORDER_DEFAULT;
151 /* matrix in world-space */
152 mul_m4_m4m4(cob->matrix, cob->pchan->pose_mat, ob->obmat);
155 unit_m4(cob->matrix);
157 copy_m4_m4(cob->startmat, cob->matrix);
161 default: /* other types not yet handled */
162 unit_m4(cob->matrix);
163 unit_m4(cob->startmat);
170 /* cleanup after constraint evaluation */
171 void constraints_clear_evalob (bConstraintOb *cob)
173 float delta[4][4], imat[4][4];
175 /* prevent crashes */
179 /* calculate delta of constraints evaluation */
180 invert_m4_m4(imat, cob->startmat);
181 mul_m4_m4m4(delta, imat, cob->matrix);
183 /* copy matrices back to source */
185 case CONSTRAINT_OBTYPE_OBJECT:
187 /* cob->ob might not exist! */
189 /* copy new ob-matrix back to owner */
190 copy_m4_m4(cob->ob->obmat, cob->matrix);
192 /* copy inverse of delta back to owner */
193 invert_m4_m4(cob->ob->constinv, delta);
197 case CONSTRAINT_OBTYPE_BONE:
199 /* cob->ob or cob->pchan might not exist */
200 if (cob->ob && cob->pchan) {
201 /* copy new pose-matrix back to owner */
202 mul_m4_m4m4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
204 /* copy inverse of delta back to owner */
205 invert_m4_m4(cob->pchan->constinv, delta);
211 /* free tempolary struct */
215 /* -------------- Space-Conversion API -------------- */
217 /* This function is responsible for the correct transformations/conversions
218 * of a matrix from one space to another for constraint evaluation.
219 * For now, this is only implemented for Objects and PoseChannels.
221 void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4], short from, short to)
224 float diff_mat[4][4];
227 /* prevent crashes in these unlikely events */
228 if (ob==NULL || mat==NULL) return;
229 /* optimise trick - check if need to do anything */
230 if (from == to) return;
232 /* are we dealing with pose-channels or objects */
236 case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */
239 invert_m4_m4(imat, ob->obmat);
240 copy_m4_m4(tempmat, mat);
241 mul_m4_m4m4(mat, tempmat, imat);
243 /* use pose-space as stepping stone for other spaces... */
244 if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
245 /* call self with slightly different values */
246 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
250 case CONSTRAINT_SPACE_POSE: /* ---------- FROM POSESPACE ---------- */
253 if (to == CONSTRAINT_SPACE_WORLD) {
254 copy_m4_m4(tempmat, mat);
255 mul_m4_m4m4(mat, tempmat, ob->obmat);
258 else if (to == CONSTRAINT_SPACE_LOCAL) {
261 float offs_bone[4][4];
263 /* construct offs_bone the same way it is done in armature.c */
264 copy_m4_m3(offs_bone, pchan->bone->bone_mat);
265 copy_v3_v3(offs_bone[3], pchan->bone->head);
266 offs_bone[3][1]+= pchan->bone->parent->length;
268 if (pchan->bone->flag & BONE_HINGE) {
269 /* pose_mat = par_pose-space_location * chan_mat */
272 /* the rotation of the parent restposition */
273 copy_m4_m4(tmat, pchan->bone->parent->arm_mat);
275 /* the location of actual parent transform */
276 copy_v3_v3(tmat[3], offs_bone[3]);
277 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
278 mul_m4_v3(pchan->parent->pose_mat, tmat[3]);
280 mul_m4_m4m4(diff_mat, offs_bone, tmat);
281 invert_m4_m4(imat, diff_mat);
284 /* pose_mat = par_pose_mat * bone_mat * chan_mat */
285 mul_m4_m4m4(diff_mat, offs_bone, pchan->parent->pose_mat);
286 invert_m4_m4(imat, diff_mat);
290 /* pose_mat = chan_mat * arm_mat */
291 invert_m4_m4(imat, pchan->bone->arm_mat);
294 copy_m4_m4(tempmat, mat);
295 mul_m4_m4m4(mat, tempmat, imat);
298 /* pose to local with parent */
299 else if (to == CONSTRAINT_SPACE_PARLOCAL) {
301 invert_m4_m4(imat, pchan->bone->arm_mat);
302 copy_m4_m4(tempmat, mat);
303 mul_m4_m4m4(mat, tempmat, imat);
308 case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */
310 /* local to pose - do inverse procedure that was done for pose to local */
312 /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
314 float offs_bone[4][4];
316 /* construct offs_bone the same way it is done in armature.c */
317 copy_m4_m3(offs_bone, pchan->bone->bone_mat);
318 copy_v3_v3(offs_bone[3], pchan->bone->head);
319 offs_bone[3][1]+= pchan->bone->parent->length;
321 if (pchan->bone->flag & BONE_HINGE) {
322 /* pose_mat = par_pose-space_location * chan_mat */
325 /* the rotation of the parent restposition */
326 copy_m4_m4(tmat, pchan->bone->parent->arm_mat);
328 /* the location of actual parent transform */
329 copy_v3_v3(tmat[3], offs_bone[3]);
330 zero_v3(offs_bone[3]);
331 mul_m4_v3(pchan->parent->pose_mat, tmat[3]);
333 mul_m4_m4m4(diff_mat, offs_bone, tmat);
334 copy_m4_m4(tempmat, mat);
335 mul_m4_m4m4(mat, tempmat, diff_mat);
338 /* pose_mat = par_pose_mat * bone_mat * chan_mat */
339 mul_m4_m4m4(diff_mat, offs_bone, pchan->parent->pose_mat);
340 copy_m4_m4(tempmat, mat);
341 mul_m4_m4m4(mat, tempmat, diff_mat);
345 copy_m4_m4(diff_mat, pchan->bone->arm_mat);
347 copy_m4_m4(tempmat, mat);
348 mul_m4_m4m4(mat, tempmat, diff_mat);
352 /* use pose-space as stepping stone for other spaces */
353 if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) {
354 /* call self with slightly different values */
355 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
359 case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */
361 /* local + parent to pose */
363 copy_m4_m4(diff_mat, pchan->bone->arm_mat);
364 copy_m4_m4(tempmat, mat);
365 mul_m4_m4m4(mat, diff_mat, tempmat);
368 /* use pose-space as stepping stone for other spaces */
369 if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
370 /* call self with slightly different values */
371 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
379 if (from==CONSTRAINT_SPACE_WORLD && to==CONSTRAINT_SPACE_LOCAL) {
380 /* check if object has a parent */
382 /* 'subtract' parent's effects from owner */
383 mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
384 invert_m4_m4(imat, diff_mat);
385 copy_m4_m4(tempmat, mat);
386 mul_m4_m4m4(mat, tempmat, imat);
389 /* Local space in this case will have to be defined as local to the owner's
390 * transform-property-rotated axes. So subtract this rotation component.
392 object_to_mat4(ob, diff_mat);
393 normalize_m4(diff_mat);
394 zero_v3(diff_mat[3]);
396 invert_m4_m4(imat, diff_mat);
397 copy_m4_m4(tempmat, mat);
398 mul_m4_m4m4(mat, tempmat, imat);
401 else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) {
402 /* check that object has a parent - otherwise this won't work */
404 /* 'add' parent's effect back to owner */
405 copy_m4_m4(tempmat, mat);
406 mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat);
407 mul_m4_m4m4(mat, tempmat, diff_mat);
410 /* Local space in this case will have to be defined as local to the owner's
411 * transform-property-rotated axes. So add back this rotation component.
413 object_to_mat4(ob, diff_mat);
414 normalize_m4(diff_mat);
415 zero_v3(diff_mat[3]);
417 copy_m4_m4(tempmat, mat);
418 mul_m4_m4m4(mat, tempmat, diff_mat);
424 /* ------------ General Target Matrix Tools ---------- */
426 /* function that sets the given matrix based on given vertex group in mesh */
427 static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat[][4])
429 DerivedMesh *dm = NULL;
431 BMEditMesh *em = me->edit_btmesh;
432 float vec[3] = {0.0f, 0.0f, 0.0f};
433 float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3];
434 float imat[3][3], tmat[3][3];
438 /* initialize target matrix using target matrix */
439 copy_m4_m4(mat, ob->obmat);
441 /* get index of vertex group */
442 dgroup = defgroup_name_index(ob, substring);
443 if (dgroup < 0) return;
445 /* get DerivedMesh */
447 /* target is in editmode, so get a special derived mesh */
448 dm = CDDM_from_BMEditMesh(em, ob->data, 0);
452 /* when not in EditMode, use the 'final' derived mesh, depsgraph
453 * ensures we build with CD_MDEFORMVERT layer */
454 dm = (DerivedMesh *)ob->derivedFinal;
457 /* only continue if there's a valid DerivedMesh */
459 MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
460 int numVerts = dm->getNumVerts(dm);
464 /* check that dvert is a valid pointers (just in case) */
466 /* get the average of all verts with that are in the vertex-group */
467 for (i = 0; i < numVerts; i++) {
468 for (j = 0; j < dvert[i].totweight; j++) {
469 /* does this vertex belong to nominated vertex group? */
470 if (dvert[i].dw[j].def_nr == dgroup) {
471 dm->getVertCo(dm, i, co);
472 dm->getVertNo(dm, i, nor);
474 add_v3_v3(normal, nor);
483 /* calculate averages of normal and coordinates */
485 mul_v3_fl(vec, 1.0f / count);
486 mul_v3_fl(normal, 1.0f / count);
490 /* derive the rotation from the average normal:
491 * - code taken from transform_manipulator.c,
492 * calc_manipulator_stats, V3D_MANIP_NORMAL case
494 /* we need the transpose of the inverse for a normal... */
495 copy_m3_m4(imat, ob->obmat);
497 invert_m3_m3(tmat, imat);
499 mul_m3_v3(tmat, normal);
501 normalize_v3(normal);
502 copy_v3_v3(plane, tmat[1]);
504 copy_v3_v3(tmat[2], normal);
505 cross_v3_v3v3(tmat[0], normal, plane);
506 cross_v3_v3v3(tmat[1], tmat[2], tmat[0]);
508 copy_m4_m3(mat, tmat);
512 /* apply the average coordinate as the new location */
513 mul_v3_m4v3(mat[3], ob->obmat, vec);
517 /* free temporary DerivedMesh created (in EditMode case) */
522 /* function that sets the given matrix based on given vertex group in lattice */
523 static void contarget_get_lattice_mat (Object *ob, const char *substring, float mat[][4])
525 Lattice *lt= (Lattice *)ob->data;
527 DispList *dl = find_displist(&ob->disp, DL_VERTS);
528 float *co = dl?dl->verts:NULL;
529 BPoint *bp = lt->def;
531 MDeformVert *dvert = lt->dvert;
532 int tot_verts= lt->pntsu*lt->pntsv*lt->pntsw;
533 float vec[3]= {0.0f, 0.0f, 0.0f}, tvec[3];
534 int dgroup=0, grouped=0;
537 /* initialize target matrix using target matrix */
538 copy_m4_m4(mat, ob->obmat);
540 /* get index of vertex group */
541 dgroup = defgroup_name_index(ob, substring);
542 if (dgroup < 0) return;
543 if (dvert == NULL) return;
545 /* 1. Loop through control-points checking if in nominated vertex-group.
546 * 2. If it is, add it to vec to find the average point.
548 for (i=0; i < tot_verts; i++, dvert++) {
549 for (n= 0; n < dvert->totweight; n++) {
550 /* found match - vert is in vgroup */
551 if (dvert->dw[n].def_nr == dgroup) {
552 /* copy coordinates of point to temporary vector, then add to find average */
554 memcpy(tvec, co, 3*sizeof(float));
556 memcpy(tvec, bp->vec, 3*sizeof(float));
558 add_v3_v3(vec, tvec);
565 /* advance pointer to coordinate data */
570 /* find average location, then multiply by ob->obmat to find world-space location */
572 mul_v3_fl(vec, 1.0f / grouped);
573 mul_v3_m4v3(tvec, ob->obmat, vec);
575 /* copy new location to matrix */
576 copy_v3_v3(mat[3], tvec);
579 /* generic function to get the appropriate matrix for most target cases */
580 /* The cases where the target can be object data have not been implemented */
581 static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], short from, short to, float headtail)
584 if (!strlen(substring)) {
585 copy_m4_m4(mat, ob->obmat);
586 constraint_mat_convertspace(ob, NULL, mat, from, to);
588 /* Case VERTEXGROUP */
589 /* Current method just takes the average location of all the points in the
590 * VertexGroup, and uses that as the location value of the targets. Where
591 * possible, the orientation will also be calculated, by calculating an
592 * 'average' vertex normal, and deriving the rotaation from that.
594 * NOTE: EditMode is not currently supported, and will most likely remain that
595 * way as constraints can only really affect things on object/bone level.
597 else if (ob->type == OB_MESH) {
598 contarget_get_mesh_mat(ob, substring, mat);
599 constraint_mat_convertspace(ob, NULL, mat, from, to);
601 else if (ob->type == OB_LATTICE) {
602 contarget_get_lattice_mat(ob, substring, mat);
603 constraint_mat_convertspace(ob, NULL, mat, from, to);
609 pchan = get_pose_channel(ob->pose, substring);
611 /* Multiply the PoseSpace accumulation/final matrix for this
612 * PoseChannel by the Armature Object's Matrix to get a worldspace
615 if (headtail < 0.000001f) {
616 /* skip length interpolation if set to head */
617 mul_m4_m4m4(mat, pchan->pose_mat, ob->obmat);
620 float tempmat[4][4], loc[3];
622 /* interpolate along length of bone */
623 interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail);
625 /* use interpolated distance for subtarget */
626 copy_m4_m4(tempmat, pchan->pose_mat);
627 copy_v3_v3(tempmat[3], loc);
629 mul_m4_m4m4(mat, tempmat, ob->obmat);
633 copy_m4_m4(mat, ob->obmat);
635 /* convert matrix space as required */
636 constraint_mat_convertspace(ob, pchan, mat, from, to);
640 /* ************************* Specific Constraints ***************************** */
641 /* Each constraint defines a set of functions, which will be called at the appropriate
642 * times. In addition to this, each constraint should have a type-info struct, where
643 * its functions are attached for use.
646 /* Template for type-info data:
647 * - make a copy of this when creating new constraints, and just change the functions
648 * pointed to as necessary
649 * - although the naming of functions doesn't matter, it would help for code
650 * readability, to follow the same naming convention as is presented here
651 * - any functions that a constraint doesn't need to define, don't define
652 * for such cases, just use NULL
653 * - these should be defined after all the functions have been defined, so that
654 * forward-definitions/prototypes don't need to be used!
655 * - keep this copy #if-def'd so that future constraints can get based off this
658 static bConstraintTypeInfo CTI_CONSTRNAME = {
659 CONSTRAINT_TYPE_CONSTRNAME, /* type */
660 sizeof(bConstrNameConstraint), /* size */
661 "ConstrName", /* name */
662 "bConstrNameConstraint", /* struct name */
663 constrname_free, /* free data */
664 constrname_relink, /* relink data */
665 constrname_id_looper, /* id looper */
666 constrname_copy, /* copy data */
667 constrname_new_data, /* new data */
668 constrname_get_tars, /* get constraint targets */
669 constrname_flush_tars, /* flush constraint targets */
670 constrname_get_tarmat, /* get target matrix */
671 constrname_evaluate /* evaluate */
675 /* This function should be used for the get_target_matrix member of all
676 * constraints that are not picky about what happens to their target matrix.
678 static void default_get_tarmat (bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
680 if (VALID_CONS_TARGET(ct))
681 constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
686 /* This following macro should be used for all standard single-target *_get_tars functions
687 * to save typing and reduce maintainance woes.
688 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
689 * really just to help this code easier to read)
691 // TODO: cope with getting rotation order...
692 #define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \
694 ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
697 BLI_strncpy(ct->subtarget, datasubtarget, sizeof(ct->subtarget)); \
698 ct->space= con->tarspace; \
699 ct->flag= CONSTRAINT_TAR_TEMP; \
702 if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) { \
703 bPoseChannel *pchan= get_pose_channel(ct->tar->pose, ct->subtarget); \
704 ct->type = CONSTRAINT_OBTYPE_BONE; \
705 ct->rotOrder= (pchan) ? (pchan->rotmode) : EULER_ORDER_DEFAULT; \
707 else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { \
708 ct->type = CONSTRAINT_OBTYPE_VERT; \
709 ct->rotOrder = EULER_ORDER_DEFAULT; \
712 ct->type = CONSTRAINT_OBTYPE_OBJECT; \
713 ct->rotOrder= ct->tar->rotmode; \
717 BLI_addtail(list, ct); \
720 /* This following macro should be used for all standard single-target *_get_tars functions
721 * to save typing and reduce maintainance woes. It does not do the subtarget related operations
722 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
723 * really just to help this code easier to read)
725 // TODO: cope with getting rotation order...
726 #define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \
728 ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
731 ct->space= con->tarspace; \
732 ct->flag= CONSTRAINT_TAR_TEMP; \
734 if (ct->tar) ct->type = CONSTRAINT_OBTYPE_OBJECT; \
736 BLI_addtail(list, ct); \
739 /* This following macro should be used for all standard single-target *_flush_tars functions
740 * to save typing and reduce maintainance woes.
741 * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed)
742 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
743 * really just to help this code easier to read)
745 #define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, nocopy) \
748 bConstraintTarget *ctn = ct->next; \
751 BLI_strncpy(datasubtarget, ct->subtarget, sizeof(datasubtarget)); \
752 con->tarspace= (char)ct->space; \
755 BLI_freelinkN(list, ct); \
760 /* This following macro should be used for all standard single-target *_flush_tars functions
761 * to save typing and reduce maintainance woes. It does not do the subtarget related operations.
762 * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed)
763 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
764 * really just to help this code easier to read)
766 #define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, nocopy) \
769 bConstraintTarget *ctn = ct->next; \
772 con->tarspace= (char)ct->space; \
775 BLI_freelinkN(list, ct); \
780 /* --------- ChildOf Constraint ------------ */
782 static void childof_new_data (void *cdata)
784 bChildOfConstraint *data= (bChildOfConstraint *)cdata;
786 data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
787 CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
788 CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
789 unit_m4(data->invmat);
792 static void childof_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
794 bChildOfConstraint *data= con->data;
797 func(con, (ID**)&data->tar, userdata);
800 static int childof_get_tars (bConstraint *con, ListBase *list)
803 bChildOfConstraint *data= con->data;
804 bConstraintTarget *ct;
806 /* standard target-getting macro for single-target constraints */
807 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
815 static void childof_flush_tars (bConstraint *con, ListBase *list, short nocopy)
818 bChildOfConstraint *data= con->data;
819 bConstraintTarget *ct= list->first;
821 /* the following macro is used for all standard single-target constraints */
822 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
826 static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
828 bChildOfConstraint *data= con->data;
829 bConstraintTarget *ct= targets->first;
831 /* only evaluate if there is a target */
832 if (VALID_CONS_TARGET(ct)) {
835 /* simple matrix parenting */
836 if(data->flag == CHILDOF_ALL) {
838 /* multiply target (parent matrix) by offset (parent inverse) to get
839 * the effect of the parent that will be exherted on the owner
841 mul_m4_m4m4(parmat, data->invmat, ct->matrix);
843 /* now multiply the parent matrix by the owner matrix to get the
844 * the effect of this constraint (i.e. owner is 'parented' to parent)
846 mul_m4_m4m4(cob->matrix, cob->matrix, parmat);
849 float invmat[4][4], tempmat[4][4];
850 float loc[3], eul[3], size[3];
851 float loco[3], eulo[3], sizo[3];
853 /* get offset (parent-inverse) matrix */
854 copy_m4_m4(invmat, data->invmat);
856 /* extract components of both matrices */
857 copy_v3_v3(loc, ct->matrix[3]);
858 mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
859 mat4_to_size(size, ct->matrix);
861 copy_v3_v3(loco, invmat[3]);
862 mat4_to_eulO(eulo, cob->rotOrder, invmat);
863 mat4_to_size(sizo, invmat);
865 /* disable channels not enabled */
866 if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
867 if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f;
868 if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f;
869 if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f;
870 if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f;
871 if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f;
872 if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f;
873 if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f;
874 if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
876 /* make new target mat and offset mat */
877 loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
878 loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
880 /* multiply target (parent matrix) by offset (parent inverse) to get
881 * the effect of the parent that will be exherted on the owner
883 mul_m4_m4m4(parmat, invmat, ct->matrix);
885 /* now multiply the parent matrix by the owner matrix to get the
886 * the effect of this constraint (i.e. owner is 'parented' to parent)
888 copy_m4_m4(tempmat, cob->matrix);
889 mul_m4_m4m4(cob->matrix, tempmat, parmat);
891 /* without this, changes to scale and rotation can change location
892 * of a parentless bone or a disconnected bone. Even though its set
894 if (!(data->flag & CHILDOF_LOCX)) cob->matrix[3][0]= tempmat[3][0];
895 if (!(data->flag & CHILDOF_LOCY)) cob->matrix[3][1]= tempmat[3][1];
896 if (!(data->flag & CHILDOF_LOCZ)) cob->matrix[3][2]= tempmat[3][2];
901 /* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */
902 static bConstraintTypeInfo CTI_CHILDOF = {
903 CONSTRAINT_TYPE_CHILDOF, /* type */
904 sizeof(bChildOfConstraint), /* size */
905 "ChildOf", /* name */
906 "bChildOfConstraint", /* struct name */
907 NULL, /* free data */
908 NULL, /* relink data */
909 childof_id_looper, /* id looper */
910 NULL, /* copy data */
911 childof_new_data, /* new data */
912 childof_get_tars, /* get constraint targets */
913 childof_flush_tars, /* flush constraint targets */
914 default_get_tarmat, /* get a target matrix */
915 childof_evaluate /* evaluate */
918 /* -------- TrackTo Constraint ------- */
920 static void trackto_new_data (void *cdata)
922 bTrackToConstraint *data= (bTrackToConstraint *)cdata;
924 data->reserved1 = TRACK_Y;
925 data->reserved2 = UP_Z;
928 static void trackto_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
930 bTrackToConstraint *data= con->data;
933 func(con, (ID**)&data->tar, userdata);
936 static int trackto_get_tars (bConstraint *con, ListBase *list)
939 bTrackToConstraint *data= con->data;
940 bConstraintTarget *ct;
942 /* standard target-getting macro for single-target constraints */
943 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
951 static void trackto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
954 bTrackToConstraint *data= con->data;
955 bConstraintTarget *ct= list->first;
957 /* the following macro is used for all standard single-target constraints */
958 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
963 static int basis_cross (int n, int m)
979 static void vectomat (float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
982 float u[3]; /* vector specifying the up axis */
988 if (normalize_v3_v3(n, vec) == 0.0f) {
993 if (axis > 2) axis -= 3;
996 /* n specifies the transformation of the track axis */
997 if (flags & TARGET_Z_UP) {
998 /* target Z axis is the global up axis */
999 copy_v3_v3(u, target_up);
1002 /* world Z axis is the global up axis */
1008 /* project the up vector onto the plane specified by n */
1009 project_v3_v3v3(proj, u, n); /* first u onto n... */
1010 sub_v3_v3v3(proj, u, proj); /* then onto the plane */
1011 /* proj specifies the transformation of the up axis */
1013 if (normalize_v3(proj) == 0.0f) { /* degenerate projection */
1019 /* Normalized cross product of n and proj specifies transformation of the right axis */
1020 cross_v3_v3v3(right, proj, n);
1021 normalize_v3(right);
1023 if (axis != upflag) {
1024 right_index = 3 - axis - upflag;
1025 neg = (float)basis_cross(axis, upflag);
1027 /* account for up direction, track direction */
1028 m[right_index][0] = neg * right[0];
1029 m[right_index][1] = neg * right[1];
1030 m[right_index][2] = neg * right[2];
1032 copy_v3_v3(m[upflag], proj);
1034 copy_v3_v3(m[axis], n);
1036 /* identity matrix - don't do anything if the two axes are the same */
1043 static void trackto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
1045 bTrackToConstraint *data= con->data;
1046 bConstraintTarget *ct= targets->first;
1048 if (VALID_CONS_TARGET(ct)) {
1049 float size[3], vec[3];
1053 /* Get size property, since ob->size is only the object's own relative size, not its global one */
1054 mat4_to_size(size, cob->matrix);
1056 /* Clear the object's rotation */
1057 cob->matrix[0][0]=size[0];
1058 cob->matrix[0][1]=0;
1059 cob->matrix[0][2]=0;
1060 cob->matrix[1][0]=0;
1061 cob->matrix[1][1]=size[1];
1062 cob->matrix[1][2]=0;
1063 cob->matrix[2][0]=0;
1064 cob->matrix[2][1]=0;
1065 cob->matrix[2][2]=size[2];
1067 /* targetmat[2] instead of ownermat[2] is passed to vectomat
1068 * for backwards compatability it seems... (Aligorith)
1070 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
1071 vectomat(vec, ct->matrix[2],
1072 (short)data->reserved1, (short)data->reserved2,
1073 data->flags, totmat);
1075 copy_m4_m4(tmat, cob->matrix);
1076 mul_m4_m3m4(cob->matrix, totmat, tmat);
1080 static bConstraintTypeInfo CTI_TRACKTO = {
1081 CONSTRAINT_TYPE_TRACKTO, /* type */
1082 sizeof(bTrackToConstraint), /* size */
1083 "TrackTo", /* name */
1084 "bTrackToConstraint", /* struct name */
1085 NULL, /* free data */
1086 NULL, /* relink data */
1087 trackto_id_looper, /* id looper */
1088 NULL, /* copy data */
1089 trackto_new_data, /* new data */
1090 trackto_get_tars, /* get constraint targets */
1091 trackto_flush_tars, /* flush constraint targets */
1092 default_get_tarmat, /* get target matrix */
1093 trackto_evaluate /* evaluate */
1096 /* --------- Inverse-Kinemetics --------- */
1098 static void kinematic_new_data (void *cdata)
1100 bKinematicConstraint *data= (bKinematicConstraint *)cdata;
1102 data->weight= (float)1.0;
1103 data->orientweight= (float)1.0;
1104 data->iterations = 500;
1105 data->dist= (float)1.0;
1106 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
1109 static void kinematic_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
1111 bKinematicConstraint *data= con->data;
1114 func(con, (ID**)&data->tar, userdata);
1117 func(con, (ID**)&data->poletar, userdata);
1120 static int kinematic_get_tars (bConstraint *con, ListBase *list)
1123 bKinematicConstraint *data= con->data;
1124 bConstraintTarget *ct;
1126 /* standard target-getting macro for single-target constraints is used twice here */
1127 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
1128 SINGLETARGET_GET_TARS(con, data->poletar, data->polesubtarget, ct, list)
1136 static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy)
1139 bKinematicConstraint *data= con->data;
1140 bConstraintTarget *ct= list->first;
1142 /* the following macro is used for all standard single-target constraints */
1143 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
1144 SINGLETARGET_FLUSH_TARS(con, data->poletar, data->polesubtarget, ct, list, nocopy)
1148 static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
1150 bKinematicConstraint *data= con->data;
1152 if (VALID_CONS_TARGET(ct))
1153 constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
1155 if (data->flag & CONSTRAINT_IK_AUTO) {
1156 Object *ob= cob->ob;
1159 unit_m4(ct->matrix);
1163 /* move grabtarget into world space */
1164 mul_v3_m4v3(vec, ob->obmat, data->grabtarget);
1165 copy_m4_m4(ct->matrix, ob->obmat);
1166 copy_v3_v3(ct->matrix[3], vec);
1170 unit_m4(ct->matrix);
1174 static bConstraintTypeInfo CTI_KINEMATIC = {
1175 CONSTRAINT_TYPE_KINEMATIC, /* type */
1176 sizeof(bKinematicConstraint), /* size */
1178 "bKinematicConstraint", /* struct name */
1179 NULL, /* free data */
1180 NULL, /* relink data */
1181 kinematic_id_looper, /* id looper */
1182 NULL, /* copy data */
1183 kinematic_new_data, /* new data */
1184 kinematic_get_tars, /* get constraint targets */
1185 kinematic_flush_tars, /* flush constraint targets */
1186 kinematic_get_tarmat, /* get target matrix */
1187 NULL /* evaluate - solved as separate loop */
1190 /* -------- Follow-Path Constraint ---------- */
1192 static void followpath_new_data (void *cdata)
1194 bFollowPathConstraint *data= (bFollowPathConstraint *)cdata;
1196 data->trackflag = TRACK_Y;
1197 data->upflag = UP_Z;
1199 data->followflag = 0;
1202 static void followpath_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
1204 bFollowPathConstraint *data= con->data;
1207 func(con, (ID**)&data->tar, userdata);
1210 static int followpath_get_tars (bConstraint *con, ListBase *list)
1213 bFollowPathConstraint *data= con->data;
1214 bConstraintTarget *ct;
1216 /* standard target-getting macro for single-target constraints without subtargets */
1217 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list)
1225 static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocopy)
1228 bFollowPathConstraint *data= con->data;
1229 bConstraintTarget *ct= list->first;
1231 /* the following macro is used for all standard single-target constraints */
1232 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy)
1236 static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
1238 bFollowPathConstraint *data= con->data;
1240 if (VALID_CONS_TARGET(ct)) {
1241 Curve *cu= ct->tar->data;
1242 float vec[4], dir[3], radius;
1243 float totmat[4][4]= MAT4_UNITY;
1246 unit_m4(ct->matrix);
1248 /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
1249 * currently for paths to work it needs to go through the bevlist/displist system (ton)
1252 /* only happens on reload file, but violates depsgraph still... fix! */
1253 if (cu->path==NULL || cu->path->data==NULL)
1254 makeDispListCurveTypes(cob->scene, ct->tar, 0);
1256 if (cu->path && cu->path->data) {
1258 if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
1259 /* animated position along curve depending on time */
1261 curvetime= bsystem_time(cob->scene, ct->tar, cu->ctime, 0.0) - data->offset;
1263 curvetime= cu->ctime - data->offset;
1265 /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated,
1266 * but this will only work if it actually is animated...
1268 * we divide the curvetime calculated in the previous step by the length of the path, to get a time
1269 * factor, which then gets clamped to lie within 0.0 - 1.0 range
1271 curvetime /= cu->pathlen;
1272 CLAMP(curvetime, 0.0f, 1.0f);
1275 /* fixed position along curve */
1276 curvetime= data->offset_fac;
1279 if ( where_on_path(ct->tar, curvetime, vec, dir, (data->followflag & FOLLOWPATH_FOLLOW) ? quat : NULL, &radius, NULL) ) { /* quat_pt is quat or NULL*/
1280 if (data->followflag & FOLLOWPATH_FOLLOW) {
1283 vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag);
1286 q[0]= (float)cos(0.5*vec[3]);
1287 x1= (float)sin(0.5*vec[3]);
1291 mul_qt_qtqt(quat, q, quat);
1293 quat_apply_track(quat, data->trackflag, data->upflag);
1296 quat_to_mat4(totmat, quat);
1299 if (data->followflag & FOLLOWPATH_RADIUS) {
1300 float tmat[4][4], rmat[4][4];
1301 scale_m4_fl(tmat, radius);
1302 mul_m4_m4m4(rmat, totmat, tmat);
1303 copy_m4_m4(totmat, rmat);
1306 copy_v3_v3(totmat[3], vec);
1308 mul_serie_m4(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
1313 unit_m4(ct->matrix);
1316 static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
1318 bConstraintTarget *ct= targets->first;
1320 /* only evaluate if there is a target */
1321 if (VALID_CONS_TARGET(ct)) {
1324 bFollowPathConstraint *data= con->data;
1326 /* get Object transform (loc/rot/size) to determine transformation from path */
1327 // TODO: this used to be local at one point, but is probably more useful as-is
1328 copy_m4_m4(obmat, cob->matrix);
1330 /* get scaling of object before applying constraint */
1331 mat4_to_size(size, cob->matrix);
1333 /* apply targetmat - containing location on path, and rotation */
1334 mul_serie_m4(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1336 /* un-apply scaling caused by path */
1337 if ((data->followflag & FOLLOWPATH_RADIUS)==0) { /* XXX - assume that scale correction means that radius will have some scale error in it - Campbell */
1340 mat4_to_size( obsize,cob->matrix);
1342 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
1344 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
1346 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
1351 static bConstraintTypeInfo CTI_FOLLOWPATH = {
1352 CONSTRAINT_TYPE_FOLLOWPATH, /* type */
1353 sizeof(bFollowPathConstraint), /* size */
1354 "Follow Path", /* name */
1355 "bFollowPathConstraint", /* struct name */
1356 NULL, /* free data */
1357 NULL, /* relink data */
1358 followpath_id_looper, /* id looper */
1359 NULL, /* copy data */
1360 followpath_new_data, /* new data */
1361 followpath_get_tars, /* get constraint targets */
1362 followpath_flush_tars, /* flush constraint targets */
1363 followpath_get_tarmat, /* get target matrix */
1364 followpath_evaluate /* evaluate */
1367 /* --------- Limit Location --------- */
1370 static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
1372 bLocLimitConstraint *data = con->data;
1374 if (data->flag & LIMIT_XMIN) {
1375 if (cob->matrix[3][0] < data->xmin)
1376 cob->matrix[3][0] = data->xmin;
1378 if (data->flag & LIMIT_XMAX) {
1379 if (cob->matrix[3][0] > data->xmax)
1380 cob->matrix[3][0] = data->xmax;
1382 if (data->flag & LIMIT_YMIN) {
1383 if (cob->matrix[3][1] < data->ymin)
1384 cob->matrix[3][1] = data->ymin;
1386 if (data->flag & LIMIT_YMAX) {
1387 if (cob->matrix[3][1] > data->ymax)
1388 cob->matrix[3][1] = data->ymax;
1390 if (data->flag & LIMIT_ZMIN) {
1391 if (cob->matrix[3][2] < data->zmin)
1392 cob->matrix[3][2] = data->zmin;
1394 if (data->flag & LIMIT_ZMAX) {
1395 if (cob->matrix[3][2] > data->zmax)
1396 cob->matrix[3][2] = data->zmax;
1400 static bConstraintTypeInfo CTI_LOCLIMIT = {
1401 CONSTRAINT_TYPE_LOCLIMIT, /* type */
1402 sizeof(bLocLimitConstraint), /* size */
1403 "Limit Location", /* name */
1404 "bLocLimitConstraint", /* struct name */
1405 NULL, /* free data */
1406 NULL, /* relink data */
1407 NULL, /* id looper */
1408 NULL, /* copy data */
1409 NULL, /* new data */
1410 NULL, /* get constraint targets */
1411 NULL, /* flush constraint targets */
1412 NULL, /* get target matrix */
1413 loclimit_evaluate /* evaluate */
1416 /* -------- Limit Rotation --------- */
1418 static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
1420 bRotLimitConstraint *data = con->data;
1425 copy_v3_v3(loc, cob->matrix[3]);
1426 mat4_to_size(size, cob->matrix);
1428 mat4_to_eulO(eul, cob->rotOrder, cob->matrix);
1430 /* constraint data uses radians internally */
1432 /* limiting of euler values... */
1433 if (data->flag & LIMIT_XROT) {
1434 if (eul[0] < data->xmin)
1435 eul[0] = data->xmin;
1437 if (eul[0] > data->xmax)
1438 eul[0] = data->xmax;
1440 if (data->flag & LIMIT_YROT) {
1441 if (eul[1] < data->ymin)
1442 eul[1] = data->ymin;
1444 if (eul[1] > data->ymax)
1445 eul[1] = data->ymax;
1447 if (data->flag & LIMIT_ZROT) {
1448 if (eul[2] < data->zmin)
1449 eul[2] = data->zmin;
1451 if (eul[2] > data->zmax)
1452 eul[2] = data->zmax;
1455 loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
1458 static bConstraintTypeInfo CTI_ROTLIMIT = {
1459 CONSTRAINT_TYPE_ROTLIMIT, /* type */
1460 sizeof(bRotLimitConstraint), /* size */
1461 "Limit Rotation", /* name */
1462 "bRotLimitConstraint", /* struct name */
1463 NULL, /* free data */
1464 NULL, /* relink data */
1465 NULL, /* id looper */
1466 NULL, /* copy data */
1467 NULL, /* new data */
1468 NULL, /* get constraint targets */
1469 NULL, /* flush constraint targets */
1470 NULL, /* get target matrix */
1471 rotlimit_evaluate /* evaluate */
1474 /* --------- Limit Scaling --------- */
1477 static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
1479 bSizeLimitConstraint *data = con->data;
1480 float obsize[3], size[3];
1482 mat4_to_size( size,cob->matrix);
1483 mat4_to_size( obsize,cob->matrix);
1485 if (data->flag & LIMIT_XMIN) {
1486 if (size[0] < data->xmin)
1487 size[0] = data->xmin;
1489 if (data->flag & LIMIT_XMAX) {
1490 if (size[0] > data->xmax)
1491 size[0] = data->xmax;
1493 if (data->flag & LIMIT_YMIN) {
1494 if (size[1] < data->ymin)
1495 size[1] = data->ymin;
1497 if (data->flag & LIMIT_YMAX) {
1498 if (size[1] > data->ymax)
1499 size[1] = data->ymax;
1501 if (data->flag & LIMIT_ZMIN) {
1502 if (size[2] < data->zmin)
1503 size[2] = data->zmin;
1505 if (data->flag & LIMIT_ZMAX) {
1506 if (size[2] > data->zmax)
1507 size[2] = data->zmax;
1511 mul_v3_fl(cob->matrix[0], size[0]/obsize[0]);
1513 mul_v3_fl(cob->matrix[1], size[1]/obsize[1]);
1515 mul_v3_fl(cob->matrix[2], size[2]/obsize[2]);
1518 static bConstraintTypeInfo CTI_SIZELIMIT = {
1519 CONSTRAINT_TYPE_SIZELIMIT, /* type */
1520 sizeof(bSizeLimitConstraint), /* size */
1521 "Limit Scaling", /* name */
1522 "bSizeLimitConstraint", /* struct name */
1523 NULL, /* free data */
1524 NULL, /* relink data */
1525 NULL, /* id looper */
1526 NULL, /* copy data */
1527 NULL, /* new data */
1528 NULL, /* get constraint targets */
1529 NULL, /* flush constraint targets */
1530 NULL, /* get target matrix */
1531 sizelimit_evaluate /* evaluate */
1534 /* ----------- Copy Location ------------- */
1536 static void loclike_new_data (void *cdata)
1538 bLocateLikeConstraint *data= (bLocateLikeConstraint *)cdata;
1540 data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
1543 static void loclike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
1545 bLocateLikeConstraint *data= con->data;
1548 func(con, (ID**)&data->tar, userdata);
1551 static int loclike_get_tars (bConstraint *con, ListBase *list)
1554 bLocateLikeConstraint *data= con->data;
1555 bConstraintTarget *ct;
1557 /* standard target-getting macro for single-target constraints */
1558 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
1566 static void loclike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
1569 bLocateLikeConstraint *data= con->data;
1570 bConstraintTarget *ct= list->first;
1572 /* the following macro is used for all standard single-target constraints */
1573 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
1577 static void loclike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
1579 bLocateLikeConstraint *data= con->data;
1580 bConstraintTarget *ct= targets->first;
1582 if (VALID_CONS_TARGET(ct)) {
1583 float offset[3] = {0.0f, 0.0f, 0.0f};
1585 if (data->flag & LOCLIKE_OFFSET)
1586 copy_v3_v3(offset, cob->matrix[3]);
1588 if (data->flag & LOCLIKE_X) {
1589 cob->matrix[3][0] = ct->matrix[3][0];
1591 if (data->flag & LOCLIKE_X_INVERT) cob->matrix[3][0] *= -1;
1592 cob->matrix[3][0] += offset[0];
1594 if (data->flag & LOCLIKE_Y) {
1595 cob->matrix[3][1] = ct->matrix[3][1];
1597 if (data->flag & LOCLIKE_Y_INVERT) cob->matrix[3][1] *= -1;
1598 cob->matrix[3][1] += offset[1];
1600 if (data->flag & LOCLIKE_Z) {
1601 cob->matrix[3][2] = ct->matrix[3][2];
1603 if (data->flag & LOCLIKE_Z_INVERT) cob->matrix[3][2] *= -1;
1604 cob->matrix[3][2] += offset[2];
1609 static bConstraintTypeInfo CTI_LOCLIKE = {
1610 CONSTRAINT_TYPE_LOCLIKE, /* type */
1611 sizeof(bLocateLikeConstraint), /* size */
1612 "Copy Location", /* name */
1613 "bLocateLikeConstraint", /* struct name */
1614 NULL, /* free data */
1615 NULL, /* relink data */
1616 loclike_id_looper, /* id looper */
1617 NULL, /* copy data */
1618 loclike_new_data, /* new data */
1619 loclike_get_tars, /* get constraint targets */
1620 loclike_flush_tars, /* flush constraint targets */
1621 default_get_tarmat, /* get target matrix */
1622 loclike_evaluate /* evaluate */
1625 /* ----------- Copy Rotation ------------- */
1627 static void rotlike_new_data (void *cdata)
1629 bRotateLikeConstraint *data= (bRotateLikeConstraint *)cdata;
1631 data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
1634 static void rotlike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
1636 bChildOfConstraint *data= con->data;
1639 func(con, (ID**)&data->tar, userdata);
1642 static int rotlike_get_tars (bConstraint *con, ListBase *list)
1645 bRotateLikeConstraint *data= con->data;
1646 bConstraintTarget *ct;
1648 /* standard target-getting macro for single-target constraints */
1649 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
1657 static void rotlike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
1660 bRotateLikeConstraint *data= con->data;
1661 bConstraintTarget *ct= list->first;
1663 /* the following macro is used for all standard single-target constraints */
1664 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
1668 static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
1670 bRotateLikeConstraint *data= con->data;
1671 bConstraintTarget *ct= targets->first;
1673 if (VALID_CONS_TARGET(ct)) {
1675 float eul[3], obeul[3];
1678 copy_v3_v3(loc, cob->matrix[3]);
1679 mat4_to_size(size, cob->matrix);
1681 /* to allow compatible rotations, must get both rotations in the order of the owner... */
1682 mat4_to_eulO(obeul, cob->rotOrder, cob->matrix);
1683 /* we must get compatible eulers from the beginning because some of them can be modified below (see bug #21875) */
1684 mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix);
1686 if ((data->flag & ROTLIKE_X)==0)
1689 if (data->flag & ROTLIKE_OFFSET)
1690 rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]);
1692 if (data->flag & ROTLIKE_X_INVERT)
1696 if ((data->flag & ROTLIKE_Y)==0)
1699 if (data->flag & ROTLIKE_OFFSET)
1700 rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]);
1702 if (data->flag & ROTLIKE_Y_INVERT)
1706 if ((data->flag & ROTLIKE_Z)==0)
1709 if (data->flag & ROTLIKE_OFFSET)
1710 rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]);
1712 if (data->flag & ROTLIKE_Z_INVERT)
1716 /* good to make eulers compatible again, since we don't know how much they were changed above */
1717 compatible_eul(eul, obeul);
1718 loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
1722 static bConstraintTypeInfo CTI_ROTLIKE = {
1723 CONSTRAINT_TYPE_ROTLIKE, /* type */
1724 sizeof(bRotateLikeConstraint), /* size */
1725 "Copy Rotation", /* name */
1726 "bRotateLikeConstraint", /* struct name */
1727 NULL, /* free data */
1728 NULL, /* relink data */
1729 rotlike_id_looper, /* id looper */
1730 NULL, /* copy data */
1731 rotlike_new_data, /* new data */
1732 rotlike_get_tars, /* get constraint targets */
1733 rotlike_flush_tars, /* flush constraint targets */
1734 default_get_tarmat, /* get target matrix */
1735 rotlike_evaluate /* evaluate */
1738 /* ---------- Copy Scaling ---------- */
1740 static void sizelike_new_data (void *cdata)
1742 bSizeLikeConstraint *data= (bSizeLikeConstraint *)cdata;
1744 data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
1747 static void sizelike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
1749 bSizeLikeConstraint *data= con->data;
1752 func(con, (ID**)&data->tar, userdata);
1755 static int sizelike_get_tars (bConstraint *con, ListBase *list)
1758 bSizeLikeConstraint *data= con->data;
1759 bConstraintTarget *ct;
1761 /* standard target-getting macro for single-target constraints */
1762 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
1770 static void sizelike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
1773 bSizeLikeConstraint *data= con->data;
1774 bConstraintTarget *ct= list->first;
1776 /* the following macro is used for all standard single-target constraints */
1777 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
1781 static void sizelike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
1783 bSizeLikeConstraint *data= con->data;
1784 bConstraintTarget *ct= targets->first;
1786 if (VALID_CONS_TARGET(ct)) {
1787 float obsize[3], size[3];
1789 mat4_to_size(size, ct->matrix);
1790 mat4_to_size(obsize, cob->matrix);
1792 if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) {
1793 if (data->flag & SIZELIKE_OFFSET) {
1794 size[0] += (obsize[0] - 1.0f);
1795 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
1798 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
1800 if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) {
1801 if (data->flag & SIZELIKE_OFFSET) {
1802 size[1] += (obsize[1] - 1.0f);
1803 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
1806 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
1808 if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) {
1809 if (data->flag & SIZELIKE_OFFSET) {
1810 size[2] += (obsize[2] - 1.0f);
1811 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
1814 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
1819 static bConstraintTypeInfo CTI_SIZELIKE = {
1820 CONSTRAINT_TYPE_SIZELIKE, /* type */
1821 sizeof(bSizeLikeConstraint), /* size */
1822 "Copy Scale", /* name */
1823 "bSizeLikeConstraint", /* struct name */
1824 NULL, /* free data */
1825 NULL, /* relink data */
1826 sizelike_id_looper, /* id looper */
1827 NULL, /* copy data */
1828 sizelike_new_data, /* new data */
1829 sizelike_get_tars, /* get constraint targets */
1830 sizelike_flush_tars, /* flush constraint targets */
1831 default_get_tarmat, /* get target matrix */
1832 sizelike_evaluate /* evaluate */
1835 /* ----------- Copy Transforms ------------- */
1837 static void translike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
1839 bTransLikeConstraint *data= con->data;
1842 func(con, (ID**)&data->tar, userdata);
1845 static int translike_get_tars (bConstraint *con, ListBase *list)
1848 bTransLikeConstraint *data= con->data;
1849 bConstraintTarget *ct;
1851 /* standard target-getting macro for single-target constraints */
1852 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
1860 static void translike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
1863 bTransLikeConstraint *data= con->data;
1864 bConstraintTarget *ct= list->first;
1866 /* the following macro is used for all standard single-target constraints */
1867 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
1871 static void translike_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
1873 bConstraintTarget *ct= targets->first;
1875 if (VALID_CONS_TARGET(ct)) {
1876 /* just copy the entire transform matrix of the target */
1877 copy_m4_m4(cob->matrix, ct->matrix);
1881 static bConstraintTypeInfo CTI_TRANSLIKE = {
1882 CONSTRAINT_TYPE_TRANSLIKE, /* type */
1883 sizeof(bTransLikeConstraint), /* size */
1884 "Copy Transforms", /* name */
1885 "bTransLikeConstraint", /* struct name */
1886 NULL, /* free data */
1887 NULL, /* relink data */
1888 translike_id_looper, /* id looper */
1889 NULL, /* copy data */
1890 NULL, /* new data */
1891 translike_get_tars, /* get constraint targets */
1892 translike_flush_tars, /* flush constraint targets */
1893 default_get_tarmat, /* get target matrix */
1894 translike_evaluate /* evaluate */
1897 /* ---------- Maintain Volume ---------- */
1899 static void samevolume_new_data (void *cdata)
1901 bSameVolumeConstraint *data= (bSameVolumeConstraint *)cdata;
1903 data->flag = SAMEVOL_Y;
1904 data->volume = 1.0f;
1907 static void samevolume_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
1909 bSameVolumeConstraint *data= con->data;
1911 float volume = data->volume;
1915 mat4_to_size(obsize, cob->matrix);
1917 /* calculate normalising scale factor for non-essential values */
1918 if (obsize[data->flag] != 0)
1919 fac = sqrtf(volume / obsize[data->flag]) / obsize[data->flag];
1921 /* apply scaling factor to the channels not being kept */
1922 switch (data->flag) {
1924 mul_v3_fl(cob->matrix[1], fac);
1925 mul_v3_fl(cob->matrix[2], fac);
1928 mul_v3_fl(cob->matrix[0], fac);
1929 mul_v3_fl(cob->matrix[2], fac);
1932 mul_v3_fl(cob->matrix[0], fac);
1933 mul_v3_fl(cob->matrix[1], fac);
1938 static bConstraintTypeInfo CTI_SAMEVOL = {
1939 CONSTRAINT_TYPE_SAMEVOL, /* type */
1940 sizeof(bSameVolumeConstraint), /* size */
1941 "Maintain Volume", /* name */
1942 "bSameVolumeConstraint", /* struct name */
1943 NULL, /* free data */
1944 NULL, /* relink data */
1945 NULL, /* id looper */
1946 NULL, /* copy data */
1947 samevolume_new_data, /* new data */
1948 NULL, /* get constraint targets */
1949 NULL, /* flush constraint targets */
1950 NULL, /* get target matrix */
1951 samevolume_evaluate /* evaluate */
1954 /* ----------- Python Constraint -------------- */
1956 static void pycon_free (bConstraint *con)
1958 bPythonConstraint *data= con->data;
1961 IDP_FreeProperty(data->prop);
1962 MEM_freeN(data->prop);
1964 /* multiple targets */
1965 BLI_freelistN(&data->targets);
1968 static void pycon_relink (bConstraint *con)
1970 bPythonConstraint *data= con->data;
1975 static void pycon_copy (bConstraint *con, bConstraint *srccon)
1977 bPythonConstraint *pycon = (bPythonConstraint *)con->data;
1978 bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
1980 pycon->prop = IDP_CopyProperty(opycon->prop);
1981 BLI_duplicatelist(&pycon->targets, &opycon->targets);
1984 static void pycon_new_data (void *cdata)
1986 bPythonConstraint *data= (bPythonConstraint *)cdata;
1988 /* everything should be set correctly by calloc, except for the prop->type constant.*/
1989 data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
1990 data->prop->type = IDP_GROUP;
1993 static int pycon_get_tars (bConstraint *con, ListBase *list)
1996 bPythonConstraint *data= con->data;
1998 list->first = data->targets.first;
1999 list->last = data->targets.last;
2001 return data->tarnum;
2007 static void pycon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
2009 bPythonConstraint *data= con->data;
2010 bConstraintTarget *ct;
2013 for (ct= data->targets.first; ct; ct= ct->next)
2014 func(con, (ID**)&ct->tar, userdata);
2017 func(con, (ID**)&data->text, userdata);
2020 /* Whether this approach is maintained remains to be seen (aligorith) */
2021 static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
2024 bPythonConstraint *data= con->data;
2027 if (VALID_CONS_TARGET(ct)) {
2028 /* special exception for curves - depsgraph issues */
2029 if (ct->tar->type == OB_CURVE) {
2030 Curve *cu= ct->tar->data;
2032 /* this check is to make sure curve objects get updated on file load correctly.*/
2033 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
2034 makeDispListCurveTypes(cob->scene, ct->tar, 0);
2037 /* firstly calculate the matrix the normal way, then let the py-function override
2038 * this matrix if it needs to do so
2040 constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
2042 /* only execute target calculation if allowed */
2044 if (G.f & G_SCRIPT_AUTOEXEC)
2045 BPY_pyconstraint_target(data, ct);
2049 unit_m4(ct->matrix);
2052 static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
2055 (void)con; (void)cob; (void)targets; /* unused */
2058 bPythonConstraint *data= con->data;
2060 /* only evaluate in python if we're allowed to do so */
2061 if ((G.f & G_SCRIPT_AUTOEXEC)==0) return;
2063 /* currently removed, until I this can be re-implemented for multiple targets */
2065 /* Firstly, run the 'driver' function which has direct access to the objects involved
2066 * Technically, this is potentially dangerous as users may abuse this and cause dependency-problems,
2067 * but it also allows certain 'clever' rigging hacks to work.
2069 BPY_pyconstraint_driver(data, cob, targets);
2072 /* Now, run the actual 'constraint' function, which should only access the matrices */
2073 BPY_pyconstraint_exec(data, cob, targets);
2074 #endif /* WITH_PYTHON */
2077 static bConstraintTypeInfo CTI_PYTHON = {
2078 CONSTRAINT_TYPE_PYTHON, /* type */
2079 sizeof(bPythonConstraint), /* size */
2080 "Script", /* name */
2081 "bPythonConstraint", /* struct name */
2082 pycon_free, /* free data */
2083 pycon_relink, /* relink data */
2084 pycon_id_looper, /* id looper */
2085 pycon_copy, /* copy data */
2086 pycon_new_data, /* new data */
2087 pycon_get_tars, /* get constraint targets */
2088 NULL, /* flush constraint targets */
2089 pycon_get_tarmat, /* get target matrix */
2090 pycon_evaluate /* evaluate */
2093 /* -------- Action Constraint ----------- */
2095 static void actcon_relink (bConstraint *con)
2097 bActionConstraint *data= con->data;
2101 static void actcon_new_data (void *cdata)
2103 bActionConstraint *data= (bActionConstraint *)cdata;
2105 /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */
2109 static void actcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
2111 bActionConstraint *data= con->data;
2114 func(con, (ID**)&data->tar, userdata);
2117 func(con, (ID**)&data->act, userdata);
2120 static int actcon_get_tars (bConstraint *con, ListBase *list)
2123 bActionConstraint *data= con->data;
2124 bConstraintTarget *ct;
2126 /* standard target-getting macro for single-target constraints */
2127 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
2135 static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
2138 bActionConstraint *data= con->data;
2139 bConstraintTarget *ct= list->first;
2141 /* the following macro is used for all standard single-target constraints */
2142 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
2146 static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
2148 bActionConstraint *data = con->data;
2150 if (VALID_CONS_TARGET(ct)) {
2151 float tempmat[4][4], vec[3];
2155 /* initialise return matrix */
2156 unit_m4(ct->matrix);
2158 /* get the transform matrix of the target */
2159 constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail);
2161 /* determine where in transform range target is */
2162 /* data->type is mapped as follows for backwards compatability:
2163 * 00,01,02 - rotation (it used to be like this)
2164 * 10,11,12 - scaling
2165 * 20,21,22 - location
2167 if (data->type < 10) {
2168 /* extract rotation (is in whatever space target should be in) */
2169 mat4_to_eul(vec, tempmat);
2170 mul_v3_fl(vec, RAD2DEGF(1.0f)); /* rad -> deg */
2173 else if (data->type < 20) {
2174 /* extract scaling (is in whatever space target should be in) */
2175 mat4_to_size(vec, tempmat);
2176 axis= data->type - 10;
2179 /* extract location */
2180 copy_v3_v3(vec, tempmat[3]);
2181 axis= data->type - 20;
2184 /* Target defines the animation */
2185 s = (vec[axis]-data->min) / (data->max-data->min);
2187 t = (s * (data->end-data->start)) + data->start;
2190 printf("do Action Constraint %s - Ob %s Pchan %s \n", con->name, cob->ob->id.name+2, (cob->pchan)?cob->pchan->name:NULL);
2192 /* Get the appropriate information from the action */
2193 if (cob->type == CONSTRAINT_OBTYPE_BONE) {
2196 bPoseChannel *pchan, *tchan;
2198 /* make a temporary pose and evaluate using that */
2199 pose = MEM_callocN(sizeof(bPose), "pose");
2201 /* make a copy of the bone of interest in the temp pose before evaluating action, so that it can get set
2202 * - we need to manually copy over a few settings, including rotation order, otherwise this fails
2206 tchan= verify_pose_channel(pose, pchan->name);
2207 tchan->rotmode= pchan->rotmode;
2209 /* evaluate action using workob (it will only set the PoseChannel in question) */
2210 what_does_obaction(cob->ob, &workob, pose, data->act, pchan->name, t);
2212 /* convert animation to matrices for use here */
2213 pchan_calc_mat(tchan);
2214 copy_m4_m4(ct->matrix, tchan->chan_mat);
2219 else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) {
2222 /* evaluate using workob */
2223 // FIXME: we don't have any consistent standards on limiting effects on object...
2224 what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t);
2225 object_to_mat4(&workob, ct->matrix);
2228 /* behaviour undefined... */
2229 puts("Error: unknown owner type for Action Constraint");
2234 static void actcon_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
2236 bConstraintTarget *ct= targets->first;
2238 if (VALID_CONS_TARGET(ct)) {
2241 /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix
2242 * function has already taken care of everything else.
2244 copy_m4_m4(temp, cob->matrix);
2245 mul_m4_m4m4(cob->matrix, ct->matrix, temp);
2249 static bConstraintTypeInfo CTI_ACTION = {
2250 CONSTRAINT_TYPE_ACTION, /* type */
2251 sizeof(bActionConstraint), /* size */
2252 "Action", /* name */
2253 "bActionConstraint", /* struct name */
2254 NULL, /* free data */
2255 actcon_relink, /* relink data */
2256 actcon_id_looper, /* id looper */
2257 NULL, /* copy data */
2258 actcon_new_data, /* new data */
2259 actcon_get_tars, /* get constraint targets */
2260 actcon_flush_tars, /* flush constraint targets */
2261 actcon_get_tarmat, /* get target matrix */
2262 actcon_evaluate /* evaluate */
2265 /* --------- Locked Track ---------- */
2267 static void locktrack_new_data (void *cdata)
2269 bLockTrackConstraint *data= (bLockTrackConstraint *)cdata;
2271 data->trackflag = TRACK_Y;
2272 data->lockflag = LOCK_Z;
2275 static void locktrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
2277 bLockTrackConstraint *data= con->data;
2280 func(con, (ID**)&data->tar, userdata);
2283 static int locktrack_get_tars (bConstraint *con, ListBase *list)
2286 bLockTrackConstraint *data= con->data;
2287 bConstraintTarget *ct;
2289 /* the following macro is used for all standard single-target constraints */
2290 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
2298 static void locktrack_flush_tars (bConstraint *con, ListBase *list, short nocopy)
2301 bLockTrackConstraint *data= con->data;
2302 bConstraintTarget *ct= list->first;
2304 /* the following macro is used for all standard single-target constraints */
2305 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
2309 static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
2311 bLockTrackConstraint *data= con->data;
2312 bConstraintTarget *ct= targets->first;
2314 if (VALID_CONS_TARGET(ct)) {
2315 float vec[3],vec2[3];
2322 /* Vector object -> target */
2323 sub_v3_v3v3(vec, ct->matrix[3], cob->matrix[3]);
2324 switch (data->lockflag){
2325 case LOCK_X: /* LOCK X */
2327 switch (data->trackflag) {
2328 case TRACK_Y: /* LOCK X TRACK Y */
2330 /* Projection of Vector on the plane */
2331 project_v3_v3v3(vec2, vec, cob->matrix[0]);
2332 sub_v3_v3v3(totmat[1], vec, vec2);
2333 normalize_v3(totmat[1]);
2335 /* the x axis is fixed */
2336 normalize_v3_v3(totmat[0], cob->matrix[0]);
2338 /* the z axis gets mapped onto a third orthogonal vector */
2339 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
2342 case TRACK_Z: /* LOCK X TRACK Z */
2344 /* Projection of Vector on the plane */
2345 project_v3_v3v3(vec2, vec, cob->matrix[0]);
2346 sub_v3_v3v3(totmat[2], vec, vec2);
2347 normalize_v3(totmat[2]);
2349 /* the x axis is fixed */
2350 normalize_v3_v3(totmat[0], cob->matrix[0]);
2352 /* the z axis gets mapped onto a third orthogonal vector */
2353 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
2356 case TRACK_nY: /* LOCK X TRACK -Y */
2358 /* Projection of Vector on the plane */
2359 project_v3_v3v3(vec2, vec, cob->matrix[0]);
2360 sub_v3_v3v3(totmat[1], vec, vec2);
2361 normalize_v3(totmat[1]);
2362 negate_v3(totmat[1]);
2364 /* the x axis is fixed */
2365 normalize_v3_v3(totmat[0], cob->matrix[0]);
2367 /* the z axis gets mapped onto a third orthogonal vector */
2368 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
2371 case TRACK_nZ: /* LOCK X TRACK -Z */
2373 /* Projection of Vector on the plane */
2374 project_v3_v3v3(vec2, vec, cob->matrix[0]);
2375 sub_v3_v3v3(totmat[2], vec, vec2);
2376 normalize_v3(totmat[2]);
2377 negate_v3(totmat[2]);
2379 /* the x axis is fixed */
2380 normalize_v3_v3(totmat[0], cob->matrix[0]);
2382 /* the z axis gets mapped onto a third orthogonal vector */
2383 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
2394 case LOCK_Y: /* LOCK Y */
2396 switch (data->trackflag) {
2397 case TRACK_X: /* LOCK Y TRACK X */
2399 /* Projection of Vector on the plane */
2400 project_v3_v3v3(vec2, vec, cob->matrix[1]);
2401 sub_v3_v3v3(totmat[0], vec, vec2);
2402 normalize_v3(totmat[0]);
2404 /* the y axis is fixed */
2405 normalize_v3_v3(totmat[1], cob->matrix[1]);
2407 /* the z axis gets mapped onto a third orthogonal vector */
2408 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
2411 case TRACK_Z: /* LOCK Y TRACK Z */
2413 /* Projection of Vector on the plane */
2414 project_v3_v3v3(vec2, vec, cob->matrix[1]);
2415 sub_v3_v3v3(totmat[2], vec, vec2);
2416 normalize_v3(totmat[2]);
2418 /* the y axis is fixed */
2419 normalize_v3_v3(totmat[1], cob->matrix[1]);
2421 /* the z axis gets mapped onto a third orthogonal vector */
2422 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
2425 case TRACK_nX: /* LOCK Y TRACK -X */
2427 /* Projection of Vector on the plane */
2428 project_v3_v3v3(vec2, vec, cob->matrix[1]);
2429 sub_v3_v3v3(totmat[0], vec, vec2);
2430 normalize_v3(totmat[0]);
2431 negate_v3(totmat[0]);
2433 /* the y axis is fixed */
2434 normalize_v3_v3(totmat[1], cob->matrix[1]);
2436 /* the z axis gets mapped onto a third orthogonal vector */
2437 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]);
2440 case TRACK_nZ: /* LOCK Y TRACK -Z */
2442 /* Projection of Vector on the plane */
2443 project_v3_v3v3(vec2, vec, cob->matrix[1]);
2444 sub_v3_v3v3(totmat[2], vec, vec2);
2445 normalize_v3(totmat[2]);
2446 negate_v3(totmat[2]);
2448 /* the y axis is fixed */
2449 normalize_v3_v3(totmat[1], cob->matrix[1]);
2451 /* the z axis gets mapped onto a third orthogonal vector */
2452 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
2463 case LOCK_Z: /* LOCK Z */
2465 switch (data->trackflag) {
2466 case TRACK_X: /* LOCK Z TRACK X */
2468 /* Projection of Vector on the plane */
2469 project_v3_v3v3(vec2, vec, cob->matrix[2]);
2470 sub_v3_v3v3(totmat[0], vec, vec2);
2471 normalize_v3(totmat[0]);
2473 /* the z axis is fixed */
2474 normalize_v3_v3(totmat[2], cob->matrix[2]);
2476 /* the x axis gets mapped onto a third orthogonal vector */
2477 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
2480 case TRACK_Y: /* LOCK Z TRACK Y */
2482 /* Projection of Vector on the plane */
2483 project_v3_v3v3(vec2, vec, cob->matrix[2]);
2484 sub_v3_v3v3(totmat[1], vec, vec2);
2485 normalize_v3(totmat[1]);
2487 /* the z axis is fixed */
2488 normalize_v3_v3(totmat[2], cob->matrix[2]);
2490 /* the x axis gets mapped onto a third orthogonal vector */
2491 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
2494 case TRACK_nX: /* LOCK Z TRACK -X */
2496 /* Projection of Vector on the plane */
2497 project_v3_v3v3(vec2, vec, cob->matrix[2]);
2498 sub_v3_v3v3(totmat[0], vec, vec2);
2499 normalize_v3(totmat[0]);
2500 negate_v3(totmat[0]);
2502 /* the z axis is fixed */
2503 normalize_v3_v3(totmat[2], cob->matrix[2]);
2505 /* the x axis gets mapped onto a third orthogonal vector */
2506 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]);
2509 case TRACK_nY: /* LOCK Z TRACK -Y */
2511 /* Projection of Vector on the plane */
2512 project_v3_v3v3(vec2, vec, cob->matrix[2]);
2513 sub_v3_v3v3(totmat[1], vec, vec2);
2514 normalize_v3(totmat[1]);
2515 negate_v3(totmat[1]);
2517 /* the z axis is fixed */
2518 normalize_v3_v3(totmat[2], cob->matrix[2]);
2520 /* the x axis gets mapped onto a third orthogonal vector */
2521 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]);
2538 /* Block to keep matrix heading */
2539 copy_m3_m4(tmpmat, cob->matrix);
2540 normalize_m3(tmpmat);
2541 invert_m3_m3(invmat, tmpmat);
2542 mul_m3_m3m3(tmpmat, totmat, invmat);
2543 totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
2544 totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
2545 totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
2547 copy_m4_m4(tmat, cob->matrix);
2549 mdet = determinant_m3( totmat[0][0],totmat[0][1],totmat[0][2],
2550 totmat[1][0],totmat[1][1],totmat[1][2],
2551 totmat[2][0],totmat[2][1],totmat[2][2]);
2556 /* apply out transformaton to the object */
2557 mul_m4_m3m4(cob->matrix, totmat, tmat);
2561 static bConstraintTypeInfo CTI_LOCKTRACK = {
2562 CONSTRAINT_TYPE_LOCKTRACK, /* type */
2563 sizeof(bLockTrackConstraint), /* size */
2564 "Locked Track", /* name */
2565 "bLockTrackConstraint", /* struct name */
2566 NULL, /* free data */
2567 NULL, /* relink data */
2568 locktrack_id_looper, /* id looper */
2569 NULL, /* copy data */
2570 locktrack_new_data, /* new data */
2571 locktrack_get_tars, /* get constraint targets */
2572 locktrack_flush_tars, /* flush constraint targets */
2573 default_get_tarmat, /* get target matrix */
2574 locktrack_evaluate /* evaluate */
2577 /* ---------- Limit Distance Constraint ----------- */
2579 static void distlimit_new_data (void *cdata)
2581 bDistLimitConstraint *data= (bDistLimitConstraint *)cdata;
2586 static void distlimit_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
2588 bDistLimitConstraint *data= con->data;
2591 func(con, (ID**)&data->tar, userdata);
2594 static int distlimit_get_tars (bConstraint *con, ListBase *list)
2597 bDistLimitConstraint *data= con->data;
2598 bConstraintTarget *ct;
2600 /* standard target-getting macro for single-target constraints */
2601 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
2609 static void distlimit_flush_tars (bConstraint *con, ListBase *list, short nocopy)
2612 bDistLimitConstraint *data= con->data;
2613 bConstraintTarget *ct= list->first;
2615 /* the following macro is used for all standard single-target constraints */
2616 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
2620 static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
2622 bDistLimitConstraint *data= con->data;
2623 bConstraintTarget *ct= targets->first;
2625 /* only evaluate if there is a target */
2626 if (VALID_CONS_TARGET(ct)) {
2627 float dvec[3], dist=0.0f, sfac=1.0f;
2628 short clamp_surf= 0;
2630 /* calculate our current distance from the target */
2631 dist= len_v3v3(cob->matrix[3], ct->matrix[3]);
2633 /* set distance (flag is only set when user demands it) */
2634 if (data->dist == 0)
2637 /* check if we're which way to clamp from, and calculate interpolation factor (if needed) */
2638 if (data->mode == LIMITDIST_OUTSIDE) {
2639 /* if inside, then move to surface */
2640 if (dist <= data->dist) {
2642 if (dist != 0.0f) sfac= data->dist / dist;
2644 /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */
2645 else if (data->flag & LIMITDIST_USESOFT) {
2646 if (dist <= (data->dist + data->soft)) {
2651 else if (data->mode == LIMITDIST_INSIDE) {
2652 /* if outside, then move to surface */
2653 if (dist >= data->dist) {
2655 if (dist != 0.0f) sfac= data->dist / dist;
2657 /* if soft-distance is enabled, start fading once owner is dist-soft from the target */
2658 else if (data->flag & LIMITDIST_USESOFT) {
2659 // FIXME: there's a problem with "jumping" when this kicks in
2660 if (dist >= (data->dist - data->soft)) {
2661 sfac = (float)( data->soft*(1.0f - expf(-(dist - data->dist)/data->soft)) + data->dist );
2662 if (dist != 0.0f) sfac /= dist;
2669 if (IS_EQF(dist, data->dist)==0) {
2671 if (dist != 0.0f) sfac= data->dist / dist;
2675 /* clamp to 'surface' (i.e. move owner so that dist == data->dist) */
2677 /* simply interpolate along line formed by target -> owner */
2678 interp_v3_v3v3(dvec, ct->matrix[3], cob->matrix[3], sfac);
2680 /* copy new vector onto owner */
2681 copy_v3_v3(cob->matrix[3], dvec);
2686 static bConstraintTypeInfo CTI_DISTLIMIT = {
2687 CONSTRAINT_TYPE_DISTLIMIT, /* type */
2688 sizeof(bDistLimitConstraint), /* size */
2689 "Limit Distance", /* name */
2690 "bDistLimitConstraint", /* struct name */
2691 NULL, /* free data */
2692 NULL, /* relink data */
2693 distlimit_id_looper, /* id looper */
2694 NULL, /* copy data */
2695 distlimit_new_data, /* new data */
2696 distlimit_get_tars, /* get constraint targets */
2697 distlimit_flush_tars, /* flush constraint targets */
2698 default_get_tarmat, /* get a target matrix */
2699 distlimit_evaluate /* evaluate */
2702 /* ---------- Stretch To ------------ */
2704 static void stretchto_new_data (void *cdata)
2706 bStretchToConstraint *data= (bStretchToConstraint *)cdata;
2710 data->orglength = 0.0;
2714 static void stretchto_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
2716 bStretchToConstraint *data= con->data;
2719 func(con, (ID**)&data->tar, userdata);
2722 static int stretchto_get_tars (bConstraint *con, ListBase *list)
2725 bStretchToConstraint *data= con->data;
2726 bConstraintTarget *ct;
2728 /* standard target-getting macro for single-target constraints */
2729 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
2737 static void stretchto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
2740 bStretchToConstraint *data= con->data;
2741 bConstraintTarget *ct= list->first;
2743 /* the following macro is used for all standard single-target constraints */
2744 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
2748 static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
2750 bStretchToConstraint *data= con->data;
2751 bConstraintTarget *ct= targets->first;
2753 /* only evaluate if there is a target */
2754 if (VALID_CONS_TARGET(ct)) {
2755 float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
2760 /* store scaling before destroying obmat */
2761 mat4_to_size(size, cob->matrix);
2763 /* store X orientation before destroying obmat */
2764 normalize_v3_v3(xx, cob->matrix[0]);
2766 /* store Z orientation before destroying obmat */
2767 normalize_v3_v3(zz, cob->matrix[2]);
2769 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
2774 dist = normalize_v3(vec);
2775 //dist = len_v3v3( ob->obmat[3], targetmat[3]);
2777 /* data->orglength==0 occurs on first run, and after 'R' button is clicked */
2778 if (data->orglength == 0)
2779 data->orglength = dist;
2780 if (data->bulge == 0)
2783 scale[1] = dist/data->orglength;
2784 switch (data->volmode) {
2785 /* volume preserving scaling */
2787 scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
2788 scale[2] = scale[0];
2791 scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
2796 scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
2798 /* don't care for volume */
2803 default: /* should not happen, but in case*/
2805 } /* switch (data->volmode) */
2807 /* Clear the object's rotation and scale */
2808 cob->matrix[0][0]=size[0]*scale[0];
2809 cob->matrix[0][1]=0;
2810 cob->matrix[0][2]=0;
2811 cob->matrix[1][0]=0;
2812 cob->matrix[1][1]=size[1]*scale[1];
2813 cob->matrix[1][2]=0;
2814 cob->matrix[2][0]=0;
2815 cob->matrix[2][1]=0;
2816 cob->matrix[2][2]=size[2]*scale[2];
2818 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);
2821 /* new Y aligns object target connection*/
2822 negate_v3_v3(totmat[1], vec);
2823 switch (data->plane) {
2825 /* build new Z vector */
2826 /* othogonal to "new Y" "old X! plane */
2827 cross_v3_v3v3(orth, vec, xx);
2831 copy_v3_v3(totmat[2], orth);
2833 /* we decided to keep X plane*/
2834 cross_v3_v3v3(xx, orth, vec);
2835 normalize_v3_v3(totmat[0], xx);
2838 /* build new X vector */
2839 /* othogonal to "new Y" "old Z! plane */
2840 cross_v3_v3v3(orth, vec, zz);
2844 negate_v3_v3(totmat[0], orth);
2846 /* we decided to keep Z */
2847 cross_v3_v3v3(zz, orth, vec);
2848 normalize_v3_v3(totmat[2], zz);
2850 } /* switch (data->plane) */
2852 copy_m4_m4(tmat, cob->matrix);
2853 mul_m4_m3m4(cob->matrix, totmat, tmat);
2857 static bConstraintTypeInfo CTI_STRETCHTO = {
2858 CONSTRAINT_TYPE_STRETCHTO, /* type */
2859 sizeof(bStretchToConstraint), /* size */
2860 "Stretch To", /* name */
2861 "bStretchToConstraint", /* struct name */
2862 NULL, /* free data */
2863 NULL, /* relink data */
2864 stretchto_id_looper, /* id looper */
2865 NULL, /* copy data */
2866 stretchto_new_data, /* new data */
2867 stretchto_get_tars, /* get constraint targets */
2868 stretchto_flush_tars, /* flush constraint targets */