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