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