== Transformation Constraint ==
[blender.git] / source / blender / blenkernel / intern / constraint.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): 2007, Joshua Leung, major recode
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h> 
34 #include <string.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38 #include "nla.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42
43 #include "DNA_armature_types.h"
44 #include "DNA_constraint_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_action_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_scene_types.h"
49
50 #include "BKE_utildefines.h"
51 #include "BKE_action.h"
52 #include "BKE_anim.h" // for the curve calculation part
53 #include "BKE_armature.h"
54 #include "BKE_blender.h"
55 #include "BKE_constraint.h"
56 #include "BKE_displist.h"
57 #include "BKE_object.h"
58 #include "BKE_ipo.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_idprop.h"
62
63 #include "BPY_extern.h"
64
65 #include "blendef.h"
66
67 #ifdef HAVE_CONFIG_H
68 #include <config.h>
69 #endif
70
71 #ifndef M_PI
72 #define M_PI            3.14159265358979323846
73 #endif
74
75
76 /* ********************* Data level ****************** */
77
78 void free_constraint_data (bConstraint *con)
79 {
80         if (con->data) {
81                 /* any constraint-type specific stuff here */
82                 switch (con->type) {
83                         case CONSTRAINT_TYPE_PYTHON:
84                         {
85                                 bPythonConstraint *data= con->data;
86                                 IDP_FreeProperty(data->prop);
87                                 MEM_freeN(data->prop);
88                         }
89                                 break;
90                 }
91                 
92                 MEM_freeN(con->data);
93         }
94 }
95
96 void free_constraints (ListBase *conlist)
97 {
98         bConstraint *con;
99         
100         /* Do any specific freeing */
101         for (con=conlist->first; con; con=con->next) {
102                 free_constraint_data(con);
103         }
104         
105         /* Free the whole list */
106         BLI_freelistN(conlist);
107 }
108
109 void free_constraint_channels (ListBase *chanbase)
110 {
111         bConstraintChannel *chan;
112         
113         for (chan=chanbase->first; chan; chan=chan->next) {
114                 if (chan->ipo) {
115                         chan->ipo->id.us--;
116                 }
117         }
118         
119         BLI_freelistN(chanbase);
120 }
121
122 void relink_constraints (struct ListBase *list)
123 {
124         bConstraint *con;
125         
126         for (con = list->first; con; con=con->next) {
127                 /* check if constraint has a target that needs relinking */
128                 if (constraint_has_target(con)) {
129                         Object *tar;
130                         char *subtarget;
131                         
132                         tar = get_constraint_target(con, &subtarget);
133                         ID_NEW(tar);
134                 }
135         }
136 }
137
138 void copy_constraint_channels (ListBase *dst, ListBase *src)
139 {
140         bConstraintChannel *dchan, *schan;
141         
142         dst->first=dst->last=NULL;
143         duplicatelist(dst, src);
144         
145         for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
146                 dchan->ipo = copy_ipo(schan->ipo);
147         }
148 }
149
150 void clone_constraint_channels (ListBase *dst, ListBase *src)
151 {
152         bConstraintChannel *dchan, *schan;
153         
154         dst->first=dst->last=NULL;
155         duplicatelist(dst, src);
156         
157         for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
158                 id_us_plus((ID *)dchan->ipo);
159         }
160 }
161
162 void copy_constraints (ListBase *dst, ListBase *src)
163 {
164         bConstraint *con, *srccon;
165         
166         dst->first= dst->last= NULL;
167         duplicatelist (dst, src);
168         
169         for (con = dst->first, srccon=src->first; con; srccon=srccon->next, con=con->next) {
170                 con->data = MEM_dupallocN (con->data);
171                 
172                 /* only do specific constraints if required */
173                 if (con->type == CONSTRAINT_TYPE_PYTHON) {
174                         bPythonConstraint *pycon = (bPythonConstraint *)con->data;
175                         bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
176                         
177                         pycon->prop = IDP_CopyProperty(opycon->prop);
178                 }
179         }
180 }
181
182 /* **************** Editor Functions **************** */
183
184 char constraint_has_target (bConstraint *con) 
185 {
186         switch (con->type) {
187         case CONSTRAINT_TYPE_PYTHON:
188                 {
189                         bPythonConstraint *data = con->data;
190                         if (data->tar) return 1;
191                 }
192                 break;
193         case CONSTRAINT_TYPE_TRACKTO:
194                 {
195                         bTrackToConstraint *data = con->data;
196                         if (data->tar) return 1;
197                 }
198                 break;
199         case CONSTRAINT_TYPE_KINEMATIC:
200                 {
201                         bKinematicConstraint *data = con->data;
202                         if (data->tar) return 1;
203                 }
204                 break;
205         case CONSTRAINT_TYPE_FOLLOWPATH:
206                 {
207                         bFollowPathConstraint *data = con->data;
208                         if (data->tar) return 1;
209                 }
210                 break;
211         case CONSTRAINT_TYPE_ROTLIKE:
212                 {
213                         bRotateLikeConstraint *data = con->data;
214                         if (data->tar) return 1;
215                 }
216                 break;
217         case CONSTRAINT_TYPE_LOCLIKE:
218                 {
219                         bLocateLikeConstraint *data = con->data;
220                         if (data->tar) return 1;
221                 }
222                 break;
223         case CONSTRAINT_TYPE_SIZELIKE:
224                 {
225                         bSizeLikeConstraint *data = con->data;
226                         if (data->tar) return 1;
227                 }
228                 break;
229         case CONSTRAINT_TYPE_MINMAX:
230                 {
231                         bMinMaxConstraint *data = con->data;
232                         if (data->tar) return 1;
233                 }
234                 break;
235         case CONSTRAINT_TYPE_ACTION:
236                 {
237                         bActionConstraint *data = con->data;
238                         if (data->tar) return 1;
239                 }
240                 break;
241         case CONSTRAINT_TYPE_LOCKTRACK:
242                 {
243                         bLockTrackConstraint *data = con->data;
244                         if (data->tar) return 1;
245                 }
246         case CONSTRAINT_TYPE_STRETCHTO:
247                 {
248                         bStretchToConstraint *data = con->data;
249                         if (data->tar) return 1;
250                 }
251                 break;
252         case CONSTRAINT_TYPE_RIGIDBODYJOINT:
253                 {
254                         bRigidBodyJointConstraint *data = con->data;
255                         if (data->tar) return 1;
256                 }
257                 break;
258         case CONSTRAINT_TYPE_CLAMPTO:
259                 {
260                         bClampToConstraint *data = con->data;
261                         if (data->tar) return 1;
262                 }
263                         break;
264         case CONSTRAINT_TYPE_CHILDOF:
265                 {
266                         bChildOfConstraint *data = con->data;
267                         if (data->tar) return 1;
268                 }
269                 break;
270         case CONSTRAINT_TYPE_TRANSFORM:
271                 {
272                         bTransformConstraint *data = con->data;
273                         if (data->tar) return 1;
274                 }
275                 break;
276         }
277         
278         /* Unknown types or CONSTRAINT_TYPE_NULL or no target */
279         return 0;
280 }
281
282 Object *get_constraint_target(bConstraint *con, char **subtarget)
283 {
284         /* If the target for this constraint is target, return a pointer 
285          * to the name for this constraints subtarget ... NULL otherwise
286          */
287         switch (con->type) {
288         case CONSTRAINT_TYPE_PYTHON:
289                 {
290                         bPythonConstraint *data=con->data;
291                         *subtarget = data->subtarget;
292                         return data->tar;
293                 }
294                 break;
295         case CONSTRAINT_TYPE_ACTION:
296                 {
297                         bActionConstraint *data = con->data;
298                         *subtarget= data->subtarget;
299                         return data->tar;
300                 }
301                 break;
302         case CONSTRAINT_TYPE_LOCLIKE:
303                 {
304                         bLocateLikeConstraint *data = con->data;
305                         *subtarget= data->subtarget;
306                         return data->tar;
307                 }
308                 break;
309         case CONSTRAINT_TYPE_ROTLIKE:
310                 {
311                         bRotateLikeConstraint *data = con->data;
312                         *subtarget= data->subtarget;
313                         return data->tar;
314                 }
315                 break;
316         case CONSTRAINT_TYPE_SIZELIKE:
317                 {
318                         bSizeLikeConstraint *data = con->data;
319                         *subtarget= data->subtarget;
320                         return data->tar;
321                 }
322                 break;
323         case CONSTRAINT_TYPE_KINEMATIC:
324                 {
325                         bKinematicConstraint *data = con->data;
326                         *subtarget= data->subtarget;
327                         return data->tar;
328                 }
329                 break;
330         case CONSTRAINT_TYPE_TRACKTO:
331                 {
332                         bTrackToConstraint *data = con->data;
333                         *subtarget= data->subtarget;
334                         return data->tar;
335                 }
336                 break;
337         case CONSTRAINT_TYPE_MINMAX:
338                 {
339                         bMinMaxConstraint *data = con->data;
340                         *subtarget= data->subtarget;
341                         return data->tar;
342                 }
343                 break;
344         case CONSTRAINT_TYPE_LOCKTRACK:
345                 {
346                         bLockTrackConstraint *data = con->data;
347                         *subtarget= data->subtarget;
348                         return data->tar;
349                 }
350                 break;
351         case CONSTRAINT_TYPE_FOLLOWPATH: 
352                 {
353                         bFollowPathConstraint *data = con->data;
354                         *subtarget= NULL;
355                         return data->tar;
356                 }
357                 break;
358         case CONSTRAINT_TYPE_STRETCHTO:
359                 {
360                         bStretchToConstraint *data = con->data;
361                         *subtarget= data->subtarget;
362                         return data->tar;
363                 }
364                 break;
365         case CONSTRAINT_TYPE_RIGIDBODYJOINT: 
366                 {
367                         bRigidBodyJointConstraint *data = con->data;
368                         *subtarget= NULL;
369                         return data->tar;
370                 }
371                 break;
372         case CONSTRAINT_TYPE_CLAMPTO:
373                 {
374                         bClampToConstraint *data = con->data;
375                         *subtarget= NULL;
376                         return data->tar;
377                 }
378                 break;
379         case CONSTRAINT_TYPE_CHILDOF:   
380                 {
381                         bChildOfConstraint *data = con->data;
382                         *subtarget= data->subtarget;
383                         return data->tar;
384                 }
385                 break;
386         case CONSTRAINT_TYPE_TRANSFORM: 
387                 {
388                         bTransformConstraint *data = con->data;
389                         *subtarget= data->subtarget;
390                         return data->tar;
391                 }
392                 break;
393         default:
394                 *subtarget= NULL;
395                 break;
396         }
397         
398         return NULL;  
399 }
400
401 void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
402 {
403         /* Set the target for this constraint */
404         switch (con->type) {
405                 case CONSTRAINT_TYPE_PYTHON:
406                 {
407                         bPythonConstraint *data = con->data;
408                         data->tar= ob;
409                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
410                 }
411                         break;          
412                 case CONSTRAINT_TYPE_ACTION:
413                 {
414                         bActionConstraint *data = con->data;
415                         data->tar= ob;
416                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
417                 }
418                         break;
419                 case CONSTRAINT_TYPE_LOCLIKE:
420                 {
421                         bLocateLikeConstraint *data = con->data;
422                         data->tar= ob;
423                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
424                 }
425                         break;
426                 case CONSTRAINT_TYPE_ROTLIKE:
427                 {
428                         bRotateLikeConstraint *data = con->data;
429                         data->tar= ob;
430                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
431                 }
432                         break;
433                 case CONSTRAINT_TYPE_SIZELIKE:
434                 {
435                         bSizeLikeConstraint *data = con->data;
436                         data->tar= ob;
437                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
438                 }
439                         break;
440                 case CONSTRAINT_TYPE_KINEMATIC:
441                 {
442                         bKinematicConstraint *data = con->data;
443                         data->tar= ob;
444                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
445                 }
446                         break;
447                 case CONSTRAINT_TYPE_TRACKTO:
448                 {
449                         bTrackToConstraint *data = con->data;
450                         data->tar= ob;
451                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
452                 }
453                         break;
454                 case CONSTRAINT_TYPE_LOCKTRACK:
455                 {
456                         bLockTrackConstraint *data = con->data;
457                         data->tar= ob;
458                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
459                 }
460                         break;
461                 case CONSTRAINT_TYPE_FOLLOWPATH: 
462                 {
463                         bFollowPathConstraint *data = con->data;
464                         data->tar= ob;
465                 }
466                         break;
467                 case CONSTRAINT_TYPE_STRETCHTO:
468                 {
469                         bStretchToConstraint *data = con->data;
470                         data->tar= ob;
471                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
472                 }
473                         break;
474                 case CONSTRAINT_TYPE_RIGIDBODYJOINT: 
475                 {
476                         bRigidBodyJointConstraint *data = con->data;
477                         data->tar= ob;
478                 }
479                         break;
480                 case CONSTRAINT_TYPE_MINMAX:
481                 {
482                         bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
483                         data->tar= ob;
484                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
485                 }
486                         break;
487                 case CONSTRAINT_TYPE_CLAMPTO: 
488                 {
489                         bClampToConstraint *data = con->data;
490                         data->tar= ob;
491                 }
492                         break;
493                 case CONSTRAINT_TYPE_CHILDOF:
494                 {
495                         bChildOfConstraint *data = con->data;
496                         data->tar= ob;
497                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
498                 }
499                         break;
500                 case CONSTRAINT_TYPE_TRANSFORM:
501                 {
502                         bTransformConstraint *data = con->data;
503                         data->tar= ob;
504                         if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
505                 }
506                         break;
507         }
508 }
509
510 void unique_constraint_name (bConstraint *con, ListBase *list)
511 {
512         bConstraint *curcon;
513         char tempname[64];
514         int     number = 1, exists = 0;
515         char *dot;
516         
517         /* See if we are given an empty string */
518         if (con->name[0] == '\0') {
519                 /* give it default name first */
520                 strcpy(con->name, "Const");
521         }
522         
523         /* See if we even need to do this */
524         for (curcon = list->first; curcon; curcon=curcon->next) {
525                 if (curcon != con) {
526                         if (!strcmp(curcon->name, con->name)) {
527                                 exists = 1;
528                                 break;
529                         }
530                 }
531         }
532         
533         if (!exists)
534                 return;
535
536         /*      Strip off the suffix */
537         dot=strchr(con->name, '.');
538         if (dot)
539                 *dot=0;
540         
541         for (number = 1; number <= 999; number++) {
542                 sprintf(tempname, "%s.%03d", con->name, number);
543                 
544                 exists = 0;
545                 for (curcon=list->first; curcon; curcon=curcon->next) {
546                         if (con!=curcon) {
547                                 if (!strcmp(curcon->name, tempname)) {
548                                         exists = 1;
549                                         break;
550                                 }
551                         }
552                 }
553                 if (!exists) {
554                         strcpy(con->name, tempname);
555                         return;
556                 }
557         }
558 }
559
560 void *new_constraint_data (short type)
561 {
562         void *result;
563         
564         switch (type) {
565         case CONSTRAINT_TYPE_PYTHON:
566                 {
567                         bPythonConstraint *data;
568                         data = MEM_callocN(sizeof(bPythonConstraint), "pythonConstraint");
569                         
570                         /* everything should be set correctly by calloc, except for the prop->type constant.*/
571                         data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
572                         data->prop->type = IDP_GROUP;
573                         
574                         result = data;
575                 }
576                 break;          
577         case CONSTRAINT_TYPE_KINEMATIC:
578                 {
579                         bKinematicConstraint *data;
580                         data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
581
582                         data->weight= (float)1.0;
583                         data->orientweight= (float)1.0;
584                         data->iterations = 500;
585                         data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
586                         
587                         result = data;
588                 }
589                 break;
590         case CONSTRAINT_TYPE_TRACKTO:
591                 {
592                         bTrackToConstraint *data;
593                         data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
594                         
595                         data->reserved1 = TRACK_Y;
596                         data->reserved2 = UP_Z;
597                         
598                         result = data;
599                 }
600                 break;
601         case CONSTRAINT_TYPE_MINMAX:
602                 {
603                         bMinMaxConstraint *data;
604                         data = MEM_callocN(sizeof(bMinMaxConstraint), "minmaxConstraint");
605                         
606                         data->minmaxflag = TRACK_Z;
607                         data->offset = 0.0f;
608                         data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
609                         data->flag = 0;
610                         
611                         result = data;
612                 }
613                 break;
614         case CONSTRAINT_TYPE_LOCLIKE:
615                 {
616                         bLocateLikeConstraint *data;
617                         data = MEM_callocN(sizeof(bLocateLikeConstraint), "LocLikeConstraint");
618                         data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
619                         result = data;
620                 }
621                 break;
622         case CONSTRAINT_TYPE_ROTLIKE:
623                 {
624                         bRotateLikeConstraint *data;
625                         data = MEM_callocN(sizeof(bRotateLikeConstraint), "RotLikeConstraint");
626                         data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
627                         result = data;
628                 }
629                 break;
630         case CONSTRAINT_TYPE_SIZELIKE:
631                 {
632                         bSizeLikeConstraint *data;
633                         data = MEM_callocN(sizeof(bLocateLikeConstraint), "SizeLikeConstraint");
634                         data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
635                         result = data;
636                 }
637                 break;
638         case CONSTRAINT_TYPE_ACTION:
639                 {
640                         bActionConstraint *data;
641                         data = MEM_callocN(sizeof(bActionConstraint), "ActionConstraint");
642                         
643                         /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */
644                         data->type = 20;
645                         
646                         result = data;
647                 }
648                 break;
649         case CONSTRAINT_TYPE_LOCKTRACK:
650                 {
651                         bLockTrackConstraint *data;
652                         data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
653                         
654                         data->trackflag = TRACK_Y;
655                         data->lockflag = LOCK_Z;
656                         
657                         result = data;
658                 }
659                 break;
660         case CONSTRAINT_TYPE_FOLLOWPATH:
661                 {
662                         bFollowPathConstraint *data;
663                         data = MEM_callocN(sizeof(bFollowPathConstraint), "followpathConstraint");
664
665                         data->trackflag = TRACK_Y;
666                         data->upflag = UP_Z;
667                         data->offset = 0;
668                         data->followflag = 0;
669
670                         result = data;
671                 }
672                 break;
673         case CONSTRAINT_TYPE_STRETCHTO:
674                 {
675                         bStretchToConstraint *data;
676                         data = MEM_callocN(sizeof(bStretchToConstraint), "StretchToConstraint");
677
678                         data->volmode = 0;
679                         data->plane = 0;
680                         data->orglength = 0.0; 
681                         data->bulge = 1.0;
682                         result = data;
683                 }
684                 break; 
685         case CONSTRAINT_TYPE_LOCLIMIT:
686                 {
687                         bLocLimitConstraint *data;
688                         data = MEM_callocN(sizeof(bLocLimitConstraint), "LocLimitConstraint");
689                         result = data;
690                 }
691                 break;
692         case CONSTRAINT_TYPE_ROTLIMIT:
693                 {
694                         bRotLimitConstraint *data;
695                         data = MEM_callocN(sizeof(bRotLimitConstraint), "RotLimitConstraint");
696                         result = data;
697                 }
698                 break;
699         case CONSTRAINT_TYPE_SIZELIMIT:
700                 {
701                         bSizeLimitConstraint *data;
702                         data = MEM_callocN(sizeof(bSizeLimitConstraint), "SizeLimitConstraint");
703                         result = data;
704                 }
705                 break;
706     case CONSTRAINT_TYPE_RIGIDBODYJOINT:
707                 {
708                         bRigidBodyJointConstraint *data;
709                         data = MEM_callocN(sizeof(bRigidBodyJointConstraint), "RigidBodyToConstraint");
710                         
711                         // removed code which set target of this constraint  
712             data->type=1;
713                         
714                         result = data;
715                 }
716                 break;
717         case CONSTRAINT_TYPE_CLAMPTO:
718                 {
719                         bClampToConstraint *data;
720                         data = MEM_callocN(sizeof(bClampToConstraint), "ClampToConstraint");
721                         result = data;
722                 }
723                 break;
724         case CONSTRAINT_TYPE_CHILDOF:
725                 {
726                         bChildOfConstraint *data;
727                         data = MEM_callocN(sizeof(bChildOfConstraint), "ChildOfConstraint");
728                         
729                         data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
730                                                         CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
731                                                         CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
732                         Mat4One(data->invmat);
733                         
734                         result = data;
735                 }
736                 break;
737         case CONSTRAINT_TYPE_TRANSFORM:
738                 {
739                         bTransformConstraint *data;
740                         data = MEM_callocN(sizeof(bTransformConstraint), "TransformationConstraint");
741                         
742                         data->map[0]= 0;
743                         data->map[1]= 1;
744                         data->map[2]= 2;
745                         
746                         result = data;
747                 }
748                 break;
749   
750         default:
751                 result = NULL;
752                 break;
753         }
754
755         return result;
756 }
757
758 bConstraintChannel *get_constraint_channel (ListBase *list, const char *name)
759 {
760         bConstraintChannel *chan;
761
762         for (chan = list->first; chan; chan=chan->next) {
763                 if (!strcmp(name, chan->name)) {
764                         return chan;
765                 }
766         }
767         return NULL;
768 }
769
770 /* finds or creates new constraint channel */
771 bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name)
772 {
773         bConstraintChannel *chan;
774         
775         chan= get_constraint_channel (list, name);
776         if(chan==NULL) {
777                 chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint chan");
778                 BLI_addtail(list, chan);
779                 strcpy(chan->name, name);
780         }
781         
782         return chan;
783 }
784
785
786 /* ***************** Evaluating ********************* */
787
788 /* package an object/bone for use in constraint evaluation */
789 /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
790 bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatype)
791 {
792         bConstraintOb *cob;
793         
794         /* create regardless of whether we have any data! */
795         cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb");
796         
797         /* based on type of available data */
798         switch (datatype) {
799                 case TARGET_OBJECT:
800                 {
801                         /* disregard subdata... calloc should set other values right */
802                         if (ob) {
803                                 cob->ob = ob;
804                                 cob->type = datatype;
805                                 Mat4CpyMat4(cob->matrix, ob->obmat);
806                                 Mat4CpyMat4(cob->startmat, ob->obmat);
807                         }
808                         else 
809                                 Mat4One(cob->matrix);
810                 }
811                         break;
812                 case TARGET_BONE:
813                 {
814                         /* only set if we have valid bone, otherwise default */
815                         if (ob && subdata) {
816                                 cob->ob = ob;
817                                 cob->pchan = (bPoseChannel *)subdata;
818                                 cob->type = datatype;
819                                 
820                                 /* matrix in world-space */
821                                 Mat4MulMat4 (cob->matrix, cob->pchan->pose_mat, ob->obmat);
822                                 Mat4CpyMat4(cob->startmat, cob->matrix);
823                         }
824                         else
825                                 Mat4One(cob->matrix);
826                                 Mat4CpyMat4(cob->startmat, cob->matrix);
827                 }
828                         break;
829                         
830                 default: // other types not yet handled
831                         Mat4One(cob->matrix);
832                         break;
833         }
834         
835         return cob;
836 }
837
838 /* cleanup after constraint evaluation */
839 void constraints_clear_evalob (bConstraintOb *cob)
840 {
841         float delta[4][4], imat[4][4];
842         
843         /* prevent crashes */
844         if (cob == NULL) 
845                 return;
846         
847         /* calculate delta of constraints evaluation */
848         Mat4Invert(imat, cob->startmat);
849         Mat4MulMat4(delta, cob->matrix, imat);
850         
851         /* copy matrices back to source */
852         switch (cob->type) {
853                 case TARGET_OBJECT:
854                 {
855                         /* copy new ob-matrix back to owner */
856                         Mat4CpyMat4(cob->ob->obmat, cob->matrix);
857                         
858                         /* copy inverse of delta back to owner */
859                         Mat4Invert(cob->ob->constinv, delta);
860                 }
861                         break;
862                 case TARGET_BONE:
863                 {
864                         /* copy new pose-matrix back to owner */
865                         Mat4MulMat4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
866                         
867                         /* copy inverse of delta back to owner */
868                         Mat4Invert(cob->pchan->constinv, delta);
869                 }
870                         break;
871         }
872         
873         /* free tempolary struct */
874         MEM_freeN(cob);
875 }
876
877 /* -------------------------------- Constraint Channels ---------------------------- */
878
879 /* does IPO's of constraint channels only */
880 void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
881 {
882         bConstraint *con;
883         bConstraintChannel *chan;
884         IpoCurve *icu= NULL;
885         
886         /* for each Constraint, calculate its Influence from the corresponding ConstraintChannel */
887         for (con=conbase->first; con; con=con->next) {
888                 chan = get_constraint_channel(chanbase, con->name);
889                 if (chan && chan->ipo) {
890                         calc_ipo(chan->ipo, ctime);
891                         for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
892                                 switch (icu->adrcode) {
893                                         case CO_ENFORCE:
894                                         {
895                                                 con->enforce = icu->curval;
896                                                 if (con->enforce<0.0f) con->enforce= 0.0f;
897                                                 else if (con->enforce>1.0f) con->enforce= 1.0f;
898                                         }
899                                                 break;
900                                 }
901                         }
902                 }
903         }
904 }
905
906 /* ------------------------------- Space-Conversion API ---------------------------- */
907
908 /* This function is responsible for the correct transformations/conversions 
909  * of a matrix from one space to another for constraint evaluation.
910  * For now, this is only implemented for Objects and PoseChannels.
911  */
912 static void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4], short from, short to)
913 {
914         float tempmat[4][4];
915         float diff_mat[4][4];
916         float imat[4][4];
917         
918         /* prevent crashes in these unlikely events  */
919         if (ob==NULL || mat==NULL) return;
920         /* optimise trick - check if need to do anything */
921         if (from == to) return;
922         
923         /* are we dealing with pose-channels or objects */
924         if (pchan) {
925                 /* pose channels */
926                 switch (from) {
927                         case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */
928                         {
929                                 /* world to pose */
930                                 if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_LOCAL || to==CONSTRAINT_SPACE_PARLOCAL) {
931                                         Mat4Invert(imat, ob->obmat);
932                                         Mat4CpyMat4(tempmat, mat);
933                                         Mat4MulMat4(mat, tempmat, imat);
934                                 }
935                                 /* pose to local */
936                                 if (to == CONSTRAINT_SPACE_LOCAL) {
937                                         /* call self with slightly different values */
938                                         constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
939                                 }
940                                 /* pose to local + parent */
941                                 else if (to == CONSTRAINT_SPACE_PARLOCAL) {
942                                         /* call self with slightly different values */
943                                         constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
944                                 }
945                         }
946                                 break;
947                         case CONSTRAINT_SPACE_POSE:     /* ---------- FROM POSESPACE ---------- */
948                         {
949                                 /* pose to world */
950                                 if (to == CONSTRAINT_SPACE_WORLD) {
951                                         Mat4CpyMat4(tempmat, mat);
952                                         Mat4MulMat4(mat, tempmat, ob->obmat);
953                                 }
954                                 /* pose to local */
955                                 else if (to == CONSTRAINT_SPACE_LOCAL) {
956                                         if (pchan->bone) {
957                                                 if (pchan->parent && pchan->parent->bone) {
958                                                         float offs_bone[4][4];
959                                                                 
960                                                         /* construct offs_bone the same way it is done in armature.c */
961                                                         Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
962                                                         VECCOPY(offs_bone[3], pchan->bone->head);
963                                                         offs_bone[3][1]+= pchan->parent->bone->length;
964                                                         
965                                                         if (pchan->bone->flag & BONE_HINGE) {
966                                                                 /* pose_mat = par_pose-space_location * chan_mat */
967                                                                 float tmat[4][4];
968                                                                 
969                                                                 /* the rotation of the parent restposition */
970                                                                 Mat4CpyMat4(tmat, pchan->parent->bone->arm_mat);
971                                                                 
972                                                                 /* the location of actual parent transform */
973                                                                 VECCOPY(tmat[3], offs_bone[3]);
974                                                                 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
975                                                                 Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]);
976                                                                 
977                                                                 Mat4MulMat4(diff_mat, offs_bone, tmat);
978                                                                 Mat4Invert(imat, diff_mat);
979                                                         }
980                                                         else {
981                                                                 /* pose_mat = par_pose_mat * bone_mat * chan_mat */
982                                                                 Mat4MulMat4(diff_mat, pchan->parent->pose_mat, offs_bone);
983                                                                 Mat4Invert(imat, diff_mat);
984                                                         }
985                                                 }
986                                                 else {
987                                                         /* pose_mat = chan_mat * arm_mat */
988                                                         Mat4Invert(imat, pchan->bone->arm_mat);
989                                                 }
990                                                 
991                                                 Mat4CpyMat4(tempmat, mat);
992                                                 Mat4MulMat4(mat, tempmat, imat);
993                                         }
994                                 }
995                                 /* pose to local with parent */
996                                 else if (to == CONSTRAINT_SPACE_PARLOCAL) {
997                                         if (pchan->bone) {
998                                                 Mat4Invert(imat, pchan->bone->arm_mat);
999                                                 Mat4CpyMat4(tempmat, mat);
1000                                                 Mat4MulMat4(mat, tempmat, imat);
1001                                         }
1002                                 }
1003                         }
1004                                 break;
1005                         case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */
1006                         {
1007                                 /* local to pose */
1008                                 if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) {
1009                                         /* do inverse procedure that was done for pose to local */
1010                                         if (pchan->bone) {
1011                                                 /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */                                         
1012                                                 if (pchan->parent) {
1013                                                         float offs_bone[4][4];
1014                                                                 
1015                                                         /* construct offs_bone the same way it is done in armature.c */
1016                                                         Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
1017                                                         VECCOPY(offs_bone[3], pchan->bone->head);
1018                                                         offs_bone[3][1]+= pchan->parent->bone->length;
1019                                                         
1020                                                         Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat);
1021                                                         Mat4CpyMat4(tempmat, mat);
1022                                                         Mat4MulMat4(mat, tempmat, diff_mat);
1023                                                 }
1024                                                 else {
1025                                                         Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
1026                                                         
1027                                                         Mat4CpyMat4(tempmat, mat);
1028                                                         Mat4MulMat4(mat, tempmat, diff_mat);
1029                                                 }
1030                                         }
1031                                 }
1032                                 /* local to world */
1033                                 if (to == CONSTRAINT_SPACE_WORLD) {
1034                                         /* call self with slightly different values */
1035                                         constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
1036                                 }
1037                         }
1038                                 break;
1039                         case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */
1040                         {
1041                                 /* local to pose */
1042                                 if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) {
1043                                         if (pchan->bone) {                                      
1044                                                 Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
1045                                                 Mat4CpyMat4(tempmat, mat);
1046                                                 Mat4MulMat4(mat, diff_mat, tempmat);
1047                                         }
1048                                 }
1049                                 /* local to world */
1050                                 if (to == CONSTRAINT_SPACE_WORLD) {
1051                                         /* call self with slightly different values */
1052                                         constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
1053                                 }
1054                         }
1055                                 break;
1056                 }
1057         }
1058         else {
1059                 /* objects */
1060                 if (from==CONSTRAINT_SPACE_WORLD && to==CONSTRAINT_SPACE_LOCAL) {
1061                         /* check if object has a parent - otherwise this won't work */
1062                         if (ob->parent) {
1063                                 /* 'subtract' parent's effects from owner */
1064                                 Mat4MulMat4(diff_mat, ob->parentinv, ob->parent->obmat);
1065                                 Mat4Invert(imat, diff_mat);
1066                                 Mat4CpyMat4(tempmat, mat);
1067                                 Mat4MulMat4(mat, tempmat, imat);
1068                         }
1069                 }
1070                 else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) {
1071                         /* check that object has a parent - otherwise this won't work */
1072                         if (ob->parent) {
1073                                 /* 'add' parent's effect back to owner */
1074                                 Mat4CpyMat4(tempmat, mat);
1075                                 Mat4MulMat4(diff_mat, ob->parentinv, ob->parent->obmat);
1076                                 Mat4MulMat4(mat, tempmat, diff_mat);
1077                         }
1078                 }
1079         }
1080 }
1081
1082 /* ------------------------------- Target ---------------------------- */
1083
1084 /* generic function to get the appropriate matrix for most target cases */
1085 /* The cases where the target can be object data have not been implemented */
1086 static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], short from, short to)
1087 {
1088         /*      Case OBJECT */
1089         if (!strlen(substring)) {
1090                 Mat4CpyMat4(mat, ob->obmat);
1091                 constraint_mat_convertspace(ob, NULL, mat, from, to);
1092         }
1093         /*      Case VERTEXGROUP */
1094         else if (ELEM(ob->type, OB_MESH, OB_LATTICE)) {
1095                 /* devise a matrix from the data in the vertexgroup */
1096                 /* TODO: will be handled in other files */
1097         }
1098         /*      Case BONE */
1099         else {
1100                 bPoseChannel *pchan;
1101                 
1102                 pchan = get_pose_channel(ob->pose, substring);
1103                 if (pchan) {
1104                         /* Multiply the PoseSpace accumulation/final matrix for this
1105                          * PoseChannel by the Armature Object's Matrix to get a worldspace
1106                          * matrix.
1107                          */
1108                         Mat4MulMat4(mat, pchan->pose_mat, ob->obmat);
1109                 } 
1110                 else
1111                         Mat4CpyMat4(mat, ob->obmat);
1112                         
1113                 /* convert matrix space as required */
1114                 constraint_mat_convertspace(ob, pchan, mat, from, to);
1115         }
1116 }
1117
1118
1119 /* stupid little cross product function, 0:x, 1:y, 2:z axes */
1120 static int basis_cross(int n, int m)
1121 {
1122         if(n-m == 1) return 1;
1123         if(n-m == -1) return -1;
1124         if(n-m == 2) return -1;
1125         if(n-m == -2) return 1;
1126         else return 0;
1127 }
1128
1129 static void vectomat(float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
1130 {
1131         float n[3];
1132         float u[3]; /* vector specifying the up axis */
1133         float proj[3];
1134         float right[3];
1135         float neg = -1;
1136         int right_index;
1137         
1138         VecCopyf(n, vec);
1139         if(Normalize(n) == 0.0) { 
1140                 n[0] = 0.0;
1141                 n[1] = 0.0;
1142                 n[2] = 1.0;
1143         }
1144         if(axis > 2) axis -= 3;
1145         else VecMulf(n,-1);
1146
1147         /* n specifies the transformation of the track axis */
1148
1149         if(flags & TARGET_Z_UP) { 
1150                 /* target Z axis is the global up axis */
1151                 u[0] = target_up[0];
1152                 u[1] = target_up[1];
1153                 u[2] = target_up[2];
1154         }
1155         else { 
1156                 /* world Z axis is the global up axis */
1157                 u[0] = 0;
1158                 u[1] = 0;
1159                 u[2] = 1;
1160         }
1161
1162         /* project the up vector onto the plane specified by n */
1163         Projf(proj, u, n); /* first u onto n... */
1164         VecSubf(proj, u, proj); /* then onto the plane */
1165         /* proj specifies the transformation of the up axis */
1166
1167         if(Normalize(proj) == 0.0) { /* degenerate projection */
1168                 proj[0] = 0.0;
1169                 proj[1] = 1.0;
1170                 proj[2] = 0.0;
1171         }
1172
1173         /* Normalized cross product of n and proj specifies transformation of the right axis */
1174         Crossf(right, proj, n);
1175         Normalize(right);
1176
1177         if(axis != upflag) {
1178                 right_index = 3 - axis - upflag;
1179                 neg = (float) basis_cross(axis, upflag);
1180
1181                 /* account for up direction, track direction */
1182                 m[right_index][0] = neg * right[0];
1183                 m[right_index][1] = neg * right[1];
1184                 m[right_index][2] = neg * right[2];
1185
1186                 m[upflag][0] = proj[0];
1187                 m[upflag][1] = proj[1];
1188                 m[upflag][2] = proj[2];
1189
1190                 m[axis][0] = n[0];
1191                 m[axis][1] = n[1];
1192                 m[axis][2] = n[2];
1193         }
1194         /* identity matrix - don't do anything if the two axes are the same */
1195         else {
1196                 m[0][0]= m[1][1]= m[2][2]= 1.0;
1197                 m[0][1]= m[0][2]= m[0][3]= 0.0;
1198                 m[1][0]= m[1][2]= m[1][3]= 0.0;
1199                 m[2][0]= m[2][1]= m[2][3]= 0.0;
1200         }
1201 }
1202
1203
1204 /* called during solve_constraints */
1205 /* also for make_parent, to find correct inverse of "follow path" */
1206 /* warning: ownerdata is PoseChannel or Object */
1207 /* ctime is global time, uncorrected for local bsystem_time */
1208 short get_constraint_target_matrix (bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime)
1209 {
1210         short valid=0;
1211
1212         switch (con->type) {
1213         case CONSTRAINT_TYPE_NULL:
1214                 {
1215                         Mat4One(mat);
1216                 }
1217                 break;
1218         case CONSTRAINT_TYPE_ACTION:
1219                 {
1220                         if (ownertype == TARGET_BONE) {
1221                                 extern void chan_calc_mat(bPoseChannel *chan);
1222                                 bActionConstraint *data = (bActionConstraint*)con->data;
1223                                 bPose *pose;
1224                                 bPoseChannel *pchan, *tchan;
1225                                 float tempmat[4][4], vec[3];
1226                                 float s, t;
1227                                 short axis;
1228                                 
1229                                 /* initialise return matrix */
1230                                 Mat4One(mat);
1231                                 
1232                                 /* only continue if there is a target  */
1233                                 if (data->tar==NULL) return 0;
1234                                 
1235                                 /* get the transform matrix of the target */
1236                                 constraint_target_to_mat4(data->tar, data->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, con->tarspace); // FIXME: change these spaces 
1237                                 
1238                                 /* determine where in transform range target is */
1239                                 /* data->type is mapped as follows for backwards compatability:
1240                                  *      00,01,02        - rotation (it used to be like this)
1241                                  *      10,11,12        - scaling
1242                                  *      20,21,22        - location
1243                                  */
1244                                 if (data->type < 10) {
1245                                         /* extract rotation (is in whatever space target should be in) */
1246                                         Mat4ToEul(tempmat, vec);
1247                                         vec[0] *= (float)(180.0/M_PI);
1248                                         vec[1] *= (float)(180.0/M_PI);
1249                                         vec[2] *= (float)(180.0/M_PI);
1250                                         axis= data->type;
1251                                 }
1252                                 else if (data->type < 20) {
1253                                         /* extract scaling (is in whatever space target should be in) */
1254                                         Mat4ToSize(tempmat, vec);
1255                                         axis= data->type - 10;
1256                                 }
1257                                 else {
1258                                         /* extract location */
1259                                         VECCOPY(vec, tempmat[3]);
1260                                         axis= data->type - 20;
1261                                 }
1262                                 
1263                                 /* Target defines the animation */
1264                                 s = (vec[axis]-data->min) / (data->max-data->min);
1265                                 CLAMP(s, 0, 1);
1266                                 t = ( s * (data->end-data->start)) + data->start;
1267                                 
1268                                 /* Get the appropriate information from the action, we make temp pose */
1269                                 pose = MEM_callocN(sizeof(bPose), "pose");
1270                                 
1271                                 pchan = ownerdata;
1272                                 tchan= verify_pose_channel(pose, pchan->name);
1273                                 extract_pose_from_action(pose, data->act, t);
1274                                 
1275                                 chan_calc_mat(tchan);
1276                                 
1277                                 Mat4CpyMat4(mat, tchan->chan_mat);
1278                                 
1279                                 /* Clean up */
1280                                 free_pose_channels(pose);
1281                                 MEM_freeN(pose);
1282                         }
1283                 }
1284                 break;
1285         case CONSTRAINT_TYPE_LOCLIKE:
1286                 {
1287                         bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
1288                         Object *ob= data->tar;
1289                         
1290                         if (data->tar) {
1291                                 if (strlen(data->subtarget)) {
1292                                         bPoseChannel *pchan;
1293                                         float tmat[4][4];
1294                                         
1295                                         pchan = get_pose_channel(ob->pose, data->subtarget);
1296                                         if (pchan) {
1297                                                 Mat4CpyMat4(tmat, pchan->pose_mat);
1298                                                 
1299                                                 if (data->flag & LOCLIKE_TIP) { 
1300                                                         VECCOPY(tmat[3], pchan->pose_tail);
1301                                                 }
1302                                                         
1303                                                 Mat4MulMat4(mat, tmat, ob->obmat);
1304                                         }
1305                                         else 
1306                                                 Mat4CpyMat4(mat, ob->obmat);
1307                                                 
1308                                         /* convert matrix space as required  */
1309                                         constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1310                                 }
1311                                 else {
1312                                         Mat4CpyMat4(mat, ob->obmat);
1313                                         
1314                                         /* convert matrix space as required */
1315                                         constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1316                                 }
1317                                 valid=1;
1318                         }
1319                         else
1320                                 Mat4One(mat);
1321                 } 
1322                 break;
1323         case CONSTRAINT_TYPE_ROTLIKE:
1324                 {
1325                         bRotateLikeConstraint *data;
1326                         data = (bRotateLikeConstraint*)con->data;
1327                         
1328                         if (data->tar) {
1329                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1330                                 valid=1;
1331                         }
1332                         else
1333                                 Mat4One(mat);
1334                 } 
1335                 break;
1336         case CONSTRAINT_TYPE_SIZELIKE:
1337                 {
1338                         bSizeLikeConstraint *data;
1339                         data = (bSizeLikeConstraint*)con->data;
1340                         
1341                         if (data->tar) {
1342                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1343                                 valid=1;
1344                         }
1345                         else
1346                                 Mat4One(mat);
1347                 } 
1348                 break;
1349         case CONSTRAINT_TYPE_MINMAX:
1350                 {
1351                         bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
1352                         
1353                         if (data->tar) {
1354                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1355                                 valid=1;
1356                         }
1357                         else
1358                                 Mat4One(mat);
1359                 } 
1360                 break;
1361         case CONSTRAINT_TYPE_TRACKTO:
1362                 {
1363                         bTrackToConstraint *data;
1364                         data = (bTrackToConstraint*)con->data;
1365                         
1366                         if (data->tar) {
1367                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1368                                 valid=1;
1369                         }
1370                         else
1371                                 Mat4One (mat);
1372                 }
1373                 break;
1374         case CONSTRAINT_TYPE_KINEMATIC:
1375                 {
1376                         bKinematicConstraint *data;
1377                         data = (bKinematicConstraint*)con->data;
1378                         
1379                         if (data->tar) {
1380                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1381                                 valid=1;
1382                         }
1383                         else if (data->flag & CONSTRAINT_IK_AUTO) {
1384                                 Object *ob= (Object *)ownerdata;
1385                                 
1386                                 if (ob==NULL)
1387                                         Mat4One(mat);
1388                                 else {
1389                                         float vec[3];
1390                                         /* move grabtarget into world space */
1391                                         VECCOPY(vec, data->grabtarget);
1392                                         Mat4MulVecfl(ob->obmat, vec);
1393                                         Mat4CpyMat4(mat, ob->obmat);
1394                                         VECCOPY(mat[3], vec);
1395                                 }
1396                         }
1397                         else
1398                                 Mat4One(mat);
1399                 } 
1400                 break;
1401         case CONSTRAINT_TYPE_LOCKTRACK:
1402                 {
1403                         bLockTrackConstraint *data;
1404                         data = (bLockTrackConstraint*)con->data;
1405                         
1406                         if (data->tar) {
1407                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace); 
1408                                 valid=1;
1409                         }
1410                         else
1411                                 Mat4One(mat);
1412                 } 
1413                 break;
1414         case CONSTRAINT_TYPE_FOLLOWPATH:
1415                 {
1416                         bFollowPathConstraint *data;
1417                         data = (bFollowPathConstraint*)con->data;
1418                         
1419                         if (data->tar) {
1420                                 Curve *cu;
1421                                 float q[4], vec[4], dir[3], *quat, x1;
1422                                 float totmat[4][4];
1423                                 float curvetime;
1424                                 
1425                                 Mat4One(totmat);
1426                                 Mat4One(mat);
1427                                 
1428                                 cu= data->tar->data;
1429                                 
1430                                 /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
1431                                         currently for paths to work it needs to go through the bevlist/displist system (ton) */
1432                                 
1433                                 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1434                                         makeDispListCurveTypes(data->tar, 0);
1435                                 if (cu->path && cu->path->data) {
1436                                         curvetime= bsystem_time(data->tar, data->tar->parent, (float)ctime, 0.0) - data->offset;
1437                                         
1438                                         if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
1439                                                 curvetime /= cu->pathlen;
1440                                                 CLAMP(curvetime, 0.0, 1.0);
1441                                         }
1442                                         
1443                                         if (where_on_path(data->tar, curvetime, vec, dir) ) {
1444                                                 if (data->followflag) {
1445                                                         quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
1446                                                         
1447                                                         Normalize(dir);
1448                                                         q[0]= (float)cos(0.5*vec[3]);
1449                                                         x1= (float)sin(0.5*vec[3]);
1450                                                         q[1]= -x1*dir[0];
1451                                                         q[2]= -x1*dir[1];
1452                                                         q[3]= -x1*dir[2];
1453                                                         QuatMul(quat, q, quat);
1454                                                         
1455                                                         QuatToMat4(quat, totmat);
1456                                                 }
1457                                                 VECCOPY(totmat[3], vec);
1458                                                 
1459                                                 Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
1460                                         }
1461                                 }
1462                                 valid=1;
1463                         }
1464                         else
1465                                 Mat4One(mat);
1466                 }
1467                 break;
1468         case CONSTRAINT_TYPE_STRETCHTO:
1469                 {
1470                         bStretchToConstraint *data;
1471                         data = (bStretchToConstraint*)con->data;
1472                         
1473                         if (data->tar) {
1474                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1475                                 valid = 1;
1476                         }
1477                         else
1478                                 Mat4One(mat);
1479                 }
1480                 break;
1481         case CONSTRAINT_TYPE_PYTHON:
1482                 {
1483                         bPythonConstraint *data;
1484                         data = (bPythonConstraint*)con->data;
1485                         
1486                         /* special exception for curves - depsgraph issues */
1487                         if (data->tar && data->tar->type == OB_CURVE) {
1488                                 Curve *cu= data->tar->data;
1489                                 
1490                                 /* this check is to make sure curve objects get updated on file load correctly.*/
1491                                 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1492                                         makeDispListCurveTypes(data->tar, 0);                           
1493                         }
1494                         
1495                         /* if the script doesn't set the target matrix for any reason, fall back to standard methods */
1496                         if (BPY_pyconstraint_targets(data, mat) < 1) {
1497                                 if (data->tar) {
1498                                         constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1499                                         valid = 1;
1500                                 }
1501                                 else
1502                                         Mat4One(mat);
1503                         }
1504                 }
1505                 break;
1506         case CONSTRAINT_TYPE_CLAMPTO:
1507                 {
1508                         bClampToConstraint *data;
1509                         data = (bClampToConstraint*)con->data;
1510                         
1511                         if (data->tar) {
1512                                 Curve *cu= data->tar->data;
1513                                 
1514                                 /* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
1515                                         currently for paths to work it needs to go through the bevlist/displist system (ton) */
1516                                 
1517                                 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1518                                         makeDispListCurveTypes(data->tar, 0);
1519                                 
1520                                 valid = 1;
1521                         }
1522                         
1523                         Mat4One(mat);
1524                 }
1525                 break;
1526         case CONSTRAINT_TYPE_CHILDOF:
1527                 {
1528                         bChildOfConstraint *data;
1529                         data= (bChildOfConstraint *)con->data;
1530                         
1531                         if (data->tar) {
1532                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1533                                 valid = 1;
1534                         }
1535                         else
1536                                 Mat4One(mat);
1537                 }
1538                 break;
1539         case CONSTRAINT_TYPE_TRANSFORM:
1540                 {
1541                         bTransformConstraint *data;
1542                         data= (bTransformConstraint *)con->data;
1543                         
1544                         if (data->tar) {
1545                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
1546                                 valid = 1;
1547                         }
1548                         else
1549                                 Mat4One(mat);
1550                 }
1551                 break;
1552
1553         default:
1554                 Mat4One(mat);
1555                 break;
1556         }
1557
1558         return valid;
1559 }
1560
1561 /* ---------------------------------------------- Constraint Evaluation ------------------------------------------------- */
1562
1563 /* This is only called during solve_constraints to solve a particular constraint.
1564  * It works on ownermat, and uses targetmat to help accomplish its tasks.
1565  */
1566 static void evaluate_constraint (bConstraint *constraint, float ownermat[][4], float targetmat[][4])
1567 {
1568         if (constraint == NULL || constraint->data == NULL)
1569                 return;
1570                 
1571         switch (constraint->type) {
1572         case CONSTRAINT_TYPE_NULL:
1573         case CONSTRAINT_TYPE_KINEMATIC: /* removed */
1574                 break;
1575         case CONSTRAINT_TYPE_PYTHON:
1576                 {
1577                         bPythonConstraint *data;
1578                         
1579                         data = constraint->data;
1580                         BPY_pyconstraint_eval(data, ownermat, targetmat);
1581                 } 
1582                 break;
1583         case CONSTRAINT_TYPE_ACTION:
1584                 {
1585                         bActionConstraint *data;
1586                         float temp[4][4];
1587                         
1588                         data = constraint->data;
1589                         Mat4CpyMat4(temp, ownermat);
1590                         
1591                         Mat4MulMat4(ownermat, targetmat, temp);
1592                 }
1593                 break;
1594         case CONSTRAINT_TYPE_LOCLIKE:
1595                 {
1596                         bLocateLikeConstraint *data;
1597                         float offset[3] = {0.0f, 0.0f, 0.0f};
1598
1599                         data = constraint->data;
1600                         
1601                         if (data->flag & LOCLIKE_OFFSET)
1602                                 VECCOPY(offset, ownermat[3]);
1603                         
1604                         if (data->flag & LOCLIKE_X) {
1605                                 ownermat[3][0] = targetmat[3][0];
1606                                 
1607                                 if(data->flag & LOCLIKE_X_INVERT) ownermat[3][0] *= -1;
1608                                 ownermat[3][0] += offset[0];
1609                         }
1610                         if (data->flag & LOCLIKE_Y) {
1611                                 ownermat[3][1] = targetmat[3][1];
1612                                 
1613                                 if(data->flag & LOCLIKE_Y_INVERT) ownermat[3][1] *= -1;
1614                                 ownermat[3][1] += offset[1];
1615                         }
1616                         if (data->flag & LOCLIKE_Z) {
1617                                 ownermat[3][2] = targetmat[3][2];
1618                                 
1619                                 if(data->flag & LOCLIKE_Z_INVERT) ownermat[3][2] *= -1;
1620                                 ownermat[3][2] += offset[2];
1621                         }
1622                 }
1623                 break;
1624         case CONSTRAINT_TYPE_ROTLIKE:
1625                 {
1626                         bRotateLikeConstraint *data;
1627                         float   loc[3];
1628                         float   eul[3], obeul[3];
1629                         float   size[3];
1630                         short changed= 0;
1631                         
1632                         data = constraint->data;
1633                         
1634                         VECCOPY(loc, ownermat[3]);
1635                         Mat4ToSize(ownermat, size);
1636                         
1637                         Mat4ToEul(targetmat, eul);
1638                         Mat4ToEul(ownermat, obeul);
1639                         
1640                         if ((data->flag & ROTLIKE_X)==0) {
1641                                 eul[0] = obeul[0];
1642                                 changed = 1;
1643                         }
1644                         else if (data->flag & ROTLIKE_X_INVERT) {
1645                                 eul[0] *= -1;
1646                                 changed = 1;
1647                         }       
1648                         if ((data->flag & ROTLIKE_Y)==0) {
1649                                 eul[1] = obeul[1];
1650                                 changed = 1;
1651                         }
1652                         else if (data->flag & ROTLIKE_Y_INVERT) {
1653                                 eul[1] *= -1;
1654                                 changed = 1;
1655                         }
1656                         if ((data->flag & ROTLIKE_Z)==0) {
1657                                 eul[2] = obeul[2];
1658                                 changed = 1;
1659                         }
1660                         else if (data->flag & ROTLIKE_Z_INVERT) {
1661                                 eul[2] *= -1;
1662                                 changed = 1;
1663                         }
1664                         
1665                         
1666                         if (changed) {
1667                                 compatible_eul(eul, obeul);
1668                                 LocEulSizeToMat4(ownermat, loc, eul, size);
1669                         }
1670                         else {
1671                                 float quat[4];
1672                                 
1673                                 Mat4ToQuat(targetmat, quat);
1674                                 LocQuatSizeToMat4(ownermat, loc, quat, size);
1675                         }       
1676                 }
1677                 break;
1678         case CONSTRAINT_TYPE_SIZELIKE:
1679                 {
1680                         bSizeLikeConstraint *data;
1681                         float obsize[3], size[3];
1682                         
1683                         data = constraint->data;
1684  
1685                         Mat4ToSize(targetmat, size);
1686                         Mat4ToSize(ownermat, obsize);
1687                         
1688                         if ((data->flag & SIZELIKE_X) && obsize[0] != 0)
1689                                 VecMulf(ownermat[0], size[0] / obsize[0]);
1690                         if ((data->flag & SIZELIKE_Y) && obsize[1] != 0)
1691                                 VecMulf(ownermat[1], size[1] / obsize[1]);
1692                         if ((data->flag & SIZELIKE_Z) && obsize[2] != 0)
1693                                 VecMulf(ownermat[2], size[2] / obsize[2]);
1694                 }
1695                 break;
1696         case CONSTRAINT_TYPE_MINMAX:
1697                 {
1698                         bMinMaxConstraint *data;
1699                         float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
1700                         float val1, val2;
1701                         int index;
1702                         
1703                         data = constraint->data;
1704                         
1705                         Mat4CpyMat4(obmat, ownermat);
1706                         Mat4CpyMat4(tarmat, targetmat);
1707                         
1708                         if (data->flag & MINMAX_USEROT) {
1709                                 /* take rotation of target into account by doing the transaction in target's localspace */
1710                                 Mat4Invert(imat, tarmat);
1711                                 Mat4MulMat4(tmat, obmat, imat);
1712                                 Mat4CpyMat4(obmat, tmat);
1713                                 Mat4One(tarmat);
1714                         }
1715                         
1716                         switch (data->minmaxflag) {
1717                         case TRACK_Z:
1718                                 val1 = tarmat[3][2];
1719                                 val2 = obmat[3][2]-data->offset;
1720                                 index = 2;
1721                                 break;
1722                         case TRACK_Y:
1723                                 val1 = tarmat[3][1];
1724                                 val2 = obmat[3][1]-data->offset;
1725                                 index = 1;
1726                                 break;
1727                         case TRACK_X:
1728                                 val1 = tarmat[3][0];
1729                                 val2 = obmat[3][0]-data->offset;
1730                                 index = 0;
1731                                 break;
1732                         case TRACK_nZ:
1733                                 val2 = tarmat[3][2];
1734                                 val1 = obmat[3][2]-data->offset;
1735                                 index = 2;
1736                                 break;
1737                         case TRACK_nY:
1738                                 val2 = tarmat[3][1];
1739                                 val1 = obmat[3][1]-data->offset;
1740                                 index = 1;
1741                                 break;
1742                         case TRACK_nX:
1743                                 val2 = tarmat[3][0];
1744                                 val1 = obmat[3][0]-data->offset;
1745                                 index = 0;
1746                                 break;
1747                         default:
1748                                 return;
1749                         }
1750                         
1751                         if (val1 > val2) {
1752                                 obmat[3][index] = tarmat[3][index] + data->offset;
1753                                 if (data->flag & MINMAX_STICKY) {
1754                                         if (data->flag & MINMAX_STUCK) {
1755                                                 VECCOPY(obmat[3], data->cache);
1756                                         } 
1757                                         else {
1758                                                 VECCOPY(data->cache, obmat[3]);
1759                                                 data->flag |= MINMAX_STUCK;
1760                                         }
1761                                 }
1762                                 if (data->flag & MINMAX_USEROT) {
1763                                         /* get out of localspace */
1764                                         Mat4MulMat4(tmat, obmat, targetmat);
1765                                         Mat4CpyMat4(ownermat, tmat);
1766                                 } 
1767                                 else {                  
1768                                         VECCOPY(ownermat[3], obmat[3]);
1769                                 }
1770                         } 
1771                         else {
1772                                 data->flag &= ~MINMAX_STUCK;
1773                         }
1774                 }
1775                 break;
1776         case CONSTRAINT_TYPE_TRACKTO:
1777                 {
1778                         bTrackToConstraint *data;
1779                         float size[3], vec[3];
1780                         float totmat[3][3];
1781                         float tmat[4][4];
1782
1783                         data = constraint->data;                        
1784                         
1785                         if (data->tar) {
1786                                 /* Get size property, since ob->size is only the object's own relative size, not its global one */
1787                                 Mat4ToSize (ownermat, size);
1788                                 
1789                                 /* Clear the object's rotation */       
1790                                 ownermat[0][0]=size[0];
1791                                 ownermat[0][1]=0;
1792                                 ownermat[0][2]=0;
1793                                 ownermat[1][0]=0;
1794                                 ownermat[1][1]=size[1];
1795                                 ownermat[1][2]=0;
1796                                 ownermat[2][0]=0;
1797                                 ownermat[2][1]=0;
1798                                 ownermat[2][2]=size[2];
1799                                 
1800                                 VecSubf(vec, ownermat[3], targetmat[3]);
1801                                 vectomat(vec, ownermat[2], 
1802                                                 (short)data->reserved1, (short)data->reserved2, 
1803                                                 data->flags, totmat);
1804                                 
1805                                 Mat4CpyMat4(tmat, ownermat);
1806                                 Mat4MulMat34(ownermat, totmat, tmat);
1807                         }
1808                 }
1809                 break;
1810         case CONSTRAINT_TYPE_LOCKTRACK:
1811                 {
1812                         bLockTrackConstraint *data;
1813                         float vec[3],vec2[3];
1814                         float totmat[3][3];
1815                         float tmpmat[3][3];
1816                         float invmat[3][3];
1817                         float tmat[4][4];
1818                         float mdet;
1819
1820                         data = constraint->data;                        
1821                         
1822                         if (data->tar) {
1823                                 /* Vector object -> target */
1824                                 VecSubf(vec, targetmat[3], ownermat[3]);
1825                                 switch (data->lockflag){
1826                                 case LOCK_X: /* LOCK X */
1827                                 {
1828                                         switch (data->trackflag) {
1829                                                 case TRACK_Y: /* LOCK X TRACK Y */
1830                                                 {
1831                                                         /* Projection of Vector on the plane */
1832                                                         Projf(vec2, vec, ownermat[0]);
1833                                                         VecSubf(totmat[1], vec, vec2);
1834                                                         Normalize(totmat[1]);
1835                                                         
1836                                                         /* the x axis is fixed */
1837                                                         totmat[0][0] = ownermat[0][0];
1838                                                         totmat[0][1] = ownermat[0][1];
1839                                                         totmat[0][2] = ownermat[0][2];
1840                                                         Normalize(totmat[0]);
1841                                                         
1842                                                         /* the z axis gets mapped onto a third orthogonal vector */
1843                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1844                                                 }
1845                                                         break;
1846                                                 case TRACK_Z: /* LOCK X TRACK Z */
1847                                                 {
1848                                                         /* Projection of Vector on the plane */
1849                                                         Projf(vec2, vec, ownermat[0]);
1850                                                         VecSubf(totmat[2], vec, vec2);
1851                                                         Normalize(totmat[2]);
1852
1853                                                         /* the x axis is fixed */
1854                                                         totmat[0][0] = ownermat[0][0];
1855                                                         totmat[0][1] = ownermat[0][1];
1856                                                         totmat[0][2] = ownermat[0][2];
1857                                                         Normalize(totmat[0]);
1858                                         
1859                                                         /* the z axis gets mapped onto a third orthogonal vector */
1860                                                         Crossf(totmat[1], totmat[2], totmat[0]);
1861                                                 }
1862                                                         break;
1863                                                 case TRACK_nY: /* LOCK X TRACK -Y */
1864                                                 {
1865                                                         /* Projection of Vector on the plane */
1866                                                         Projf(vec2, vec, ownermat[0]);
1867                                                         VecSubf(totmat[1], vec, vec2);
1868                                                         Normalize(totmat[1]);
1869                                                         VecMulf(totmat[1],-1);
1870                                                         
1871                                                         /* the x axis is fixed */
1872                                                         totmat[0][0] = ownermat[0][0];
1873                                                         totmat[0][1] = ownermat[0][1];
1874                                                         totmat[0][2] = ownermat[0][2];
1875                                                         Normalize(totmat[0]);
1876                                                         
1877                                                         /* the z axis gets mapped onto a third orthogonal vector */
1878                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1879                                                 }
1880                                                         break;
1881                                                 case TRACK_nZ: /* LOCK X TRACK -Z */
1882                                                 {
1883                                                         /* Projection of Vector on the plane */
1884                                                         Projf(vec2, vec, ownermat[0]);
1885                                                         VecSubf(totmat[2], vec, vec2);
1886                                                         Normalize(totmat[2]);
1887                                                         VecMulf(totmat[2],-1);
1888                                                                 
1889                                                         /* the x axis is fixed */
1890                                                         totmat[0][0] = ownermat[0][0];
1891                                                         totmat[0][1] = ownermat[0][1];
1892                                                         totmat[0][2] = ownermat[0][2];
1893                                                         Normalize(totmat[0]);
1894                                                                 
1895                                                         /* the z axis gets mapped onto a third orthogonal vector */
1896                                                         Crossf(totmat[1], totmat[2], totmat[0]);
1897                                                 }
1898                                                         break;
1899                                                 default:
1900                                                 {
1901                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1902                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1903                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1904                                                 }
1905                                                         break;
1906                                         }
1907                                 }
1908                                         break;
1909                                 case LOCK_Y: /* LOCK Y */
1910                                 {
1911                                         switch (data->trackflag) {
1912                                                 case TRACK_X: /* LOCK Y TRACK X */
1913                                                 {
1914                                                         /* Projection of Vector on the plane */
1915                                                         Projf(vec2, vec, ownermat[1]);
1916                                                         VecSubf(totmat[0], vec, vec2);
1917                                                         Normalize(totmat[0]);
1918                                                         
1919                                                         /* the y axis is fixed */
1920                                                         totmat[1][0] = ownermat[1][0];
1921                                                         totmat[1][1] = ownermat[1][1];
1922                                                         totmat[1][2] = ownermat[1][2];
1923                                                         Normalize(totmat[1]);
1924                                                         
1925                                                         /* the z axis gets mapped onto a third orthogonal vector */
1926                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1927                                                 }
1928                                                         break;
1929                                                 case TRACK_Z: /* LOCK Y TRACK Z */
1930                                                 {
1931                                                         /* Projection of Vector on the plane */
1932                                                         Projf(vec2, vec, ownermat[1]);
1933                                                         VecSubf(totmat[2], vec, vec2);
1934                                                         Normalize(totmat[2]);
1935
1936                                                         /* the y axis is fixed */
1937                                                         totmat[1][0] = ownermat[1][0];
1938                                                         totmat[1][1] = ownermat[1][1];
1939                                                         totmat[1][2] = ownermat[1][2];
1940                                                         Normalize(totmat[1]);
1941                                                         
1942                                                         /* the z axis gets mapped onto a third orthogonal vector */
1943                                                         Crossf(totmat[0], totmat[1], totmat[2]);
1944                                                 }
1945                                                         break;
1946                                                 case TRACK_nX: /* LOCK Y TRACK -X */
1947                                                 {
1948                                                         /* Projection of Vector on the plane */
1949                                                         Projf(vec2, vec, ownermat[1]);
1950                                                         VecSubf(totmat[0], vec, vec2);
1951                                                         Normalize(totmat[0]);
1952                                                         VecMulf(totmat[0],-1);
1953
1954                                                         /* the y axis is fixed */
1955                                                         totmat[1][0] = ownermat[1][0];
1956                                                         totmat[1][1] = ownermat[1][1];
1957                                                         totmat[1][2] = ownermat[1][2];
1958                                                         Normalize(totmat[1]);
1959                                                         
1960                                                         /* the z axis gets mapped onto a third orthogonal vector */
1961                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1962                                                 }
1963                                                         break;
1964                                                 case TRACK_nZ: /* LOCK Y TRACK -Z */
1965                                                 {
1966                                                         /* Projection of Vector on the plane */
1967                                                         Projf(vec2, vec, ownermat[1]);
1968                                                         VecSubf(totmat[2], vec, vec2);
1969                                                         Normalize(totmat[2]);
1970                                                         VecMulf(totmat[2],-1);
1971
1972                                                         /* the y axis is fixed */
1973                                                         totmat[1][0] = ownermat[1][0];
1974                                                         totmat[1][1] = ownermat[1][1];
1975                                                         totmat[1][2] = ownermat[1][2];
1976                                                         Normalize(totmat[1]);
1977                                                         
1978                                                         /* the z axis gets mapped onto a third orthogonal vector */
1979                                                         Crossf(totmat[0], totmat[1], totmat[2]);
1980                                                 }
1981                                                         break;
1982                                                 default:
1983                                                 {
1984                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1985                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1986                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1987                                                 }
1988                                                         break;
1989                                         }
1990                                 }
1991                                         break;
1992                                 case LOCK_Z: /* LOCK Z */
1993                                 {
1994                                         switch (data->trackflag) {
1995                                                 case TRACK_X: /* LOCK Z TRACK X */
1996                                                 {
1997                                                         /* Projection of Vector on the plane */
1998                                                         Projf(vec2, vec, ownermat[2]);
1999                                                         VecSubf(totmat[0], vec, vec2);
2000                                                         Normalize(totmat[0]);
2001                                                         
2002                                                         /* the z axis is fixed */
2003                                                         totmat[2][0] = ownermat[2][0];
2004                                                         totmat[2][1] = ownermat[2][1];
2005                                                         totmat[2][2] = ownermat[2][2];
2006                                                         Normalize(totmat[2]);
2007                                                         
2008                                                         /* the x axis gets mapped onto a third orthogonal vector */
2009                                                         Crossf(totmat[1], totmat[2], totmat[0]);
2010                                                 }
2011                                                         break;
2012                                                 case TRACK_Y: /* LOCK Z TRACK Y */
2013                                                 {
2014                                                         /* Projection of Vector on the plane */
2015                                                         Projf(vec2, vec, ownermat[2]);
2016                                                         VecSubf(totmat[1], vec, vec2);
2017                                                         Normalize(totmat[1]);
2018                                                         
2019                                                         /* the z axis is fixed */
2020                                                         totmat[2][0] = ownermat[2][0];
2021                                                         totmat[2][1] = ownermat[2][1];
2022                                                         totmat[2][2] = ownermat[2][2];
2023                                                         Normalize(totmat[2]);
2024                                                                 
2025                                                         /* the x axis gets mapped onto a third orthogonal vector */
2026                                                         Crossf(totmat[0], totmat[1], totmat[2]);
2027                                                 }
2028                                                         break;
2029                                                 case TRACK_nX: /* LOCK Z TRACK -X */
2030                                                 {
2031                                                         /* Projection of Vector on the plane */
2032                                                         Projf(vec2, vec, ownermat[2]);
2033                                                         VecSubf(totmat[0], vec, vec2);
2034                                                         Normalize(totmat[0]);
2035                                                         VecMulf(totmat[0],-1);
2036                                                         
2037                                                         /* the z axis is fixed */
2038                                                         totmat[2][0] = ownermat[2][0];
2039                                                         totmat[2][1] = ownermat[2][1];
2040                                                         totmat[2][2] = ownermat[2][2];
2041                                                         Normalize(totmat[2]);
2042                                                         
2043                                                         /* the x axis gets mapped onto a third orthogonal vector */
2044                                                         Crossf(totmat[1], totmat[2], totmat[0]);
2045                                                 }
2046                                                         break;
2047                                                 case TRACK_nY: /* LOCK Z TRACK -Y */
2048                                                 {
2049                                                         /* Projection of Vector on the plane */
2050                                                         Projf(vec2, vec, ownermat[2]);
2051                                                         VecSubf(totmat[1], vec, vec2);
2052                                                         Normalize(totmat[1]);
2053                                                         VecMulf(totmat[1],-1);
2054                                                         
2055                                                         /* the z axis is fixed */
2056                                                         totmat[2][0] = ownermat[2][0];
2057                                                         totmat[2][1] = ownermat[2][1];
2058                                                         totmat[2][2] = ownermat[2][2];
2059                                                         Normalize(totmat[2]);
2060                                                                 
2061                                                         /* the x axis gets mapped onto a third orthogonal vector */
2062                                                         Crossf(totmat[0], totmat[1], totmat[2]);
2063                                                 }
2064                                                         break;
2065                                                 default:
2066                                                 {
2067                                                                 totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
2068                                                                 totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
2069                                                                 totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
2070                                                 }
2071                                                         break;
2072                                         }
2073                                 }
2074                                         break;
2075                                 default:
2076                                         {
2077                                                 totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
2078                                                 totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
2079                                                 totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
2080                                         }
2081                                         break;
2082                                 }
2083                                 /* Block to keep matrix heading */
2084                                 tmpmat[0][0] = ownermat[0][0];tmpmat[0][1] = ownermat[0][1];tmpmat[0][2] = ownermat[0][2];
2085                                 tmpmat[1][0] = ownermat[1][0];tmpmat[1][1] = ownermat[1][1];tmpmat[1][2] = ownermat[1][2];
2086                                 tmpmat[2][0] = ownermat[2][0];tmpmat[2][1] = ownermat[2][1];tmpmat[2][2] = ownermat[2][2];
2087                                 Normalize(tmpmat[0]);
2088                                 Normalize(tmpmat[1]);
2089                                 Normalize(tmpmat[2]);
2090                                 Mat3Inv(invmat,tmpmat);
2091                                 Mat3MulMat3(tmpmat, totmat, invmat);
2092                                 totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
2093                                 totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
2094                                 totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
2095
2096                                 Mat4CpyMat4(tmat, ownermat);
2097
2098                                 mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
2099                                                                 totmat[1][0],totmat[1][1],totmat[1][2],
2100                                                                 totmat[2][0],totmat[2][1],totmat[2][2]);
2101                                 if (mdet==0)
2102                                 {
2103                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
2104                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
2105                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
2106                                 }
2107
2108                                 /* apply out transformaton to the object */
2109                                 Mat4MulMat34(ownermat, totmat, tmat);
2110                         }
2111                 }
2112                 break;
2113         case CONSTRAINT_TYPE_FOLLOWPATH:
2114                 {
2115                         bFollowPathConstraint *data;
2116                         float obmat[4][4];
2117                         float size[3], obsize[3];
2118                         
2119                         data = constraint->data;                        
2120                         
2121                         if (data->tar) {
2122                                 /* get Object local transform (loc/rot/size) to determine transformation from path */
2123                                 //object_to_mat4(ob, obmat);
2124                                 Mat4CpyMat4(obmat, ownermat); // FIXME!!!
2125                                 
2126                                 /* get scaling of object before applying constraint */
2127                                 Mat4ToSize(ownermat, size);
2128                                 
2129                                 /* apply targetmat - containing location on path, and rotation */
2130                                 Mat4MulSerie(ownermat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
2131                                 
2132                                 /* un-apply scaling caused by path */
2133                                 Mat4ToSize(ownermat, obsize);
2134                                 if (obsize[0] != 0)
2135                                         VecMulf(ownermat[0], size[0] / obsize[0]);
2136                                 if (obsize[1] != 0)
2137                                         VecMulf(ownermat[1], size[1] / obsize[1]);
2138                                 if (obsize[2] != 0)
2139                                         VecMulf(ownermat[2], size[2] / obsize[2]);
2140                         }
2141                 }
2142                 break;
2143         case CONSTRAINT_TYPE_STRETCHTO:
2144         {
2145             bStretchToConstraint *data;
2146             float size[3],scale[3],vec[3],xx[3],zz[3],orth[3];
2147             float totmat[3][3];
2148             float tmat[4][4];
2149             float dist;
2150                         
2151             data = constraint->data;            
2152             Mat4ToSize (ownermat, size);
2153             
2154             if (data->tar) {
2155                 /* store X orientation before destroying obmat */
2156                 xx[0] = ownermat[0][0];
2157                 xx[1] = ownermat[0][1];
2158                 xx[2] = ownermat[0][2];
2159                 Normalize(xx);
2160                                 
2161                 /* store Z orientation before destroying obmat */
2162                 zz[0] = ownermat[2][0];
2163                 zz[1] = ownermat[2][1];
2164                 zz[2] = ownermat[2][2];
2165                 Normalize(zz);
2166                                 
2167                                 VecSubf(vec, ownermat[3], targetmat[3]);
2168                                 vec[0] /= size[0];
2169                                 vec[1] /= size[1];
2170                                 vec[2] /= size[2];
2171
2172                                 dist = Normalize(vec);
2173                 //dist = VecLenf( ob->obmat[3], targetmat[3]);
2174
2175                 if (data->orglength == 0)  data->orglength = dist;
2176                 if (data->bulge ==0) data->bulge = 1.0;
2177
2178                 scale[1] = dist/data->orglength;
2179                 switch (data->volmode) {
2180                 /* volume preserving scaling */
2181                 case VOLUME_XZ :
2182                     scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
2183                     scale[2] = scale[0];
2184                     break;
2185                 case VOLUME_X:
2186                     scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
2187                     scale[2] = 1.0;
2188                     break;
2189                 case VOLUME_Z:
2190                     scale[0] = 1.0;
2191                     scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
2192                     break;
2193                     /* don't care for volume */
2194                 case NO_VOLUME:
2195                     scale[0] = 1.0;
2196                     scale[2] = 1.0;
2197                     break;
2198                 default: /* should not happen, but in case*/
2199                     return;    
2200                 } /* switch (data->volmode) */
2201
2202                 /* Clear the object's rotation and scale */
2203                                 ownermat[0][0]=size[0]*scale[0];
2204                                 ownermat[0][1]=0;
2205                                 ownermat[0][2]=0;
2206                                 ownermat[1][0]=0;
2207                                 ownermat[1][1]=size[1]*scale[1];
2208                                 ownermat[1][2]=0;
2209                                 ownermat[2][0]=0;
2210                                 ownermat[2][1]=0;
2211                                 ownermat[2][2]=size[2]*scale[2];
2212                 
2213                                 VecSubf(vec, ownermat[3], targetmat[3]);
2214                                 Normalize(vec);
2215                                 
2216                 /* new Y aligns  object target connection*/
2217                 totmat[1][0] = -vec[0];
2218                 totmat[1][1] = -vec[1];
2219                 totmat[1][2] = -vec[2];
2220                 switch (data->plane) {
2221                 case PLANE_X:
2222                     /* build new Z vector */
2223                     /* othogonal to "new Y" "old X! plane */
2224                     Crossf(orth, vec, xx);
2225                     Normalize(orth);
2226                     
2227                     /* new Z*/
2228                     totmat[2][0] = orth[0];
2229                     totmat[2][1] = orth[1];
2230                     totmat[2][2] = orth[2];
2231                     
2232                     /* we decided to keep X plane*/
2233                     Crossf(xx, orth, vec);
2234                     Normalize(xx);
2235                     totmat[0][0] = xx[0];
2236                     totmat[0][1] = xx[1];
2237                     totmat[0][2] = xx[2];
2238                     break;
2239                 case PLANE_Z:
2240                     /* build new X vector */
2241                     /* othogonal to "new Y" "old Z! plane */
2242                     Crossf(orth, vec, zz);
2243                     Normalize(orth);
2244                     
2245                     /* new X */
2246                     totmat[0][0] = -orth[0];
2247                     totmat[0][1] = -orth[1];
2248                     totmat[0][2] = -orth[2];
2249                     
2250                     /* we decided to keep Z */
2251                     Crossf(zz, orth, vec);
2252                     Normalize(zz);
2253                     totmat[2][0] = zz[0];
2254                     totmat[2][1] = zz[1];
2255                     totmat[2][2] = zz[2];
2256                     break;
2257                 } /* switch (data->plane) */
2258                 
2259                 Mat4CpyMat4(tmat, ownermat);
2260                                 
2261                 Mat4MulMat34(ownermat, totmat, tmat);
2262             }
2263         }
2264         break;
2265         case CONSTRAINT_TYPE_LOCLIMIT:
2266                 {
2267                         bLocLimitConstraint *data;
2268
2269                         data = constraint->data;
2270                         
2271                         if (data->flag & LIMIT_XMIN) {
2272                                 if(ownermat[3][0] < data->xmin)
2273                                         ownermat[3][0] = data->xmin;
2274                         }
2275                         if (data->flag & LIMIT_XMAX) {
2276                                 if (ownermat[3][0] > data->xmax)
2277                                         ownermat[3][0] = data->xmax;
2278                         }
2279                         if (data->flag & LIMIT_YMIN) {
2280                                 if(ownermat[3][1] < data->ymin)
2281                                         ownermat[3][1] = data->ymin;
2282                         }
2283                         if (data->flag & LIMIT_YMAX) {
2284                                 if (ownermat[3][1] > data->ymax)
2285                                         ownermat[3][1] = data->ymax;
2286                         }
2287                         if (data->flag & LIMIT_ZMIN) {
2288                                 if(ownermat[3][2] < data->zmin) 
2289                                         ownermat[3][2] = data->zmin;
2290                         }
2291                         if (data->flag & LIMIT_ZMAX) {
2292                                 if (ownermat[3][2] > data->zmax)
2293                                         ownermat[3][2] = data->zmax;
2294                         }
2295                 }
2296                 break;
2297         case CONSTRAINT_TYPE_ROTLIMIT:
2298                 {
2299                         bRotLimitConstraint *data;
2300                         float loc[3];
2301                         float eul[3];
2302                         float size[3];
2303                         
2304                         data = constraint->data;
2305                         
2306                         VECCOPY(loc, ownermat[3]);
2307                         Mat4ToSize(ownermat, size);
2308                         
2309                         Mat4ToEul(ownermat, eul);
2310                         
2311                         /* eulers: radians to degrees! */
2312                         eul[0] = (eul[0] / M_PI * 180);
2313                         eul[1] = (eul[1] / M_PI * 180);
2314                         eul[2] = (eul[2] / M_PI * 180);
2315                         
2316                         /* limiting of euler values... */
2317                         if (data->flag & LIMIT_XROT) {
2318                                 if (eul[0] < data->xmin) 
2319                                         eul[0] = data->xmin;
2320                                         
2321                                 if (eul[0] > data->xmax)
2322                                         eul[0] = data->xmax;
2323                         }
2324                         if (data->flag & LIMIT_YROT) {
2325                                 if (eul[1] < data->ymin)
2326                                         eul[1] = data->ymin;
2327                                         
2328                                 if (eul[1] > data->ymax)
2329                                         eul[1] = data->ymax;
2330                         }
2331                         if (data->flag & LIMIT_ZROT) {
2332                                 if (eul[2] < data->zmin)
2333                                         eul[2] = data->zmin;
2334                                         
2335                                 if (eul[2] > data->zmax)
2336                                         eul[2] = data->zmax;
2337                         }
2338                                 
2339                         /* eulers: degrees to radians ! */
2340                         eul[0] = (eul[0] / 180 * M_PI); 
2341                         eul[1] = (eul[1] / 180 * M_PI);
2342                         eul[2] = (eul[2] / 180 * M_PI);
2343                         
2344                         LocEulSizeToMat4(ownermat, loc, eul, size);
2345                 }
2346                 break;
2347         case CONSTRAINT_TYPE_SIZELIMIT:
2348                 {
2349                         bSizeLimitConstraint *data;
2350                         float obsize[3], size[3];
2351                         
2352                         data = constraint->data;
2353                         
2354                         Mat4ToSize(ownermat, size);
2355                         Mat4ToSize(ownermat, obsize);
2356                         
2357                         if (data->flag & LIMIT_XMIN) {
2358                                 if (size[0] < data->xmin) 
2359                                         size[0] = data->xmin;   
2360                         }
2361                         if (data->flag & LIMIT_XMAX) {
2362                                 if (size[0] > data->xmax) 
2363                                         size[0] = data->xmax;
2364                         }
2365                         if (data->flag & LIMIT_YMIN) {
2366                                 if (size[1] < data->ymin) 
2367                                         size[1] = data->ymin;   
2368                         }
2369                         if (data->flag & LIMIT_YMAX) {
2370                                 if (size[1] > data->ymax) 
2371                                         size[1] = data->ymax;
2372                         }
2373                         if (data->flag & LIMIT_ZMIN) {
2374                                 if (size[2] < data->zmin) 
2375                                         size[2] = data->zmin;   
2376                         }
2377                         if (data->flag & LIMIT_ZMAX) {
2378                                 if (size[2] > data->zmax) 
2379                                         size[2] = data->zmax;
2380                         }
2381                         
2382                         VecMulf(ownermat[0], size[0]/obsize[0]);
2383                         VecMulf(ownermat[1], size[1]/obsize[1]);
2384                         VecMulf(ownermat[2], size[2]/obsize[2]);
2385                 }
2386                 break;
2387         case CONSTRAINT_TYPE_RIGIDBODYJOINT:
2388         {
2389                         /* Do nothing. The GameEngine will take care of this.*/
2390         }
2391         break;  
2392         case CONSTRAINT_TYPE_CLAMPTO:
2393                 {
2394                         bClampToConstraint *data;
2395                         Curve *cu;
2396                         float obmat[4][4], targetMatrix[4][4], ownLoc[3];
2397                         float curveMin[3], curveMax[3];
2398                         
2399                         data = constraint->data;
2400                         
2401                         /* prevent crash if user deletes curve */
2402                         if ((data->tar == NULL) || (data->tar->type != OB_CURVE) ) 
2403                                 return;
2404                         else
2405                                 cu= data->tar->data;
2406                         
2407                         Mat4CpyMat4(obmat, ownermat);
2408                         Mat4One(targetMatrix);
2409                         VECCOPY(ownLoc, obmat[3]);
2410                         
2411                         INIT_MINMAX(curveMin, curveMax)
2412                         minmax_object(data->tar, curveMin, curveMax);
2413                         
2414                         /* get targetmatrix */
2415                         if (cu->path && cu->path->data) {
2416                                 float vec[4], dir[3], totmat[4][4];
2417                                 float curvetime;
2418                                 short clamp_axis;
2419                                 
2420                                 /* find best position on curve */
2421                                 /* 1. determine which axis to sample on? */
2422                                 if (data->flag==CLAMPTO_AUTO) {
2423                                         float size[3];
2424                                         VecSubf(size, curveMax, curveMin);
2425                                         
2426                                         /* find axis along which the bounding box has the greatest
2427                                          * extent. Otherwise, default to the x-axis, as that is quite
2428                                          * frequently used.
2429                                          */
2430                                         if ((size[2]>size[0]) && (size[2]>size[1]))
2431                                                 clamp_axis= CLAMPTO_Z;
2432                                         else if ((size[1]>size[0]) && (size[1]>size[2]))
2433                                                 clamp_axis= CLAMPTO_Y;
2434                                         else
2435                                                 clamp_axis = CLAMPTO_X;
2436                                 }
2437                                 else 
2438                                         clamp_axis= data->flag;
2439                                         
2440                                 /* 2. determine position relative to curve on a 0-1 scale */
2441                                 if (clamp_axis > 0) clamp_axis--;
2442                                 if (ownLoc[clamp_axis] <= curveMin[clamp_axis])
2443                                         curvetime = 0.0;
2444                                 else if (ownLoc[clamp_axis] >= curveMax[clamp_axis])
2445                                         curvetime = 1.0;
2446                                 else
2447                                         curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]);
2448                                 
2449                                 /* 3. position on curve */
2450                                 if(where_on_path(data->tar, curvetime, vec, dir) ) {
2451                                         Mat4One(totmat);
2452                                         VECCOPY(totmat[3], vec);
2453                                         
2454                                         Mat4MulSerie(targetMatrix, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
2455                                 }
2456                         }
2457                         
2458                         /* obtain final object position */
2459                         VECCOPY(ownermat[3], targetMatrix[3]);
2460                 }
2461                 break;
2462         case CONSTRAINT_TYPE_CHILDOF: 
2463                 {
2464                         bChildOfConstraint *data;
2465                         
2466                         data = constraint->data;
2467                         
2468                         /* only evaluate if there is a target */
2469                         if (data->tar) {
2470                                 float parmat[4][4], invmat[4][4], tempmat[4][4];
2471                                 float loc[3], eul[3], size[3];
2472                                 float loco[3], eulo[3], sizo[3];
2473                                 
2474                                 /* get offset (parent-inverse) matrix */
2475                                 Mat4CpyMat4(invmat, data->invmat);
2476                                 
2477                                 /* extract components of both matrices */
2478                                 VECCOPY(loc, targetmat[3]);
2479                                 Mat4ToEul(targetmat, eul);
2480                                 Mat4ToSize(targetmat, size);
2481                                 
2482                                 VECCOPY(loco, invmat[3]);
2483                                 Mat4ToEul(invmat, eulo);
2484                                 Mat4ToSize(invmat, sizo);
2485                                 
2486                                 /* disable channels not enabled */
2487                                 if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
2488                                 if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f;
2489                                 if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f;
2490                                 if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f;
2491                                 if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f;
2492                                 if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f;
2493                                 if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f;
2494                                 if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f;
2495                                 if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
2496                                 
2497                                 /* make new target mat and offset mat */
2498                                 LocEulSizeToMat4(targetmat, loc, eul, size);
2499                                 LocEulSizeToMat4(invmat, loco, eulo, sizo);
2500                                 
2501                                 /* multiply target (parent matrix) by offset (parent inverse) to get 
2502                                  * the effect of the parent that will be exherted on the owner
2503                                  */
2504                                 Mat4MulMat4(parmat, invmat, targetmat);
2505                                 
2506                                 /* now multiply the parent matrix by the owner matrix to get the 
2507                                  * the effect of this constraint (i.e.  owner is 'parented' to parent)
2508                                  */
2509                                 Mat4CpyMat4(tempmat, ownermat);
2510                                 Mat4MulMat4(ownermat, tempmat, parmat); 
2511                         }
2512                 }
2513                 break;
2514         case CONSTRAINT_TYPE_TRANSFORM:
2515                 {
2516                         bTransformConstraint *data;
2517                         
2518                         data = constraint->data;
2519                         
2520                         /* only work if there is a target */
2521                         if (data->tar) {
2522                                 float loc[3], eul[3], size[3];
2523                                 float dvec[3], sval[3];
2524                                 short i;
2525                                 
2526                                 /* obtain target effect */
2527                                 switch (data->from) {
2528                                         case 2: /* scale */
2529                                         {
2530                                                 Mat4ToSize(targetmat, dvec);
2531                                         }
2532                                                 break;
2533                                         case 1: /* rotation */
2534                                         {
2535                                                 /* copy, and reduce to smallest rotation distance */
2536                                                 Mat4ToEul(targetmat, dvec);
2537                                                 
2538                                                 /* reduce rotation */
2539                                                 for (i=0; i<3; i++)
2540                                                         dvec[i]= fmod(dvec[i], M_PI*2);
2541                                         }
2542                                                 break;
2543                                         default: /* location */
2544                                         {
2545                                                 VECCOPY(dvec, targetmat[3]);
2546                                         }
2547                                                 break;
2548                                 }
2549                                 
2550                                 /* extract components of owner's matrix */
2551                                 VECCOPY(loc, ownermat[3]);
2552                                 Mat4ToEul(ownermat, eul);
2553                                 Mat4ToSize(ownermat, size);
2554                                 
2555                                 /* determine where in range current transforms lie */
2556                                 if (data->expo) {
2557                                         for (i=0; i<3; i++) {
2558                                                 if (data->from_max[i] - data->from_min[i])
2559                                                         sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
2560                                                 else
2561                                                         sval[i]= 0.0f;
2562                                         }
2563                                 }
2564                                 else {
2565                                         /* clamp transforms out of range */
2566                                         for (i=0; i<3; i++) {
2567                                                 CLAMP(dvec[i], data->from_min[i], data->from_max[i]);
2568                                                 if (data->from_max[i] - data->from_min[i])
2569                                                         sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
2570                                                 else
2571                                                         sval[i]= 0.0f;
2572                                         }
2573                                 }
2574                                 
2575                                 /* convert radian<->degree */
2576                                 if (data->from==1 && data->to==0) {
2577           &nb