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