=ID Property update=
[blender-staging.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): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h> 
34 #include <string.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38 #include "nla.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42
43 #include "DNA_armature_types.h"
44 #include "DNA_constraint_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_action_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_scene_types.h"
49
50 #include "BKE_utildefines.h"
51 #include "BKE_action.h"
52 #include "BKE_anim.h" // for the curve calculation part
53 #include "BKE_armature.h"
54 #include "BKE_blender.h"
55 #include "BKE_constraint.h"
56 #include "BKE_displist.h"
57 #include "BKE_object.h"
58 #include "BKE_ipo.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_idprop.h"
62
63 #include "BPY_extern.h"
64
65 #include "blendef.h"
66
67 #ifdef HAVE_CONFIG_H
68 #include <config.h>
69 #endif
70
71 #ifndef M_PI
72 #define M_PI            3.14159265358979323846
73 #endif
74
75 /* Local function prototypes */
76
77 /* ********************* Data level ****************** */
78
79 void free_constraint_data (bConstraint *con)
80 {
81         if (con->data) {
82                 /* any constraint-type specific stuff here */
83                 switch (con->type) {
84                         case CONSTRAINT_TYPE_PYTHON:
85                         {
86                                 bPythonConstraint *data= con->data;
87                                 IDP_FreeProperty(data->prop);
88                                 MEM_freeN(data->prop);
89                         }
90                                 break;
91                 }
92                 
93                 MEM_freeN(con->data);
94         }
95 }
96
97 void free_constraints (ListBase *conlist)
98 {
99         bConstraint *con;
100         
101         /* Do any specific freeing */
102         for (con=conlist->first; con; con=con->next) {
103                 free_constraint_data(con);
104         }
105         
106         /* Free the whole list */
107         BLI_freelistN(conlist);
108 }
109
110 void free_constraint_channels (ListBase *chanbase)
111 {
112         bConstraintChannel *chan;
113         
114         for (chan=chanbase->first; chan; chan=chan->next) {
115                 if (chan->ipo) {
116                         chan->ipo->id.us--;
117                 }
118         }
119         
120         BLI_freelistN(chanbase);
121 }
122
123 void relink_constraints (struct ListBase *list)
124 {
125         bConstraint *con;
126         
127         for (con = list->first; con; con=con->next) {
128                 /* check if constraint has a target that needs relinking */
129                 if (constraint_has_target(con)) {
130                         Object *tar;
131                         char *subtarget;
132                         
133                         tar = get_constraint_target(con, &subtarget);
134                         ID_NEW(tar);
135                 }
136         }
137 }
138
139 void copy_constraint_channels (ListBase *dst, ListBase *src)
140 {
141         bConstraintChannel *dchan, *schan;
142         
143         dst->first=dst->last=NULL;
144         duplicatelist(dst, src);
145         
146         for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
147                 dchan->ipo = copy_ipo(schan->ipo);
148         }
149 }
150
151 void clone_constraint_channels (ListBase *dst, ListBase *src)
152 {
153         bConstraintChannel *dchan, *schan;
154         
155         dst->first=dst->last=NULL;
156         duplicatelist(dst, src);
157         
158         for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
159                 id_us_plus((ID *)dchan->ipo);
160         }
161 }
162
163 void copy_constraints (ListBase *dst, ListBase *src)
164 {
165         bConstraint *con, *srccon;
166         
167         dst->first= dst->last= NULL;
168         
169         duplicatelist (dst, src);
170         
171         for (con = dst->first, srccon=src->first; con; srccon=srccon->next, con=con->next) {
172                 con->data = MEM_dupallocN (con->data);
173                 if (con->type == CONSTRAINT_TYPE_PYTHON) {
174                         bPythonConstraint *pycon = (bPythonConstraint*) con->data;
175                         bPythonConstraint *opycon = (bPythonConstraint*) srccon->data;
176
177                         pycon->prop = IDP_CopyProperty(opycon->prop);
178                 }
179                 /* removed a whole lot of useless code here (ton) */
180         }
181 }
182
183
184 /* **************** Editor Functions **************** */
185
186 char constraint_has_target (bConstraint *con) 
187 {
188         switch (con->type) {
189         case CONSTRAINT_TYPE_PYTHON:
190                 {
191                         bPythonConstraint *data = con->data;
192                         if (data->tar)
193                                 return 1;
194                 }
195                 break;
196         case CONSTRAINT_TYPE_TRACKTO:
197                 {
198                         bTrackToConstraint *data = con->data;
199                         if (data->tar)
200                                 return 1;
201                 }
202                 break;
203         case CONSTRAINT_TYPE_KINEMATIC:
204                 {
205                         bKinematicConstraint *data = con->data;
206                         if (data->tar)
207                                 return 1;
208                 }
209                 break;
210         case CONSTRAINT_TYPE_FOLLOWPATH:
211                 {
212                         bFollowPathConstraint *data = con->data;
213                         if (data->tar)
214                                 return 1;
215                 }
216                 break;
217         case CONSTRAINT_TYPE_ROTLIKE:
218                 {
219                         bRotateLikeConstraint *data = con->data;
220                         if (data->tar)
221                                 return 1;
222                 }
223                 break;
224         case CONSTRAINT_TYPE_LOCLIKE:
225                 {
226                         bLocateLikeConstraint *data = con->data;
227                         if (data->tar)
228                                 return 1;
229                 }
230                 break;
231         case CONSTRAINT_TYPE_SIZELIKE:
232                 {
233                         bSizeLikeConstraint *data = con->data;
234                         if (data->tar)
235                                 return 1;
236                 }
237                 break;
238         case CONSTRAINT_TYPE_MINMAX:
239                 {
240                         bMinMaxConstraint *data = con->data;
241                         if (data->tar)
242                                 return 1;
243                 }
244                 break;
245         case CONSTRAINT_TYPE_ACTION:
246                 {
247                         bActionConstraint *data = con->data;
248                         if (data->tar)
249                                 return 1;
250                 }
251                 break;
252         case CONSTRAINT_TYPE_LOCKTRACK:
253                 {
254                         bLockTrackConstraint *data = con->data;
255                         if (data->tar)
256                                 return 1;
257                 }
258         case CONSTRAINT_TYPE_STRETCHTO:
259                 {
260                         bStretchToConstraint *data = con->data;
261                         if (data->tar)
262                                 return 1;
263                 }
264                 break;
265         case CONSTRAINT_TYPE_RIGIDBODYJOINT:
266                 {
267                         bRigidBodyJointConstraint *data = con->data;
268                         if (data->tar)
269                                 return 1;
270                 }
271                 break;
272         case CONSTRAINT_TYPE_CLAMPTO:
273                 {
274                         bClampToConstraint *data = con->data;
275                         if (data->tar)
276                                 return 1;
277                 }
278                         break;
279         }
280         // Unknown types or CONSTRAINT_TYPE_NULL or no target
281         return 0;
282 }
283
284 Object *get_constraint_target(bConstraint *con, char **subtarget)
285 {
286         /* If the target for this constraint is target, return a pointer 
287           * to the name for this constraints subtarget ... NULL otherwise
288           */
289         switch (con->type) {
290         case CONSTRAINT_TYPE_PYTHON:
291                 {
292                         bPythonConstraint *data=con->data;
293                         *subtarget = data->subtarget;
294                         return data->tar;
295                 }
296                 break;
297         case CONSTRAINT_TYPE_ACTION:
298                 {
299                         bActionConstraint *data = con->data;
300                         *subtarget= data->subtarget;
301                         return data->tar;
302                 }
303                 break;
304         case CONSTRAINT_TYPE_LOCLIKE:
305                 {
306                         bLocateLikeConstraint *data = con->data;
307                         *subtarget= data->subtarget;
308                         return data->tar;
309                 }
310                 break;
311         case CONSTRAINT_TYPE_ROTLIKE:
312                 {
313                         bRotateLikeConstraint *data = con->data;
314                         *subtarget= data->subtarget;
315                         return data->tar;
316                 }
317                 break;
318         case CONSTRAINT_TYPE_SIZELIKE:
319                 {
320                         bSizeLikeConstraint *data = con->data;
321                         *subtarget= data->subtarget;
322                         return data->tar;
323                 }
324                 break;
325         case CONSTRAINT_TYPE_KINEMATIC:
326                 {
327                         bKinematicConstraint *data = con->data;
328                         *subtarget= data->subtarget;
329                         return data->tar;
330                 }
331                 break;
332         case CONSTRAINT_TYPE_TRACKTO:
333                 {
334                         bTrackToConstraint *data = con->data;
335                         *subtarget= data->subtarget;
336                         return data->tar;
337                 }
338                 break;
339         case CONSTRAINT_TYPE_MINMAX:
340                 {
341                         bMinMaxConstraint *data = con->data;
342                         *subtarget= data->subtarget;
343                         return data->tar;
344                 }
345                 break;
346         case CONSTRAINT_TYPE_LOCKTRACK:
347                 {
348                         bLockTrackConstraint *data = con->data;
349                         *subtarget= data->subtarget;
350                         return data->tar;
351                 }
352                 break;
353         case CONSTRAINT_TYPE_FOLLOWPATH: 
354                 {
355                         bFollowPathConstraint *data = con->data;
356                         *subtarget= NULL;
357                         return data->tar;
358                 }
359                 break;
360         case CONSTRAINT_TYPE_STRETCHTO:
361                 {
362                         bStretchToConstraint *data = con->data;
363                         *subtarget= data->subtarget;
364                         return (data->tar);
365                 }
366                 break;
367         case CONSTRAINT_TYPE_RIGIDBODYJOINT: 
368                 {
369                         bRigidBodyJointConstraint *data = con->data;
370                         *subtarget= NULL;
371                         return data->tar;
372                 }
373                 break;
374         case CONSTRAINT_TYPE_CLAMPTO:
375                 {
376                         bClampToConstraint *data = con->data;
377                         *subtarget= NULL;
378                         return data->tar;
379                 }
380                 break;
381         default:
382                 *subtarget= NULL;
383                 break;
384         }
385         
386         return NULL;  
387 }
388
389 void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
390 {
391         /* Set the target for this constraint  */
392         switch (con->type) {
393                 
394                 case CONSTRAINT_TYPE_PYTHON:
395                 {
396                         bPythonConstraint *data = con->data;
397                         data->tar= ob;
398                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
399                 }
400                         break;          
401                 case CONSTRAINT_TYPE_ACTION:
402                 {
403                         bActionConstraint *data = con->data;
404                         data->tar= ob;
405                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
406                 }
407                         break;
408                 case CONSTRAINT_TYPE_LOCLIKE:
409                 {
410                         bLocateLikeConstraint *data = con->data;
411                         data->tar= ob;
412                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
413                 }
414                         break;
415                 case CONSTRAINT_TYPE_ROTLIKE:
416                 {
417                         bRotateLikeConstraint *data = con->data;
418                         data->tar= ob;
419                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
420                 }
421                         break;
422                 case CONSTRAINT_TYPE_SIZELIKE:
423                 {
424                         bSizeLikeConstraint *data = con->data;
425                         data->tar= ob;
426                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
427                 }
428                         break;
429                 case CONSTRAINT_TYPE_KINEMATIC:
430                 {
431                         bKinematicConstraint *data = con->data;
432                         data->tar= ob;
433                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
434                 }
435                         break;
436                 case CONSTRAINT_TYPE_TRACKTO:
437                 {
438                         bTrackToConstraint *data = con->data;
439                         data->tar= ob;
440                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
441                 }
442                         break;
443                 case CONSTRAINT_TYPE_LOCKTRACK:
444                 {
445                         bLockTrackConstraint *data = con->data;
446                         data->tar= ob;
447                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
448                 }
449                         break;
450                 case CONSTRAINT_TYPE_FOLLOWPATH: 
451                 {
452                         bFollowPathConstraint *data = con->data;
453                         data->tar= ob;
454                 }
455                         break;
456                 case CONSTRAINT_TYPE_STRETCHTO:
457                 {
458                         bStretchToConstraint *data = con->data;
459                         data->tar= ob;
460                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
461                 }
462                         break;
463                 case CONSTRAINT_TYPE_RIGIDBODYJOINT: 
464                 {
465                         bRigidBodyJointConstraint *data = con->data;
466                         data->tar= ob;
467                 }
468                         break;
469                 case CONSTRAINT_TYPE_MINMAX:
470                 {
471                         bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
472                         data->tar= ob;
473                         if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
474                 }
475                         break;
476                 case CONSTRAINT_TYPE_CLAMPTO: 
477                 {
478                         bClampToConstraint *data = con->data;
479                         data->tar= ob;
480                 }
481                         break;
482         }
483 }
484
485 void unique_constraint_name (bConstraint *con, ListBase *list)
486 {
487         char            tempname[64];
488         int                     number;
489         char            *dot;
490         int exists = 0;
491         bConstraint *curcon;
492         
493         /* See if we are given an empty string */
494         if (con->name[0] == '\0') {
495                 /* give it default name first */
496                 strcpy (con->name, "Const");
497         }
498         
499         /* See if we even need to do this */
500         for (curcon = list->first; curcon; curcon=curcon->next) {
501                 if (curcon!=con){
502                         if (!strcmp(curcon->name, con->name)) {
503                                 exists = 1;
504                                 break;
505                         }
506                 }
507         }
508         
509         if (!exists)
510                 return;
511
512         /*      Strip off the suffix */
513         dot=strchr(con->name, '.');
514         if (dot)
515                 *dot=0;
516         
517         for (number = 1; number <=999; number++) {
518                 sprintf (tempname, "%s.%03d", con->name, number);
519                 
520                 exists = 0;
521                 for (curcon=list->first; curcon; curcon=curcon->next) {
522                         if (con!=curcon) {
523                                 if (!strcmp (curcon->name, tempname)) {
524                                         exists = 1;
525                                         break;
526                                 }
527                         }
528                 }
529                 if (!exists) {
530                         strcpy (con->name, tempname);
531                         return;
532                 }
533         }
534 }
535
536 void *new_constraint_data (short type)
537 {
538         void *result;
539         
540         switch (type) {
541         case CONSTRAINT_TYPE_PYTHON:
542                 {
543                         bPythonConstraint *data;
544                         data = MEM_callocN(sizeof(bPythonConstraint), "pythonConstraint");
545                         
546                         /* everything should be set correctly by calloc, except for the prop->type constant.*/
547                         data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
548                         data->prop->type = IDP_GROUP;
549                         
550                         result = data;
551                 }
552                 break;          
553         case CONSTRAINT_TYPE_KINEMATIC:
554                 {
555                         bKinematicConstraint *data;
556                         data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
557
558                         data->weight= (float)1.0;
559                         data->orientweight= (float)1.0;
560                         data->iterations = 500;
561                         data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
562                         
563                         result = data;
564                 }
565                 break;
566         case CONSTRAINT_TYPE_TRACKTO:
567                 {
568                         bTrackToConstraint *data;
569                         data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
570                         
571                         data->reserved1 = TRACK_Y;
572                         data->reserved2 = UP_Z;
573                         
574                         result = data;
575                 }
576                 break;
577         case CONSTRAINT_TYPE_MINMAX:
578                 {
579                         bMinMaxConstraint *data;
580                         data = MEM_callocN(sizeof(bMinMaxConstraint), "minmaxConstraint");
581                         
582                         data->minmaxflag = TRACK_Z;
583                         data->offset = 0.0f;
584                         data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
585                         data->flag = 0;
586                         
587                         result = data;
588                 }
589                 break;
590         case CONSTRAINT_TYPE_LOCLIKE:
591                 {
592                         bLocateLikeConstraint *data;
593                         data = MEM_callocN(sizeof(bLocateLikeConstraint), "loclikeConstraint");
594                         data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
595                         result = data;
596                 }
597                 break;
598         case CONSTRAINT_TYPE_ROTLIKE:
599                 {
600                         bRotateLikeConstraint *data;
601                         data = MEM_callocN(sizeof(bRotateLikeConstraint), "rotlikeConstraint");
602                         data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
603                         result = data;
604                 }
605                 break;
606         case CONSTRAINT_TYPE_SIZELIKE:
607                 {
608                         bSizeLikeConstraint *data;
609                         data = MEM_callocN(sizeof(bLocateLikeConstraint), "sizelikeConstraint");
610                         data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
611                         result = data;
612                 }
613                 break;
614         case CONSTRAINT_TYPE_ACTION:
615                 {
616                         bActionConstraint *data;
617                         data = MEM_callocN(sizeof(bActionConstraint), "actionConstraint");
618                         data->local= 1;
619                         
620                         result = data;
621                 }
622                 break;
623         case CONSTRAINT_TYPE_LOCKTRACK:
624                 {
625                         bLockTrackConstraint *data;
626                         data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
627
628                         data->trackflag = TRACK_Y;
629                         data->lockflag = LOCK_Z;
630
631                         result = data;
632                 }
633                 break;
634         case CONSTRAINT_TYPE_FOLLOWPATH:
635                 {
636                         bFollowPathConstraint *data;
637                         data = MEM_callocN(sizeof(bFollowPathConstraint), "followpathConstraint");
638
639                         data->trackflag = TRACK_Y;
640                         data->upflag = UP_Z;
641                         data->offset = 0;
642                         data->followflag = 0;
643
644                         result = data;
645                 }
646                 break;
647         case CONSTRAINT_TYPE_STRETCHTO:
648                 {
649                         bStretchToConstraint *data;
650                         data = MEM_callocN(sizeof(bStretchToConstraint), "StretchToConstraint");
651
652                         data->volmode = 0;
653                         data->plane = 0;
654                         data->orglength = 0.0; 
655                         data->bulge = 1.0;
656                         result = data;
657                 }
658                 break; 
659         case CONSTRAINT_TYPE_LOCLIMIT:
660                 {
661                         bLocLimitConstraint *data;
662                         data = MEM_callocN(sizeof(bLocLimitConstraint), "LocLimitConstraint");
663                         result = data;
664                 }
665                 break;
666         case CONSTRAINT_TYPE_ROTLIMIT:
667                 {
668                         bRotLimitConstraint *data;
669                         data = MEM_callocN(sizeof(bRotLimitConstraint), "RotLimitConstraint");
670                         result = data;
671                 }
672                 break;
673         case CONSTRAINT_TYPE_SIZELIMIT:
674                 {
675                         bSizeLimitConstraint *data;
676                         data = MEM_callocN(sizeof(bSizeLimitConstraint), "SizeLimitConstraint");
677                         result = data;
678                 }
679                 break;
680     case CONSTRAINT_TYPE_RIGIDBODYJOINT:
681                 {
682                         bRigidBodyJointConstraint *data;
683                         int i;
684                         Base *base_iter;
685
686                         data = MEM_callocN(sizeof(bRigidBodyJointConstraint), "RigidBodyToConstraint");
687                         base_iter = G.scene->base.first;
688             while( base_iter && !data->tar ) {
689                 if( ( ( base_iter->flag & SELECT ) &&
690 //                    ( base_iter->lay & G.vd->lay ) ) &&
691                     ( base_iter != G.scene->basact ) )
692                     )
693                         data->tar=base_iter->object;
694                 base_iter = base_iter->next;
695             }
696             data->type=1;
697             data->pivX=0.0;
698             data->pivY=0.0;
699             data->pivZ=0.0;
700             data->axX=0.0;
701             data->axY=0.0;
702             data->axZ=0.0;
703                         for (i=0;i<6;i++)
704                         {
705                                 data->minLimit[i]=0.0;
706                                 data->maxLimit[i]=0.0;
707                         }
708             data->extraFz=0.0;
709                         result = data;
710                 }
711                 break;
712         case CONSTRAINT_TYPE_CLAMPTO:
713                 {
714                         bClampToConstraint *data;
715                         data = MEM_callocN(sizeof(bClampToConstraint), "ClampToConstraint");
716                         result = data;
717                 }
718                 break;
719   
720         default:
721                 result = NULL;
722                 break;
723         }
724
725         return result;
726 }
727
728 bConstraintChannel *get_constraint_channel (ListBase *list, const char *name)
729 {
730         bConstraintChannel *chan;
731
732         for (chan = list->first; chan; chan=chan->next) {
733                 if (!strcmp(name, chan->name)) {
734                         return chan;
735                 }
736         }
737         return NULL;
738 }
739
740 /* finds or creates new constraint channel */
741 bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name)
742 {
743         bConstraintChannel *chan;
744         
745         chan= get_constraint_channel (list, name);
746         if(chan==NULL) {
747                 chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint chan");
748                 BLI_addtail(list, chan);
749                 strcpy(chan->name, name);
750         }
751         
752         return chan;
753 }
754
755
756 /* ***************** Evaluating ********************* */
757
758 /* does ipos only */
759 void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
760 {
761         bConstraint *con;
762         bConstraintChannel *chan;
763         IpoCurve *icu=NULL;
764         
765         for (con=conbase->first; con; con=con->next) {
766                 chan = get_constraint_channel(chanbase, con->name);
767                 if (chan && chan->ipo){
768                         calc_ipo(chan->ipo, ctime);
769                         for (icu=chan->ipo->curve.first; icu; icu=icu->next){
770                                 switch (icu->adrcode){
771                                 case CO_ENFORCE:
772                                         con->enforce = icu->curval;
773                                         if (con->enforce<0.0f) con->enforce= 0.0f;
774                                         else if (con->enforce>1.0f) con->enforce= 1.0f;
775                                         break;
776                                 }
777                         }
778                 }
779         }
780 }
781
782 static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3])
783 {
784
785         /*      Case OBJECT */
786         if (!strlen(substring)) {
787                 Mat4CpyMat4 (mat, ob->obmat);
788                 VECCOPY (size, ob->size);  // whats this for, hack! (ton)
789         }
790         /*      Case BONE */
791         else {
792                 bPoseChannel *pchan;
793                 float   bsize[3]={1, 1, 1};
794
795                 pchan = get_pose_channel(ob->pose, substring);
796                 if (pchan){
797                         /**
798                          *      Multiply the objectspace bonematrix by the skeletons's global
799                          *      transform to obtain the worldspace transformation of the target
800                          */
801                         Mat4MulMat4 (mat, pchan->pose_mat, ob->obmat);
802                 } 
803                 else
804                         Mat4CpyMat4 (mat, ob->obmat);
805
806                 VECCOPY(size, bsize);   // whats this for, hack! (ton)
807         }
808 }
809
810
811 /* stupid little cross product function, 0:x, 1:y, 2:z axes */
812 static int basis_cross(int n, int m)
813 {
814         if(n-m == 1) return 1;
815         if(n-m == -1) return -1;
816         if(n-m == 2) return -1;
817         if(n-m == -2) return 1;
818         else return 0;
819 }
820
821 static void vectomat(float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
822 {
823         float n[3];
824         float u[3]; /* vector specifying the up axis */
825         float proj[3];
826         float right[3];
827         float neg = -1;
828         int right_index;
829
830         VecCopyf(n, vec);
831         if(Normalize(n) == 0.0) { 
832                 n[0] = 0.0;
833                 n[1] = 0.0;
834                 n[2] = 1.0;
835         }
836         if(axis > 2) axis -= 3;
837         else VecMulf(n,-1);
838
839         /* n specifies the transformation of the track axis */
840
841         if(flags & TARGET_Z_UP) { 
842                 /* target Z axis is the global up axis */
843                 u[0] = target_up[0];
844                 u[1] = target_up[1];
845                 u[2] = target_up[2];
846         }
847         else { 
848                 /* world Z axis is the global up axis */
849                 u[0] = 0;
850                 u[1] = 0;
851                 u[2] = 1;
852         }
853
854         /* project the up vector onto the plane specified by n */
855         Projf(proj, u, n); /* first u onto n... */
856         VecSubf(proj, u, proj); /* then onto the plane */
857         /* proj specifies the transformation of the up axis */
858
859         if(Normalize(proj) == 0.0) { /* degenerate projection */
860                 proj[0] = 0.0;
861                 proj[1] = 1.0;
862                 proj[2] = 0.0;
863         }
864
865         /* Normalized cross product of n and proj specifies transformation of the right axis */
866         Crossf(right, proj, n);
867         Normalize(right);
868
869         if(axis != upflag) {
870                 right_index = 3 - axis - upflag;
871                 neg = (float) basis_cross(axis, upflag);
872
873                 /* account for up direction, track direction */
874                 m[right_index][0] = neg * right[0];
875                 m[right_index][1] = neg * right[1];
876                 m[right_index][2] = neg * right[2];
877
878                 m[upflag][0] = proj[0];
879                 m[upflag][1] = proj[1];
880                 m[upflag][2] = proj[2];
881
882                 m[axis][0] = n[0];
883                 m[axis][1] = n[1];
884                 m[axis][2] = n[2];
885         }
886
887         else {
888                 m[0][0]= m[1][1]= m[2][2]= 1.0;
889                 m[0][1]= m[0][2]= m[0][3]= 0.0;
890                 m[1][0]= m[1][2]= m[1][3]= 0.0;
891                 m[2][0]= m[2][1]= m[2][3]= 0.0;
892         }
893 }
894
895
896 /* called during solve_constraints */
897 /* also for make_parent, to find correct inverse of "follow path" */
898 /* warning, ownerdata is void... is not Bone anymore, but PoseChannel or Object */
899 /* ctime is global time, uncorrected for local bsystem_time */
900 short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
901 {
902         short valid=0;
903
904         switch (con->type) {
905         case CONSTRAINT_TYPE_NULL:
906                 {
907                         Mat4One(mat);
908                 }
909                 break;
910         case CONSTRAINT_TYPE_ACTION:
911                 {
912                         if (ownertype == TARGET_BONE) {
913                                 extern void chan_calc_mat(bPoseChannel *chan);
914                                 bActionConstraint *data = (bActionConstraint*)con->data;
915                                 bPose *pose;
916                                 bPoseChannel *pchan, *tchan;
917                                 float tempmat3[3][3];
918                                 float eul[3];
919                                 float s,t;
920                                 
921                                 Mat4One(mat);   // return mat
922                                 
923                                 if (data->tar==NULL) return 0;
924                                 
925                                 /* need proper check for bone... */
926                                 if (data->subtarget[0]) {
927                                         pchan = get_pose_channel(data->tar->pose, data->subtarget);
928                                         if (pchan) {
929                                                 float arm_mat[3][3], pose_mat[3][3];            /* arm mat should be bone mat! bug... */
930                                                 
931                                                 Mat3CpyMat4(arm_mat, pchan->bone->arm_mat);
932                                                 Mat3CpyMat4(pose_mat, pchan->pose_mat);
933                                                 
934                                                 /* new; true local rotation constraint */
935                                                 if(data->local) {
936                                                         float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3];
937                                                         /* we need the local rotation = current rotation - (parent rotation + restpos) */
938                                                         
939                                                         if (pchan->parent) {
940                                                                 Mat3CpyMat4(par_mat, pchan->parent->pose_mat);
941                                                                 Mat3MulMat3(diff_mat, par_mat, arm_mat);
942                                                                 
943                                                                 Mat3Inv(ipar_mat, diff_mat);
944                                                         }
945                                                         else {
946                                                                 Mat3Inv(ipar_mat, arm_mat);
947                                                         }
948                                                         
949                                                         Mat3MulMat3(tempmat3, ipar_mat, pose_mat);
950                                                 }
951                                                 else {  /* we use the deform mat, for backwards compatibility */
952                                                         float imat[3][3];
953                                                         
954                                                         Mat3Inv(imat, arm_mat);
955                                                         Mat3MulMat3(tempmat3, pose_mat, imat);
956                                                 }
957                                         }
958                                         else Mat3One(tempmat3);
959                                 }
960                                 else {
961                                         float ans[4][4];
962                                         
963                                         constraint_target_to_mat4(data->tar, data->subtarget, ans, size);
964                                         /* extract rotation, is in global world coordinates */
965                                         Mat3CpyMat4(tempmat3, ans);
966                                 }
967                                 
968                                 Mat3ToEul(tempmat3, eul);
969                                 eul[0] *= (float)(180.0/M_PI);
970                                 eul[1] *= (float)(180.0/M_PI);
971                                 eul[2] *= (float)(180.0/M_PI);
972                                 
973                                 /* Target defines the animation */
974                                 s = (eul[data->type]-data->min)/(data->max-data->min);
975                                 if (s<0)
976                                         s=0;
977                                 if (s>1)
978                                         s=1;
979
980                                 t = ( s * (data->end-data->start)) + data->start;
981
982                                 /* Get the appropriate information from the action, we make temp pose */
983                                 pose = MEM_callocN(sizeof(bPose), "pose");
984                                 
985                                 pchan = ownerdata;
986                                 tchan= verify_pose_channel(pose, pchan->name);
987                                 extract_pose_from_action (pose, data->act, t);
988                                 
989                                 chan_calc_mat(tchan);
990                                 
991                                 Mat4CpyMat4(mat, tchan->chan_mat);
992
993                                 /* Clean up */
994                                 free_pose_channels(pose);
995                                 MEM_freeN(pose);
996                         }
997                         
998                 }
999                 break;
1000         case CONSTRAINT_TYPE_LOCLIKE:
1001                 {
1002                         bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
1003                         Object *ob= data->tar;
1004                         
1005                         if (data->tar) {
1006                                 if (strlen(data->subtarget)) {
1007                                         bPoseChannel *pchan;
1008                                         float tmat[4][4];
1009                                         float bsize[3]={1, 1, 1};
1010                                         
1011                                         pchan = get_pose_channel(ob->pose, data->subtarget);
1012                                         if (pchan) {
1013                                                 Mat4CpyMat4(tmat, pchan->pose_mat);
1014                                                 
1015                                                 if (data->flag & LOCLIKE_TIP) 
1016                                                         VECCOPY(tmat[3], pchan->pose_tail);
1017                                                         
1018                                                 Mat4MulMat4 (mat, tmat, ob->obmat);
1019                                         }
1020                                         else 
1021                                                 Mat4CpyMat4 (mat, ob->obmat);
1022                                         
1023                                         VECCOPY(size, bsize); // what's this hack for? 
1024                                 }
1025                                 else {
1026                                         Mat4CpyMat4 (mat, ob->obmat);
1027                                         VECCOPY(size, data->tar->size); // what's this hack for? 
1028                                 }
1029                                 valid=1;
1030                         }
1031                         else
1032                                 Mat4One (mat);
1033                 } 
1034                 break;
1035         case CONSTRAINT_TYPE_MINMAX:
1036                 {
1037                         bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
1038
1039                         if (data->tar) {
1040                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1041                                 valid=1;
1042                         }
1043                         else
1044                                 Mat4One (mat);
1045                 } 
1046                 break;
1047         case CONSTRAINT_TYPE_ROTLIKE:
1048                 {
1049                         bRotateLikeConstraint *data;
1050                         data = (bRotateLikeConstraint*)con->data;
1051
1052                         if (data->tar) {
1053                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1054                                 valid=1;
1055                         }
1056                         else
1057                                 Mat4One (mat);
1058                 } 
1059                 break;
1060         case CONSTRAINT_TYPE_SIZELIKE:
1061                 {
1062                         bSizeLikeConstraint *data;
1063                         data = (bSizeLikeConstraint*)con->data;
1064
1065                         if (data->tar) {
1066                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1067                                 valid=1;
1068                         }
1069                         else
1070                                 Mat4One (mat);
1071                 } 
1072                 break;
1073         case CONSTRAINT_TYPE_TRACKTO:
1074                 {
1075                         bTrackToConstraint *data;
1076                         data = (bTrackToConstraint*)con->data;
1077
1078                         if (data->tar) {
1079                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1080                                 valid=1;
1081                         }
1082                         else
1083                                 Mat4One (mat);
1084                 }
1085                 break;
1086         case CONSTRAINT_TYPE_KINEMATIC:
1087                 {
1088                         bKinematicConstraint *data;
1089                         data = (bKinematicConstraint*)con->data;
1090
1091                         if (data->tar) {
1092                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1093                                 valid=1;
1094                         }
1095                         else if (data->flag & CONSTRAINT_IK_AUTO) {
1096                                 Object *ob= ownerdata;
1097                                 
1098                                 if (ob==NULL)
1099                                         Mat4One(mat);
1100                                 else {
1101                                         float vec[3];
1102                                         /* move grabtarget into world space */
1103                                         VECCOPY(vec, data->grabtarget);
1104                                         Mat4MulVecfl(ob->obmat, vec);
1105                                         Mat4CpyMat4(mat, ob->obmat);
1106                                         VECCOPY(mat[3], vec);
1107                                 }
1108                         }
1109                         else
1110                                 Mat4One (mat);
1111                 } 
1112                 break;
1113         case CONSTRAINT_TYPE_LOCKTRACK:
1114                 {
1115                         bLockTrackConstraint *data;
1116                         data = (bLockTrackConstraint*)con->data;
1117
1118                         if (data->tar) {
1119                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1120                                 valid=1;
1121                         }
1122                         else
1123                                 Mat4One (mat);
1124                 } 
1125                 break;
1126         case CONSTRAINT_TYPE_FOLLOWPATH:
1127                 {
1128                         bFollowPathConstraint *data;
1129                         data = (bFollowPathConstraint*)con->data;
1130
1131                         if (data->tar) {
1132                                 Curve *cu;
1133                                 float q[4], vec[4], dir[3], *quat, x1, totmat[4][4];
1134                                 float curvetime;
1135
1136                                 Mat4One (totmat);
1137                                 Mat4One (mat);
1138
1139                                 cu= data->tar->data;
1140
1141                                 /* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
1142                                         currently for paths to work it needs to go through the bevlist/displist system (ton) */
1143                                 
1144                                 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1145                                         makeDispListCurveTypes(data->tar, 0);
1146                                 if (cu->path && cu->path->data) {
1147                                         
1148                                         curvetime= bsystem_time(data->tar, data->tar->parent, (float)ctime, 0.0) - data->offset;
1149
1150                                         if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
1151                                                 curvetime /= cu->pathlen;
1152                                                 CLAMP(curvetime, 0.0, 1.0);
1153                                         }
1154                                         
1155                                         if (where_on_path(data->tar, curvetime, vec, dir) ) {
1156                                                 if (data->followflag) {
1157                                                         quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
1158                                                         
1159                                                         Normalize(dir);
1160                                                         q[0]= (float)cos(0.5*vec[3]);
1161                                                         x1= (float)sin(0.5*vec[3]);
1162                                                         q[1]= -x1*dir[0];
1163                                                         q[2]= -x1*dir[1];
1164                                                         q[3]= -x1*dir[2];
1165                                                         QuatMul(quat, q, quat);
1166                                                         
1167                                                         QuatToMat4(quat, totmat);
1168                                                 }
1169                                                 VECCOPY(totmat[3], vec);
1170
1171                                                 Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
1172                                         }
1173                                 }
1174                                 valid=1;
1175                         }
1176                         else
1177                                 Mat4One (mat);
1178                 }
1179                 break;
1180         case CONSTRAINT_TYPE_STRETCHTO:
1181                 {
1182                         bStretchToConstraint *data;
1183                         data = (bStretchToConstraint*)con->data;
1184
1185                         if (data->tar) {
1186                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1187                                 valid = 1;
1188                         }
1189                         else
1190                                 Mat4One (mat);
1191                 }
1192                 break;
1193         case CONSTRAINT_TYPE_PYTHON:
1194                 {
1195                         bPythonConstraint *data;
1196                         data = (bPythonConstraint*)con->data;
1197                         
1198                         /* special exception for curves - depsgraph issues */
1199                         if (data->tar && data->tar->type == OB_CURVE) {
1200                                 Curve *cu= data->tar->data;
1201                                 
1202                                 /* this check is to make sure curve objects get updated on file load correctly.*/
1203                                 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1204                                         makeDispListCurveTypes(data->tar, 0);                           
1205                         }
1206                         
1207                         /* if the script doesn't set the target matrix for any reason, fall back to standard methods */
1208                         if (BPY_pyconstraint_targets(data, mat) < 1) {
1209                                 if (data->tar) {
1210                                         constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
1211                                         valid = 1;
1212                                 }
1213                                 else
1214                                         Mat4One (mat);
1215                         }
1216                 }
1217                 break;
1218         case CONSTRAINT_TYPE_CLAMPTO:
1219                 {
1220                         bClampToConstraint *data;
1221                         data = (bClampToConstraint*)con->data;
1222
1223                         if (data->tar) {
1224                                 Curve *cu= data->tar->data;
1225                                 
1226                                 /* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
1227                                         currently for paths to work it needs to go through the bevlist/displist system (ton) */
1228                                 
1229                                 if(cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1230                                         makeDispListCurveTypes(data->tar, 0);
1231                         }
1232                         
1233                         Mat4One (mat);
1234                 }
1235                 break;
1236
1237         default:
1238                 Mat4One(mat);
1239                 break;
1240         }
1241
1242         return valid;
1243 }
1244
1245 /* only called during solve_constraints */
1246 /* bone constraints create a fake object to work on, then ob is a workob */
1247 /* if ownerdata is set, it's the posechannel */
1248 void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
1249 {
1250         float   M_oldmat[4][4];
1251         float   M_identity[4][4];
1252         
1253         if (!constraint || !ob)
1254                 return;
1255
1256         Mat4One (M_identity);
1257         
1258         switch (constraint->type) {
1259         case CONSTRAINT_TYPE_NULL:
1260         case CONSTRAINT_TYPE_KINEMATIC: /* removed */
1261                 break;
1262         case CONSTRAINT_TYPE_PYTHON:
1263                 {
1264                         bPythonConstraint *data;
1265                         
1266                         data= constraint->data;
1267                         BPY_pyconstraint_eval(data, ob->obmat, ownertype, ownerdata, targetmat);
1268                 } 
1269                 break;
1270         case CONSTRAINT_TYPE_ACTION:
1271                 {
1272                         bActionConstraint *data;
1273                         float temp[4][4];
1274                         
1275                         data = constraint->data;
1276                         Mat4CpyMat4 (temp, ob->obmat);
1277                         
1278                         Mat4MulMat4(ob->obmat, targetmat, temp);
1279                 }
1280                 break;
1281         case CONSTRAINT_TYPE_LOCLIKE:
1282                 {
1283                         bLocateLikeConstraint *data;
1284                         float offset[3] = {0.0f, 0.0f, 0.0f};
1285
1286                         data = constraint->data;
1287                         
1288                         if (data->flag & LOCLIKE_OFFSET)
1289                                 VECCOPY(offset, ob->obmat[3]);
1290                         
1291                         if (data->flag & LOCLIKE_X) {
1292                                 ob->obmat[3][0] = targetmat[3][0];
1293                                 
1294                                 if(data->flag & LOCLIKE_X_INVERT) ob->obmat[3][0] *= -1;
1295                                 ob->obmat[3][0] += offset[0];
1296                         }
1297                         if (data->flag & LOCLIKE_Y) {
1298                                 ob->obmat[3][1] = targetmat[3][1];
1299                                 
1300                                 if(data->flag & LOCLIKE_Y_INVERT) ob->obmat[3][1] *= -1;
1301                                 ob->obmat[3][1] += offset[1];
1302                         }
1303                         if (data->flag & LOCLIKE_Z) {
1304                                 ob->obmat[3][2] = targetmat[3][2];
1305                                 
1306                                 if(data->flag & LOCLIKE_Z_INVERT) ob->obmat[3][2] *= -1;
1307                                 ob->obmat[3][2] += offset[2];
1308                         }
1309                 }
1310                 break;
1311         case CONSTRAINT_TYPE_ROTLIKE:
1312                 {
1313                         bRotateLikeConstraint *data;
1314                         float   loc[3];
1315                         float   eul[3], obeul[3];
1316                         float   size[3];
1317                         
1318                         data = constraint->data;
1319                         
1320                         VECCOPY(loc, ob->obmat[3]);
1321                         Mat4ToSize(ob->obmat, size);
1322                         
1323                         Mat4ToEul(targetmat, eul);
1324                         Mat4ToEul(ob->obmat, obeul);
1325                                 
1326                         if(data->flag != (ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z)) {
1327                                 if(!(data->flag & ROTLIKE_X)) {
1328                                         eul[0]= obeul[0];
1329                                 }
1330                                 if(!(data->flag & ROTLIKE_Y)) {
1331                                         eul[1]= obeul[1];
1332                                 }
1333                                 if(!(data->flag & ROTLIKE_Z)) {
1334                                         eul[2]= obeul[2];
1335                                 }
1336                                 compatible_eul(eul, obeul);
1337                         }
1338                         
1339                         if((data->flag & ROTLIKE_X) && (data->flag & ROTLIKE_X_INVERT))
1340                                 eul[0]*= -1;
1341                         if((data->flag & ROTLIKE_Y) && (data->flag & ROTLIKE_Y_INVERT))
1342                                 eul[1]*= -1;
1343                         if((data->flag & ROTLIKE_Z) && (data->flag & ROTLIKE_Z_INVERT))
1344                                 eul[2]*= -1;
1345                         
1346                         LocEulSizeToMat4(ob->obmat, loc, eul, size);
1347                 }
1348                 break;
1349         case CONSTRAINT_TYPE_SIZELIKE:
1350                 {
1351                         bSizeLikeConstraint *data;
1352                         float obsize[3], size[3];
1353                         
1354                         data = constraint->data;
1355  
1356                         Mat4ToSize(targetmat, size);
1357                         Mat4ToSize(ob->obmat, obsize);
1358                         
1359                         if (data->flag & SIZELIKE_X && obsize[0] != 0)
1360                                 VecMulf(ob->obmat[0], size[0] / obsize[0]);
1361                         if (data->flag & SIZELIKE_Y && obsize[1] != 0)
1362                                 VecMulf(ob->obmat[1], size[1] / obsize[1]);
1363                         if (data->flag & SIZELIKE_Z && obsize[2] != 0)
1364                                 VecMulf(ob->obmat[2], size[2] / obsize[2]);
1365                 }
1366                 break;
1367         case CONSTRAINT_TYPE_MINMAX:
1368                 {
1369                         bMinMaxConstraint *data;
1370                         float val1, val2;
1371                         int index;
1372                         float obmat[4][4],imat[4][4],tarmat[4][4],tmat[4][4];
1373
1374                         data = constraint->data;
1375                         
1376                         Mat4CpyMat4(obmat,ob->obmat);
1377                         Mat4CpyMat4(tarmat,targetmat);
1378                         
1379                         if (data->flag & MINMAX_USEROT) {
1380                                 /* take rotation of target into account by doing the transaction in target's localspace */
1381                                 Mat4Invert(imat,tarmat);
1382                                 Mat4MulMat4(tmat,obmat,imat);
1383                                 Mat4CpyMat4(obmat,tmat);
1384                                 Mat4One(tarmat);
1385                         }
1386
1387                         switch (data->minmaxflag) {
1388                         case TRACK_Z:
1389                                 val1 = tarmat[3][2];
1390                                 val2 = obmat[3][2]-data->offset;
1391                                 index = 2;
1392                                 break;
1393                         case TRACK_Y:
1394                                 val1 = tarmat[3][1];
1395                                 val2 = obmat[3][1]-data->offset;
1396                                 index = 1;
1397                                 break;
1398                         case TRACK_X:
1399                                 val1 = tarmat[3][0];
1400                                 val2 = obmat[3][0]-data->offset;
1401                                 index = 0;
1402                                 break;
1403                         case TRACK_nZ:
1404                                 val2 = tarmat[3][2];
1405                                 val1 = obmat[3][2]-data->offset;
1406                                 index = 2;
1407                                 break;
1408                         case TRACK_nY:
1409                                 val2 = tarmat[3][1];
1410                                 val1 = obmat[3][1]-data->offset;
1411                                 index = 1;
1412                                 break;
1413                         case TRACK_nX:
1414                                 val2 = tarmat[3][0];
1415                                 val1 = obmat[3][0]-data->offset;
1416                                 index = 0;
1417                                 break;
1418                         default:
1419                                 return;
1420                         }
1421                         
1422                         if (val1 > val2) {
1423                                 obmat[3][index] = tarmat[3][index] + data->offset;
1424                                 if (data->flag & MINMAX_STICKY) {
1425                                         if (data->flag & MINMAX_STUCK) {
1426                                                 VECCOPY(obmat[3], data->cache);
1427                                         } 
1428                                         else {
1429                                                 VECCOPY(data->cache, obmat[3]);
1430                                                 data->flag |= MINMAX_STUCK;
1431                                         }
1432                                 }
1433                                 if (data->flag & MINMAX_USEROT) {
1434                                         /* get out of localspace */
1435                                         Mat4MulMat4(tmat,obmat,targetmat);
1436                                         Mat4CpyMat4(ob->obmat,tmat);
1437                                 } 
1438                                 else {                  
1439                                         VECCOPY(ob->obmat[3],obmat[3]);
1440                                 }
1441                         } 
1442                         else {
1443                                 data->flag &= ~MINMAX_STUCK;
1444                         }
1445                 }
1446                 break;
1447         case CONSTRAINT_TYPE_TRACKTO:
1448                 {
1449                         bTrackToConstraint *data;
1450                         float size[3];
1451                         float vec[3];
1452                         float totmat[3][3];
1453                         float tmat[4][4];
1454
1455                         data = constraint->data;                        
1456                         
1457                         if (data->tar) {
1458                                 /* Get size property, since ob->size is only the object's own relative size, not its global one */
1459                                 Mat4ToSize (ob->obmat, size);
1460                                 
1461                                 Mat4CpyMat4 (M_oldmat, ob->obmat);
1462                                 
1463                                 /* Clear the object's rotation */       
1464                                 ob->obmat[0][0]=size[0];
1465                                 ob->obmat[0][1]=0;
1466                                 ob->obmat[0][2]=0;
1467                                 ob->obmat[1][0]=0;
1468                                 ob->obmat[1][1]=size[1];
1469                                 ob->obmat[1][2]=0;
1470                                 ob->obmat[2][0]=0;
1471                                 ob->obmat[2][1]=0;
1472                                 ob->obmat[2][2]=size[2];
1473                                 
1474                                 VecSubf(vec, ob->obmat[3], targetmat[3]);
1475                                 vectomat(vec, targetmat[2], 
1476                                                 (short)data->reserved1, (short)data->reserved2, 
1477                                                 data->flags, totmat);
1478                                 
1479                                 Mat4CpyMat4(tmat, ob->obmat);
1480                                 
1481                                 Mat4MulMat34(ob->obmat, totmat, tmat);
1482                         }
1483                 }
1484                 break;
1485         case CONSTRAINT_TYPE_LOCKTRACK:
1486                 {
1487                         bLockTrackConstraint *data;
1488                         float vec[3],vec2[3];
1489                         float totmat[3][3];
1490                         float tmpmat[3][3];
1491                         float invmat[3][3];
1492                         float tmat[4][4];
1493                         float mdet;
1494
1495                         data = constraint->data;                        
1496                         
1497                         if (data->tar) {
1498                                 Mat4CpyMat4 (M_oldmat, ob->obmat);
1499                                 
1500                                 /* Vector object -> target */
1501                                 VecSubf(vec, targetmat[3], ob->obmat[3]);
1502                                 switch (data->lockflag){
1503                                 case LOCK_X: /* LOCK X */
1504                                 {
1505                                         switch (data->trackflag) {
1506                                                 case TRACK_Y: /* LOCK X TRACK Y */
1507                                                 {
1508                                                         /* Projection of Vector on the plane */
1509                                                         Projf(vec2, vec, ob->obmat[0]);
1510                                                         VecSubf(totmat[1], vec, vec2);
1511                                                         Normalize(totmat[1]);
1512                                                         
1513                                                         /* the x axis is fixed*/
1514                                                         totmat[0][0] = ob->obmat[0][0];
1515                                                         totmat[0][1] = ob->obmat[0][1];
1516                                                         totmat[0][2] = ob->obmat[0][2];
1517                                                         Normalize(totmat[0]);
1518                                                         
1519                                                         /* the z axis gets mapped onto
1520                                                         a third orthogonal vector */
1521                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1522                                                 }
1523                                                         break;
1524                                                 case TRACK_Z: /* LOCK X TRACK Z */
1525                                                 {
1526                                                         /* Projection of Vector on the plane */
1527                                                         Projf(vec2, vec, ob->obmat[0]);
1528                                                         VecSubf(totmat[2], vec, vec2);
1529                                                         Normalize(totmat[2]);
1530
1531                                                         /* the x axis is fixed*/
1532                                                         totmat[0][0] = ob->obmat[0][0];
1533                                                         totmat[0][1] = ob->obmat[0][1];
1534                                                         totmat[0][2] = ob->obmat[0][2];
1535                                                         Normalize(totmat[0]);
1536                                         
1537                                                         /* the z axis gets mapped onto
1538                                                         a third orthogonal vector */
1539                                                         Crossf(totmat[1], totmat[2], totmat[0]);
1540                                                 }
1541                                                         break;
1542                                                 case TRACK_nY: /* LOCK X TRACK -Y */
1543                                                 {
1544                                                         /* Projection of Vector on the plane */
1545                                                         Projf(vec2, vec, ob->obmat[0]);
1546                                                         VecSubf(totmat[1], vec, vec2);
1547                                                         Normalize(totmat[1]);
1548                                                         VecMulf(totmat[1],-1);
1549                                                         
1550                                                         /* the x axis is fixed*/
1551                                                         totmat[0][0] = ob->obmat[0][0];
1552                                                         totmat[0][1] = ob->obmat[0][1];
1553                                                         totmat[0][2] = ob->obmat[0][2];
1554                                                         Normalize(totmat[0]);
1555                                                         
1556                                                         /* the z axis gets mapped onto
1557                                                         a third orthogonal vector */
1558                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1559                                                 }
1560                                                         break;
1561                                                 case TRACK_nZ: /* LOCK X TRACK -Z */
1562                                                 {
1563                                                         /* Projection of Vector on the plane */
1564                                                         Projf(vec2, vec, ob->obmat[0]);
1565                                                         VecSubf(totmat[2], vec, vec2);
1566                                                         Normalize(totmat[2]);
1567                                                         VecMulf(totmat[2],-1);
1568                                                                 
1569                                                         /* the x axis is fixed*/
1570                                                         totmat[0][0] = ob->obmat[0][0];
1571                                                         totmat[0][1] = ob->obmat[0][1];
1572                                                         totmat[0][2] = ob->obmat[0][2];
1573                                                         Normalize(totmat[0]);
1574                                                                 
1575                                                         /* the z axis gets mapped onto
1576                                                         a third orthogonal vector */
1577                                                         Crossf(totmat[1], totmat[2], totmat[0]);
1578                                                 }
1579                                                         break;
1580                                                 default:
1581                                                 {
1582                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1583                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1584                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1585                                                 }
1586                                                         break;
1587                                         }
1588                                 }
1589                                         break;
1590                                 case LOCK_Y: /* LOCK Y */
1591                                 {
1592                                         switch (data->trackflag) {
1593                                                 case TRACK_X: /* LOCK Y TRACK X */
1594                                                 {
1595                                                         /* Projection of Vector on the plane */
1596                                                         Projf(vec2, vec, ob->obmat[1]);
1597                                                         VecSubf(totmat[0], vec, vec2);
1598                                                         Normalize(totmat[0]);
1599                                                         
1600                                                         /* the y axis is fixed*/
1601                                                         totmat[1][0] = ob->obmat[1][0];
1602                                                         totmat[1][1] = ob->obmat[1][1];
1603                                                         totmat[1][2] = ob->obmat[1][2];
1604                                                         Normalize(totmat[1]);
1605                                                         
1606                                                         /* the z axis gets mapped onto
1607                                                         a third orthogonal vector */
1608                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1609                                                 }
1610                                                         break;
1611                                                 case TRACK_Z: /* LOCK Y TRACK Z */
1612                                                 {
1613                                                         /* Projection of Vector on the plane */
1614                                                         Projf(vec2, vec, ob->obmat[1]);
1615                                                         VecSubf(totmat[2], vec, vec2);
1616                                                         Normalize(totmat[2]);
1617
1618                                                         /* the y axis is fixed*/
1619                                                         totmat[1][0] = ob->obmat[1][0];
1620                                                         totmat[1][1] = ob->obmat[1][1];
1621                                                         totmat[1][2] = ob->obmat[1][2];
1622                                                         Normalize(totmat[1]);
1623                                                         
1624                                                         /* the z axis gets mapped onto
1625                                                         a third orthogonal vector */
1626                                                         Crossf(totmat[0], totmat[1], totmat[2]);
1627                                                 }
1628                                                         break;
1629                                                 case TRACK_nX: /* LOCK Y TRACK -X */
1630                                                 {
1631                                                         /* Projection of Vector on the plane */
1632                                                         Projf(vec2, vec, ob->obmat[1]);
1633                                                         VecSubf(totmat[0], vec, vec2);
1634                                                         Normalize(totmat[0]);
1635                                                         VecMulf(totmat[0],-1);
1636
1637                                                         /* the y axis is fixed*/
1638                                                         totmat[1][0] = ob->obmat[1][0];
1639                                                         totmat[1][1] = ob->obmat[1][1];
1640                                                         totmat[1][2] = ob->obmat[1][2];
1641                                                         Normalize(totmat[1]);
1642                                                         
1643                                                         /* the z axis gets mapped onto
1644                                                         a third orthogonal vector */
1645                                                         Crossf(totmat[2], totmat[0], totmat[1]);
1646                                                 }
1647                                                         break;
1648                                                 case TRACK_nZ: /* LOCK Y TRACK -Z */
1649                                                 {
1650                                                         /* Projection of Vector on the plane */
1651                                                         Projf(vec2, vec, ob->obmat[1]);
1652                                                         VecSubf(totmat[2], vec, vec2);
1653                                                         Normalize(totmat[2]);
1654                                                         VecMulf(totmat[2],-1);
1655
1656                                                         /* the y axis is fixed*/
1657                                                         totmat[1][0] = ob->obmat[1][0];
1658                                                         totmat[1][1] = ob->obmat[1][1];
1659                                                         totmat[1][2] = ob->obmat[1][2];
1660                                                         Normalize(totmat[1]);
1661                                                         
1662                                                         /* the z axis gets mapped onto
1663                                                         a third orthogonal vector */
1664                                                         Crossf(totmat[0], totmat[1], totmat[2]);
1665                                                 }
1666                                                         break;
1667                                                 default:
1668                                                 {
1669                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1670                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1671                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1672                                                 }
1673                                                         break;
1674                                         }
1675                                 }
1676                                         break;
1677                                 case LOCK_Z: /* LOCK Z */
1678                                 {
1679                                         switch (data->trackflag) {
1680                                                 case TRACK_X: /* LOCK Z TRACK X */
1681                                                 {
1682                                                         /* Projection of Vector on the plane */
1683                                                         Projf(vec2, vec, ob->obmat[2]);
1684                                                         VecSubf(totmat[0], vec, vec2);
1685                                                         Normalize(totmat[0]);
1686                                                         
1687                                                         /* the z axis is fixed*/
1688                                                         totmat[2][0] = ob->obmat[2][0];
1689                                                         totmat[2][1] = ob->obmat[2][1];
1690                                                         totmat[2][2] = ob->obmat[2][2];
1691                                                         Normalize(totmat[2]);
1692                                                         
1693                                                         /* the x axis gets mapped onto
1694                                                         a third orthogonal vector */
1695                                                         Crossf(totmat[1], totmat[2], totmat[0]);
1696                                                 }
1697                                                         break;
1698                                                 case TRACK_Y: /* LOCK Z TRACK Y */
1699                                                 {
1700                                                         /* Projection of Vector on the plane */
1701                                                         Projf(vec2, vec, ob->obmat[2]);
1702                                                         VecSubf(totmat[1], vec, vec2);
1703                                                         Normalize(totmat[1]);
1704                                                         
1705                                                         /* the z axis is fixed*/
1706                                                         totmat[2][0] = ob->obmat[2][0];
1707                                                         totmat[2][1] = ob->obmat[2][1];
1708                                                         totmat[2][2] = ob->obmat[2][2];
1709                                                         Normalize(totmat[2]);
1710                                                                 
1711                                                         /* the x axis gets mapped onto
1712                                                         a third orthogonal vector */
1713                                                         Crossf(totmat[0], totmat[1], totmat[2]);
1714                                                 }
1715                                                         break;
1716                                                 case TRACK_nX: /* LOCK Z TRACK -X */
1717                                                 {
1718                                                         /* Projection of Vector on the plane */
1719                                                         Projf(vec2, vec, ob->obmat[2]);
1720                                                         VecSubf(totmat[0], vec, vec2);
1721                                                         Normalize(totmat[0]);
1722                                                         VecMulf(totmat[0],-1);
1723                                                         
1724                                                         /* the z axis is fixed*/
1725                                                         totmat[2][0] = ob->obmat[2][0];
1726                                                         totmat[2][1] = ob->obmat[2][1];
1727                                                         totmat[2][2] = ob->obmat[2][2];
1728                                                         Normalize(totmat[2]);
1729                                                         
1730                                                         /* the x axis gets mapped onto
1731                                                         a third orthogonal vector */
1732                                                         Crossf(totmat[1], totmat[2], totmat[0]);
1733                                                 }
1734                                                         break;
1735                                                 case TRACK_nY: /* LOCK Z TRACK -Y */
1736                                                 {
1737                                                         /* Projection of Vector on the plane */
1738                                                         Projf(vec2, vec, ob->obmat[2]);
1739                                                         VecSubf(totmat[1], vec, vec2);
1740                                                         Normalize(totmat[1]);
1741                                                         VecMulf(totmat[1],-1);
1742                                                         
1743                                                         /* the z axis is fixed*/
1744                                                         totmat[2][0] = ob->obmat[2][0];
1745                                                         totmat[2][1] = ob->obmat[2][1];
1746                                                         totmat[2][2] = ob->obmat[2][2];
1747                                                         Normalize(totmat[2]);
1748                                                                 
1749                                                         /* the x axis gets mapped onto
1750                                                         a third orthogonal vector */
1751                                                         Crossf(totmat[0], totmat[1], totmat[2]);
1752                                                 }
1753                                                         break;
1754                                                 default:
1755                                                 {
1756                                                                 totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1757                                                                 totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1758                                                                 totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1759                                                 }
1760                                                         break;
1761                                         }
1762                                 }
1763                                         break;
1764                                 default:
1765                                         {
1766                                                 totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1767                                                 totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1768                                                 totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1769                                         }
1770                                         break;
1771                                 }
1772                                 /* Block to keep matrix heading */
1773                                 tmpmat[0][0] = ob->obmat[0][0];tmpmat[0][1] = ob->obmat[0][1];tmpmat[0][2] = ob->obmat[0][2];
1774                                 tmpmat[1][0] = ob->obmat[1][0];tmpmat[1][1] = ob->obmat[1][1];tmpmat[1][2] = ob->obmat[1][2];
1775                                 tmpmat[2][0] = ob->obmat[2][0];tmpmat[2][1] = ob->obmat[2][1];tmpmat[2][2] = ob->obmat[2][2];
1776                                 Normalize(tmpmat[0]);
1777                                 Normalize(tmpmat[1]);
1778                                 Normalize(tmpmat[2]);
1779                                 Mat3Inv(invmat,tmpmat);
1780                                 Mat3MulMat3(tmpmat,totmat,invmat);
1781                                 totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
1782                                 totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
1783                                 totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
1784
1785                                 Mat4CpyMat4(tmat, ob->obmat);
1786
1787                                 mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
1788                                                                 totmat[1][0],totmat[1][1],totmat[1][2],
1789                                                                 totmat[2][0],totmat[2][1],totmat[2][2]);
1790                                 if (mdet==0)
1791                                 {
1792                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1793                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1794                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1795                                 }
1796
1797                                 /* apply out transformaton to the object */
1798                                 Mat4MulMat34(ob->obmat, totmat, tmat);
1799                         }
1800                 }
1801                 break;
1802         case CONSTRAINT_TYPE_FOLLOWPATH:
1803                 {
1804                         bFollowPathConstraint *data;
1805                         float obmat[4][4];
1806                         float size[3], obsize[3];
1807
1808                         data = constraint->data;                        
1809
1810                         if (data->tar) {
1811                                 /* get Object local transform (loc/rot/size) to determine transformation from path */
1812                                 object_to_mat4(ob, obmat);
1813                                 
1814                                 /* get scaling of object before applying constraint */
1815                                 Mat4ToSize(ob->obmat, size);
1816  
1817                                 /* apply targetmat - containing location on path, and rotation */
1818                                 Mat4MulSerie(ob->obmat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1819                                 
1820                                 /* un-apply scaling caused by path */
1821                                 Mat4ToSize(ob->obmat, obsize);
1822                                 if (obsize[0] != 0)
1823                                         VecMulf(ob->obmat[0], size[0] / obsize[0]);
1824                                 if (obsize[1] != 0)
1825                                         VecMulf(ob->obmat[1], size[1] / obsize[1]);
1826                                 if (obsize[2] != 0)
1827                                         VecMulf(ob->obmat[2], size[2] / obsize[2]);
1828                         }
1829                 }
1830                 break;
1831         case CONSTRAINT_TYPE_STRETCHTO:
1832         {
1833             bStretchToConstraint *data;
1834             float size[3],scale[3],vec[3],xx[3],zz[3],orth[3];
1835             float totmat[3][3];
1836             float tmat[4][4];
1837             float dist;
1838                         
1839             data = constraint->data;            
1840             Mat4ToSize (ob->obmat, size);
1841             
1842             if (data->tar) {
1843                 /* store X orientation before destroying obmat */
1844                 xx[0] = ob->obmat[0][0];
1845                 xx[1] = ob->obmat[0][1];
1846                 xx[2] = ob->obmat[0][2];
1847                 Normalize(xx);
1848                                 
1849                 /* store Z orientation before destroying obmat */
1850                 zz[0] = ob->obmat[2][0];
1851                 zz[1] = ob->obmat[2][1];
1852                 zz[2] = ob->obmat[2][2];
1853                 Normalize(zz);
1854                                 
1855                                 VecSubf(vec, ob->obmat[3], targetmat[3]);
1856                                 vec[0] /= size[0];
1857                                 vec[1] /= size[1];
1858                                 vec[2] /= size[2];
1859
1860                                 dist = Normalize(vec);
1861                 //dist = VecLenf( ob->obmat[3], targetmat[3]);
1862
1863                 if (data->orglength == 0)  data->orglength = dist;
1864                 if (data->bulge ==0) data->bulge = 1.0;
1865
1866                 scale[1] = dist/data->orglength;
1867                 switch (data->volmode) {
1868                 /* volume preserving scaling */
1869                 case VOLUME_XZ :
1870                     scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
1871                     scale[2] = scale[0];
1872                     break;
1873                 case VOLUME_X:
1874                     scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
1875                     scale[2] = 1.0;
1876                     break;
1877                 case VOLUME_Z:
1878                     scale[0] = 1.0;
1879                     scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
1880                     break;
1881                     /* don't care for volume */
1882                 case NO_VOLUME:
1883                     scale[0] = 1.0;
1884                     scale[2] = 1.0;
1885                     break;
1886                 default: /* should not happen, but in case*/
1887                     return;    
1888                 } /* switch (data->volmode) */
1889
1890                 /* Clear the object's rotation and scale */
1891                 ob->obmat[0][0]=size[0]*scale[0];
1892                 ob->obmat[0][1]=0;
1893                 ob->obmat[0][2]=0;
1894                 ob->obmat[1][0]=0;
1895                 ob->obmat[1][1]=size[1]*scale[1];
1896                 ob->obmat[1][2]=0;
1897                 ob->obmat[2][0]=0;
1898                 ob->obmat[2][1]=0;
1899                 ob->obmat[2][2]=size[2]*scale[2];
1900                 
1901                 VecSubf(vec, ob->obmat[3], targetmat[3]);
1902                 Normalize(vec);
1903                 /* new Y aligns  object target connection*/
1904                 totmat[1][0] = -vec[0];
1905                 totmat[1][1] = -vec[1];
1906                 totmat[1][2] = -vec[2];
1907                 switch (data->plane) {
1908                 case PLANE_X:
1909                     /* build new Z vector */
1910                     /* othogonal to "new Y" "old X! plane */
1911                     Crossf(orth, vec, xx);
1912                     Normalize(orth);
1913                     
1914                     /* new Z*/
1915                     totmat[2][0] = orth[0];
1916                     totmat[2][1] = orth[1];
1917                     totmat[2][2] = orth[2];
1918                     
1919                     /* we decided to keep X plane*/
1920                     Crossf(xx,orth, vec);
1921                     Normalize(xx);
1922                     totmat[0][0] = xx[0];
1923                     totmat[0][1] = xx[1];
1924                     totmat[0][2] = xx[2];
1925                     break;
1926                 case PLANE_Z:
1927                     /* build new X vector */
1928                     /* othogonal to "new Y" "old Z! plane */
1929                     Crossf(orth, vec, zz);
1930                     Normalize(orth);
1931                     
1932                     /* new X */
1933                     totmat[0][0] = -orth[0];
1934                     totmat[0][1] = -orth[1];
1935                     totmat[0][2] = -orth[2];
1936                     
1937                     /* we decided to keep Z */
1938                     Crossf(zz,orth, vec);
1939                     Normalize(zz);
1940                     totmat[2][0] = zz[0];
1941                     totmat[2][1] = zz[1];
1942                     totmat[2][2] = zz[2];
1943                     break;
1944                 } /* switch (data->plane) */
1945                 
1946                 Mat4CpyMat4(tmat, ob->obmat);
1947                 
1948                 Mat4MulMat34(ob->obmat, totmat, tmat);
1949             }
1950         }
1951         break;
1952         case CONSTRAINT_TYPE_LOCLIMIT:
1953                 {
1954                         bLocLimitConstraint *data;
1955
1956                         data = constraint->data;
1957                         
1958                         /* limit location relative to origin or parent   */
1959                         if ((data->flag2 & LIMIT_NOPARENT) && ob->parent) {
1960                                 /* limiting relative to parent */
1961                                 float parmat[4][4]; /* matrix of parent */
1962                                 float objLoc[3], parLoc[3]; /* location of object, and location of parent */
1963                                 float relLoc[3]; /* objLoc  - parLoc*/
1964                                 
1965                                 /* get matrix of parent */
1966                                 Mat4CpyMat4(parmat, ob->parent->obmat);
1967                                 
1968                                 /* get locations as vectors */
1969                                 objLoc[0] = ob->obmat[3][0];
1970                                 objLoc[1] = ob->obmat[3][1];
1971                                 objLoc[2] = ob->obmat[3][2];
1972                                 
1973                                 parLoc[0] = parmat[3][0];
1974                                 parLoc[1] = parmat[3][1];
1975                                 parLoc[2] = parmat[3][2];
1976                                 
1977                                 /* get relative location of obj from parent */
1978                                 VecSubf(relLoc, objLoc, parLoc);
1979                                 
1980                                 /* limiting location */
1981                                 if (data->flag & LIMIT_XMIN) {
1982                                         if(relLoc[0] < data->xmin) 
1983                                                 ob->obmat[3][0] = (parLoc[0]+data->xmin);
1984                                 }
1985                                 if (data->flag & LIMIT_XMAX) {
1986                                         if (relLoc[0] > data->xmax) 
1987                                                 ob->obmat[3][0] = (parLoc[0]+data->xmax);
1988                                 }
1989                                 if (data->flag & LIMIT_YMIN) {
1990                                         if(relLoc[1] < data->ymin) 
1991                                                 ob->obmat[3][1] = (parLoc[1]+data->ymin);
1992                                 }
1993                                 if (data->flag & LIMIT_YMAX) {
1994                                         if (relLoc[1] > data->ymax) 
1995                                                 ob->obmat[3][1] = (parLoc[1]+data->ymax);
1996                                 }
1997                                 if (data->flag & LIMIT_ZMIN) {
1998                                         if(relLoc[2] < data->zmin) 
1999                                                 ob->obmat[3][2] = (parLoc[2]+data->zmin);
2000                                 }
2001                                 if (data->flag & LIMIT_ZMAX) {
2002                                         if (relLoc[2] > data->zmax) 
2003                                                 ob->obmat[3][2] = (parLoc[2]+data->zmax);
2004                                 }
2005                         } else {
2006                                 /* limiting relative to origin */
2007                                 if (data->flag & LIMIT_XMIN) {
2008                                         if(ob->obmat[3][0] < data->xmin)
2009                                                 ob->obmat[3][0] = data->xmin;
2010                                 }
2011                                 if (data->flag & LIMIT_XMAX) {
2012                                         if (ob->obmat[3][0] > data->xmax)
2013                                                 ob->obmat[3][0] = data->xmax;
2014                                 }
2015                                 if (data->flag & LIMIT_YMIN) {
2016                                         if(ob->obmat[3][1] < data->ymin)
2017                                                 ob->obmat[3][1] = data->ymin;
2018                                 }
2019                                 if (data->flag & LIMIT_YMAX) {
2020                                         if (ob->obmat[3][1] > data->ymax)
2021                                                 ob->obmat[3][1] = data->ymax;
2022                                 }
2023                                 if (data->flag & LIMIT_ZMIN) {
2024                                         if(ob->obmat[3][2] < data->zmin) 
2025                                                 ob->obmat[3][2] = data->zmin;
2026                                 }
2027                                 if (data->flag & LIMIT_ZMAX) {
2028                                         if (ob->obmat[3][2] > data->zmax)
2029                                                 ob->obmat[3][2] = data->zmax;
2030                                 }
2031                         }
2032                 }
2033                 break;
2034         case CONSTRAINT_TYPE_ROTLIMIT:
2035                 {
2036                         bRotLimitConstraint *data;
2037                         float loc[3];
2038                         float eul[3];
2039                         float size[3];
2040                         
2041                         data = constraint->data;
2042                         
2043                         VECCOPY(loc, ob->obmat[3]);
2044                         Mat4ToSize(ob->obmat, size);
2045                         
2046                         Mat4ToEul(ob->obmat, eul);
2047                         
2048                         /* eulers: radians to degrees! */
2049                         eul[0] = (eul[0] / M_PI * 180);
2050                         eul[1] = (eul[1] / M_PI * 180);
2051                         eul[2] = (eul[2] / M_PI * 180);
2052                         
2053                         /* limiting of euler values... */
2054                         if (data->flag & LIMIT_XROT) {
2055                                 if (eul[0] < data->xmin) 
2056                                         eul[0] = data->xmin;
2057                                         
2058                                 if (eul[0] > data->xmax)
2059                                         eul[0] = data->xmax;
2060                         }
2061                         if (data->flag & LIMIT_YROT) {
2062                                 if (eul[1] < data->ymin)
2063                                         eul[1] = data->ymin;
2064                                         
2065                                 if (eul[1] > data->ymax)
2066                                         eul[1] = data->ymax;
2067                         }
2068                         if (data->flag & LIMIT_ZROT) {
2069                                 if (eul[2] < data->zmin)
2070                                         eul[2] = data->zmin;
2071                                         
2072                                 if (eul[2] > data->zmax)
2073                                         eul[2] = data->zmax;
2074                         }
2075                                 
2076                         /* eulers: degrees to radians ! */
2077                         eul[0] = (eul[0] / 180 * M_PI); 
2078                         eul[1] = (eul[1] / 180 * M_PI);
2079                         eul[2] = (eul[2] / 180 * M_PI);
2080                         
2081                         LocEulSizeToMat4(ob->obmat, loc, eul, size);
2082                 }
2083                 break;
2084         case CONSTRAINT_TYPE_SIZELIMIT:
2085                 {
2086                         bSizeLimitConstraint *data;
2087                         float obsize[3], size[3];
2088                         int clearNegScale=0;
2089                         
2090                         data = constraint->data;
2091                         
2092                         Mat4ToSize(ob->obmat, size);
2093                         Mat4ToSize(ob->obmat, obsize);
2094                         
2095                         if (data->flag & LIMIT_XMIN) {
2096                                 if (ob->transflag & OB_NEG_SCALE) {
2097                                         size[0] *= -1;
2098                                         
2099                                         if (size[0] < data->xmin) { 
2100                                                 size[0] = data->xmin;
2101                                                 clearNegScale += 1;
2102                                         }
2103                                 } else {
2104                                         if (size[0] < data->xmin) 
2105                                                 size[0] = data->xmin;   
2106                                 }       
2107                         }
2108                         if (data->flag & LIMIT_XMAX) {
2109                                 if (size[0] > data->xmax) 
2110                                         size[0] = data->xmax;
2111                         }
2112                         if (data->flag & LIMIT_YMIN) {
2113                                 if (ob->transflag & OB_NEG_SCALE) {
2114                                         size[1] *= -1;
2115                                         
2116                                         if (size[1] < data->ymin) { 
2117                                                 size[1] = data->ymin;
2118                                                 clearNegScale += 1;
2119                                         }
2120                                 } else {
2121                                         if (size[1] < data->ymin) 
2122                                                 size[1] = data->ymin;   
2123                                 }       
2124                         }
2125                         if (data->flag & LIMIT_YMAX) {
2126                                 if (size[1] > data->ymax) 
2127                                         size[1] = data->ymax;
2128                         }
2129                         if (data->flag & LIMIT_ZMIN) {
2130                                 if (ob->transflag & OB_NEG_SCALE) {
2131                                         size[2] *= -1;
2132                                         
2133                                         if (size[2] < data->zmin) { 
2134                                                 size[2] = data->zmin;
2135                                                 clearNegScale += 1;
2136                                         }
2137                                 } else {
2138                                         if (size[2] < data->zmin) 
2139                                                 size[2] = data->zmin;   
2140                                 }       
2141                         }
2142                         if (data->flag & LIMIT_ZMAX) {
2143                                 if (size[2] > data->zmax) 
2144                                         size[2] = data->zmax;
2145                         }
2146                         
2147                         if (clearNegScale != 0) {
2148                                 ob->transflag &= ~OB_NEG_SCALE;  /* is this how we remove that flag? */ 
2149                         }
2150                         
2151                         VecMulf(ob->obmat[0], size[0]/obsize[0]);
2152                         VecMulf(ob->obmat[1], size[1]/obsize[1]);
2153                         VecMulf(ob->obmat[2], size[2]/obsize[2]);
2154                 }
2155                 break;
2156         case CONSTRAINT_TYPE_RIGIDBODYJOINT:
2157         {
2158
2159
2160         }
2161         break;  
2162         case CONSTRAINT_TYPE_CLAMPTO:
2163                 {
2164                         bClampToConstraint *data;
2165                         Curve *cu;
2166                         float obmat[4][4], targetMatrix[4][4], ownLoc[3];
2167                         float curveMin[3], curveMax[3];
2168                         
2169                         data = constraint->data;
2170                         
2171                         /* prevent crash if user deletes curve */
2172                         if ((data->tar == NULL) || (data->tar->type != OB_CURVE) ) 
2173                                 return;
2174                         else
2175                                 cu= data->tar->data;
2176                         
2177                         Mat4CpyMat4(obmat, ob->obmat);
2178                         Mat4One(targetMatrix);
2179                         VECCOPY(ownLoc, obmat[3]);
2180                         
2181                         INIT_MINMAX(curveMin, curveMax)
2182                         minmax_object(data->tar, curveMin, curveMax);
2183                         
2184                         /* get targetmatrix */
2185                         if(cu->path && cu->path->data) {
2186                                 float vec[4], dir[3], totmat[4][4];
2187                                 float curvetime;
2188                                 short clamp_axis;
2189                                 
2190                                 /* find best position on curve */
2191                                 /* 1. determine which axis to sample on? */
2192                                 if (data->flag==CLAMPTO_AUTO) {
2193                                         float size[3];
2194                                         VecSubf(size, curveMax, curveMin);
2195                                         
2196                                         /* find axis along which the bounding box has the greatest
2197                                          * extent. Otherwise, default to the x-axis, as that is quite
2198                                          * frequently used.
2199                                          */
2200                                         if ((size[2]>size[0]) && (size[2]>size[1]))
2201                                                 clamp_axis= CLAMPTO_Z;
2202                                         else if ((size[1]>size[0]) && (size[1]>size[2]))
2203                                                 clamp_axis= CLAMPTO_Y;
2204                                         else
2205                                                 clamp_axis = CLAMPTO_X;
2206                                 }
2207                                 else 
2208                                         clamp_axis= data->flag;
2209                                         
2210                                 /* 2. determine position relative to curve on a 0-1 scale */
2211                                 if (clamp_axis > 0) clamp_axis--;
2212                                 if (ownLoc[clamp_axis] <= curveMin[clamp_axis])
2213                                         curvetime = 0.0;
2214                                 else if (ownLoc[clamp_axis] >= curveMax[clamp_axis])
2215                                         curvetime = 1.0;
2216                                 else
2217                                         curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]); // umm
2218                                 
2219                                 /* 3. position on curve */
2220                                 if(where_on_path(data->tar, curvetime, vec, dir) ) {
2221                                         Mat4One(totmat);
2222                                         VECCOPY(totmat[3], vec);
2223                                         
2224                                         Mat4MulSerie(targetMatrix, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
2225                                 }
2226                         }
2227                         
2228                         /* obtain final object position */
2229                         VECCOPY(ob->obmat[3], targetMatrix[3]);
2230                 }
2231                 break;
2232         default:
2233                 printf ("Error: Unknown constraint type\n");
2234                 break;
2235         }
2236 }