Patch: Constraints to Limit Transforms (#4662) by Joshua Leung (aligorith)
[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->tolerance = (float)0.001;
567                         data->weight= (float)1.0;
568                         data->iterations = 500;
569                         data->flag= CONSTRAINT_IK_TIP;
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->sticky = 0;
602                         data->stuck = 0;
603
604                         result = data;
605
606                 }
607                 break;
608         case CONSTRAINT_TYPE_ROTLIKE:
609                 {
610                         bRotateLikeConstraint *data;
611                         data = MEM_callocN(sizeof(bRotateLikeConstraint), "rotlikeConstraint");
612                         data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
613                         result = data;
614                 }
615                 break;
616         case CONSTRAINT_TYPE_LOCLIKE:
617                 {
618                         bLocateLikeConstraint *data;
619                         data = MEM_callocN(sizeof(bLocateLikeConstraint), "loclikeConstraint");
620                         data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
621                         result = data;
622                 }
623                 break;
624         case CONSTRAINT_TYPE_SIZELIKE:
625                 {
626                         bSizeLikeConstraint *data;
627                         data = MEM_callocN(sizeof(bLocateLikeConstraint), "sizelikeConstraint");
628
629                         data->flag |= SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
630                         result = data;
631                 }
632                 break;
633         case CONSTRAINT_TYPE_ACTION:
634                 {
635                         bActionConstraint *data;
636                         data = MEM_callocN(sizeof(bActionConstraint), "actionConstraint");
637                         data->local= 1;
638                         
639                         result = data;
640                 }
641                 break;
642         case CONSTRAINT_TYPE_LOCKTRACK:
643                 {
644                         bLockTrackConstraint *data;
645                         data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
646
647                         data->trackflag = TRACK_Y;
648                         data->lockflag = LOCK_Z;
649
650                         result = data;
651                 }
652                 break;
653         case CONSTRAINT_TYPE_FOLLOWPATH:
654                 {
655                         bFollowPathConstraint *data;
656                         data = MEM_callocN(sizeof(bFollowPathConstraint), "followpathConstraint");
657
658                         data->trackflag = TRACK_Y;
659                         data->upflag = UP_Z;
660                         data->offset = 0;
661                         data->followflag = 0;
662
663                         result = data;
664                 }
665                 break;
666         case CONSTRAINT_TYPE_STRETCHTO:
667                 {
668                         bStretchToConstraint *data;
669                         data = MEM_callocN(sizeof(bStretchToConstraint), "StretchToConstraint");
670
671                         data->volmode = 0;
672                         data->plane = 0;
673                         data->orglength = 0.0; 
674                         data->bulge = 1.0;
675                         result = data;
676                 }
677                 break; 
678         case CONSTRAINT_TYPE_LOCLIMIT:
679                 {
680                         bLocLimitConstraint *data;
681                         data = MEM_callocN(sizeof(bLocLimitConstraint), "LocLimitConstraint");
682                         
683                         data->flag = 0;
684                         data->flag2 = 0;
685                         data->xmin = 0.0f;
686                         data->xmax = 0.0f;
687                         data->ymin = 0.0f;
688                         data->ymax = 0.0f;
689                         data->zmin = 0.0f;
690                         data->zmax = 0.0f;
691                         
692                         result = data;
693                 }
694                 break;
695         case CONSTRAINT_TYPE_ROTLIMIT:
696                 {
697                         bRotLimitConstraint *data;
698                         data = MEM_callocN(sizeof(bRotLimitConstraint), "RotLimitConstraint");
699                         
700                         data->flag = 0;
701                         data->xmin = 0.0f;
702                         data->xmax = 0.0f;
703                         data->ymin = 0.0f;
704                         data->ymax = 0.0f;
705                         data->zmin = 0.0f;
706                         data->zmax = 0.0f;
707                         
708                         result = data;
709                 }
710                 break;
711         case CONSTRAINT_TYPE_SIZELIMIT:
712                 {
713                         bSizeLimitConstraint *data;
714                         data = MEM_callocN(sizeof(bSizeLimitConstraint), "SizeLimitConstraint");
715                         
716                         data->flag = 0;
717                         data->xmin = 0.0f;
718                         data->xmax = 0.0f;
719                         data->ymin = 0.0f;
720                         data->ymax = 0.0f;
721                         data->zmin = 0.0f;
722                         data->zmax = 0.0f;
723                         
724                         result = data;
725                 }
726                 break;
727         default:
728                 result = NULL;
729                 break;
730         }
731
732         return result;
733 }
734
735 bConstraintChannel *get_constraint_channel (ListBase *list, const char *name)
736 {
737         bConstraintChannel *chan;
738
739         for (chan = list->first; chan; chan=chan->next) {
740                 if (!strcmp(name, chan->name)) {
741                         return chan;
742                 }
743         }
744         return NULL;
745 }
746
747 /* finds or creates new constraint channel */
748 bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name)
749 {
750         bConstraintChannel *chan;
751         
752         chan= get_constraint_channel (list, name);
753         if(chan==NULL) {
754                 chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint chan");
755                 BLI_addtail(list, chan);
756                 strcpy(chan->name, name);
757         }
758         
759         return chan;
760 }
761
762
763 /* ***************** Evaluating ********************* */
764
765 /* does ipos only */
766 void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
767 {
768         bConstraint *con;
769         bConstraintChannel *chan;
770         IpoCurve *icu=NULL;
771         
772         for (con=conbase->first; con; con=con->next) {
773                 chan = get_constraint_channel(chanbase, con->name);
774                 if (chan && chan->ipo){
775                         calc_ipo(chan->ipo, ctime);
776                         for (icu=chan->ipo->curve.first; icu; icu=icu->next){
777                                 switch (icu->adrcode){
778                                 case CO_ENFORCE:
779                                         con->enforce = icu->curval;
780                                         if (con->enforce<0.0f) con->enforce= 0.0f;
781                                         else if (con->enforce>1.0f) con->enforce= 1.0f;
782                                         break;
783                                 }
784                         }
785                 }
786         }
787 }
788
789 void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight)
790 {
791         float squat[4], dquat[4], fquat[4];
792         float ssize[3], dsize[3], fsize[4];
793         float sloc[3], dloc[3], floc[3];
794         float mat3[3][3], dstweight;
795         float qmat[3][3], smat[3][3];
796         int i;
797
798         dstweight = 1.0F-srcweight;
799
800         Mat3CpyMat4(mat3, dst);
801         Mat3ToQuat(mat3, dquat);
802         Mat3ToSize(mat3, dsize);
803         VECCOPY (dloc, dst[3]);
804
805         Mat3CpyMat4(mat3, src);
806         Mat3ToQuat(mat3, squat);
807         Mat3ToSize(mat3, ssize);
808         VECCOPY (sloc, src[3]);
809         
810         /* Do the actual blend */
811         for (i=0; i<3; i++){
812                 floc[i] = (dloc[i]*dstweight) + (sloc[i]*srcweight);
813                 fsize[i] = 1.0f + ((dsize[i]-1.0f)*dstweight) + ((ssize[i]-1.0f)*srcweight);
814                 fquat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
815         }
816         
817         /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
818         fquat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
819         NormalQuat (fquat);
820
821         QuatToMat3(fquat, qmat);
822         SizeToMat3(fsize, smat);
823
824         Mat3MulMat3(mat3, qmat, smat);
825         Mat4CpyMat3(out, mat3);
826         VECCOPY (out[3], floc);
827 }
828
829 static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime)
830 {
831
832         /*      Case OBJECT */
833         if (!strlen(substring)) {
834                 Mat4CpyMat4 (mat, ob->obmat);
835                 VECCOPY (size, ob->size);  // whats this for, hack! (ton)
836         }
837         /*      Case BONE */
838         else {
839                 bPoseChannel *pchan;
840                 float   bsize[3]={1, 1, 1};
841
842                 pchan = get_pose_channel(ob->pose, substring);
843                 if (pchan){
844                         /**
845                          *      Multiply the objectspace bonematrix by the skeletons's global
846                          *      transform to obtain the worldspace transformation of the target
847                          */
848                         Mat4MulMat4 (mat, pchan->pose_mat, ob->obmat);
849                 } 
850                 else
851                         Mat4CpyMat4 (mat, ob->obmat);
852
853                 VECCOPY(size, bsize);   // whats this for, hack! (ton)
854         }
855 }
856
857 /* called during solve_constraints */
858 /* also for make_parent, to find correct inverse of "follow path" */
859 /* warning, ownerdata is void... is not Bone anymore, but PoseChannel or Object */
860 short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
861 {
862         short valid=0;
863
864         switch (con->type){
865         case CONSTRAINT_TYPE_NULL:
866                 {
867                         Mat4One(mat);
868                 }
869                 break;
870         case CONSTRAINT_TYPE_ACTION:
871                 {
872                         if (ownertype == TARGET_BONE) {
873                                 extern void chan_calc_mat(bPoseChannel *chan);
874                                 bActionConstraint *data = (bActionConstraint*)con->data;
875                                 bPose *pose;
876                                 bPoseChannel *pchan, *tchan;
877                                 float tempmat3[3][3];
878                                 float eul[3];
879                                 float s,t;
880                                 
881                                 Mat4One(mat);   // return mat
882                                 
883                                 if (data->tar==NULL) return 0;
884                                 
885                                 /* need proper check for bone... */
886                                 if(data->subtarget[0]) {
887                                         pchan = get_pose_channel(data->tar->pose, data->subtarget);
888                                         if (pchan) {
889                                                 float arm_mat[3][3], pose_mat[3][3];            /* arm mat should be bone mat! bug... */
890                                                 
891                                                 Mat3CpyMat4(arm_mat, pchan->bone->arm_mat);
892                                                 Mat3CpyMat4(pose_mat, pchan->pose_mat);
893                                                 
894                                                 /* new; true local rotation constraint */
895                                                 if(data->local) {
896                                                         float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3];
897                                                         /* we need the local rotation = current rotation - (parent rotation + restpos) */
898                                                         
899                                                         if (pchan->parent) {
900                                                                 Mat3CpyMat4(par_mat, pchan->parent->pose_mat);
901                                                                 Mat3MulMat3(diff_mat, par_mat, arm_mat);
902                                                                 
903                                                                 Mat3Inv(ipar_mat, diff_mat);
904                                                         }
905                                                         else {
906                                                                 Mat3Inv(ipar_mat, arm_mat);
907                                                         }
908                                                         
909                                                         Mat3MulMat3(tempmat3, ipar_mat, pose_mat);
910                                                 }
911                                                 else {  /* we use the deform mat, for backwards compatibility */
912                                                         float imat[3][3];
913                                                         
914                                                         Mat3Inv(imat, arm_mat);
915                                                         Mat3MulMat3(tempmat3, pose_mat, imat);
916                                                 }
917                                         }
918                                         else Mat3One(tempmat3);
919                                 }
920                                 else {
921                                         float ans[4][4];
922                                         
923                                         constraint_target_to_mat4(data->tar, data->subtarget, ans, size, ctime);
924                                         /* extract rotation, is in global world coordinates */
925                                         Mat3CpyMat4(tempmat3, ans);
926                                 }
927                                 
928                                 Mat3ToEul(tempmat3, eul);
929                                 eul[0]*=(float)(180.0/M_PI);
930                                 eul[1]*=(float)(180.0/M_PI);
931                                 eul[2]*=(float)(180.0/M_PI);
932                                 
933                                 /* Target defines the animation */
934                                 s = (eul[data->type]-data->min)/(data->max-data->min);
935                                 if (s<0)
936                                         s=0;
937                                 if (s>1)
938                                         s=1;
939
940                                 t = ( s * (data->end-data->start)) + data->start;
941
942                                 /* Get the appropriate information from the action, we make temp pose */
943                                 pose = MEM_callocN(sizeof(bPose), "pose");
944                                 
945                                 pchan = ownerdata;
946                                 tchan= verify_pose_channel(pose, pchan->name);
947                                 extract_pose_from_action (pose, data->act, t);
948                                 
949                                 chan_calc_mat(tchan);
950                                 
951                                 Mat4CpyMat4(mat, tchan->chan_mat);
952
953                                 /* Clean up */
954                                 free_pose_channels(pose);
955                                 MEM_freeN(pose);
956                         }
957                         
958                 }
959                 break;
960         case CONSTRAINT_TYPE_LOCLIKE:
961                 {
962                         bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
963
964                         if (data->tar){
965                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
966                                 valid=1;
967                         }
968                         else
969                                 Mat4One (mat);
970                 } 
971                 break;
972         case CONSTRAINT_TYPE_MINMAX:
973                 {
974                         bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
975
976                         if (data->tar){
977                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
978                                 valid=1;
979                         }
980                         else
981                                 Mat4One (mat);
982                 } 
983                 break;
984         case CONSTRAINT_TYPE_ROTLIKE:
985                 {
986                         bRotateLikeConstraint *data;
987                         data = (bRotateLikeConstraint*)con->data;
988
989                         if (data->tar){
990                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
991                                 valid=1;
992                         }
993                         else
994                                 Mat4One (mat);
995                 } 
996                 break;
997         case CONSTRAINT_TYPE_SIZELIKE:
998                 {
999                         bSizeLikeConstraint *data;
1000                         data = (bSizeLikeConstraint*)con->data;
1001
1002                         if (data->tar){
1003                                 /*      Update the location of the target object */
1004                                 where_is_object_time (data->tar, ctime);        
1005                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
1006                                 valid=1;
1007                         }
1008                         else
1009                                 Mat4One (mat);
1010                 } 
1011                 break;
1012         case CONSTRAINT_TYPE_TRACKTO:
1013                 {
1014                         bTrackToConstraint *data;
1015                         data = (bTrackToConstraint*)con->data;
1016
1017                         if (data->tar){
1018                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
1019                                 valid=1;
1020                         }
1021                         else
1022                                 Mat4One (mat);
1023                 }
1024                 break;
1025         case CONSTRAINT_TYPE_KINEMATIC:
1026                 {
1027                         bKinematicConstraint *data;
1028                         data = (bKinematicConstraint*)con->data;
1029
1030                         if (data->tar){
1031                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
1032                                 valid=1;
1033                         }
1034                         else if (data->flag & CONSTRAINT_IK_AUTO) {
1035                                 Object *ob= ownerdata;
1036                                 
1037                                 if(ob==NULL)
1038                                         Mat4One(mat);
1039                                 else {
1040                                         float vec[3];
1041                                         /* move grabtarget into world space */
1042                                         VECCOPY(vec, data->grabtarget);
1043                                         Mat4MulVecfl(ob->obmat, vec);
1044                                         Mat4CpyMat4(mat, ob->obmat);
1045                                         VECCOPY(mat[3], vec);
1046                                 }
1047                         }
1048                         else
1049                                 Mat4One (mat);
1050                 } 
1051                 break;
1052         case CONSTRAINT_TYPE_LOCKTRACK:
1053                 {
1054                         bLockTrackConstraint *data;
1055                         data = (bLockTrackConstraint*)con->data;
1056
1057                         if (data->tar){
1058                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
1059                                 valid=1;
1060                         }
1061                         else
1062                                 Mat4One (mat);
1063                 } 
1064                 break;
1065         case CONSTRAINT_TYPE_FOLLOWPATH:
1066                 {
1067                         bFollowPathConstraint *data;
1068                         data = (bFollowPathConstraint*)con->data;
1069
1070                         if (data->tar){
1071                                 Curve *cu;
1072                                 float q[4], vec[4], dir[3], *quat, x1, totmat[4][4];
1073                                 float curvetime;
1074
1075                                 Mat4One (totmat);
1076                                 Mat4One (mat);
1077
1078                                 cu= data->tar->data;
1079
1080                                 /* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
1081                                         currently for paths to work it needs to go through the bevlist/displist system (ton) */
1082                                 
1083                                 if(cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
1084                                         makeDispListCurveTypes(data->tar, 0);
1085                                 if(cu->path && cu->path->data) {
1086                                         curvetime= bsystem_time(data->tar, data->tar->parent, (float)ctime, 0.0) - data->offset;
1087
1088                                         if(calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
1089                                                 curvetime /= cu->pathlen;
1090                                                 CLAMP(curvetime, 0.0, 1.0);
1091                                         }
1092
1093                                         if(where_on_path(data->tar, curvetime, vec, dir) ) {
1094
1095                                                 if(data->followflag){
1096                                                         quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
1097
1098                                                         Normalise(dir);
1099                                                         q[0]= (float)cos(0.5*vec[3]);
1100                                                         x1= (float)sin(0.5*vec[3]);
1101                                                         q[1]= -x1*dir[0];
1102                                                         q[2]= -x1*dir[1];
1103                                                         q[3]= -x1*dir[2];
1104                                                         QuatMul(quat, q, quat);
1105                                                         
1106
1107                                                         QuatToMat4(quat, totmat);
1108                                                 }
1109                                                 VECCOPY(totmat[3], vec);
1110
1111                                                 Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
1112                                         }
1113                                 }
1114                                 valid=1;
1115                         }
1116                         else
1117                                 Mat4One (mat);
1118                 }
1119                 break;
1120         case CONSTRAINT_TYPE_STRETCHTO:
1121                 {
1122                         bStretchToConstraint *data;
1123                         data = (bStretchToConstraint*)con->data;
1124
1125                         if (data->tar){
1126                                 constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
1127                                 valid = 1;
1128                         }
1129                         else
1130                                 Mat4One (mat);
1131                 }
1132                 break;
1133
1134         default:
1135                 Mat4One(mat);
1136                 break;
1137         }
1138
1139         return valid;
1140 }
1141
1142
1143 /* only called during solve_constraints */
1144 /* bone constraints create a fake object to work on, then ob is a workob */
1145 /* if ownerdata is set, it's the posechannel */
1146 void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
1147 {
1148         float   M_oldmat[4][4];
1149         float   M_identity[4][4];
1150         
1151         if (!constraint || !ob)
1152                 return;
1153         
1154         Mat4One (M_identity);
1155         
1156         switch (constraint->type){
1157         case CONSTRAINT_TYPE_ACTION:
1158                 {
1159                         float temp[4][4];
1160                         bActionConstraint *data;
1161                         
1162                         data = constraint->data;
1163                         Mat4CpyMat4 (temp, ob->obmat);
1164
1165                         Mat4MulMat4(ob->obmat, targetmat, temp);
1166                 }
1167                 break;
1168         case CONSTRAINT_TYPE_LOCLIKE:
1169                 {
1170                         bLocateLikeConstraint *data;
1171
1172                         data = constraint->data;
1173                         
1174                         if (data->flag & LOCLIKE_X)
1175                                 ob->obmat[3][0] = targetmat[3][0];
1176                         if (data->flag & LOCLIKE_Y)
1177                                 ob->obmat[3][1] = targetmat[3][1];
1178                         if (data->flag & LOCLIKE_Z)
1179                                 ob->obmat[3][2] = targetmat[3][2];
1180                 }
1181                 break;
1182         case CONSTRAINT_TYPE_ROTLIKE:
1183                 {
1184                         bRotateLikeConstraint *data;
1185                         float   tmat[3][3];
1186                         float   size[3];
1187                         
1188                         data = constraint->data;
1189                         
1190                         /* old files stuff only... version patch is too much code! */
1191                         if(data->flag==0) data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
1192
1193                         Mat4ToSize(ob->obmat, size);
1194                         
1195                         Mat3CpyMat4 (tmat, targetmat);
1196                         Mat3Ortho(tmat);
1197                         
1198                         if(data->flag != (ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z)) {
1199                                 float obeul[3], eul[3], obmat[3][3];
1200                                 
1201                                 Mat3ToEul(tmat, eul);
1202                                 Mat3CpyMat4(obmat, ob->obmat);
1203                                 Mat3ToEul(obmat, obeul);
1204                                 if(!(data->flag & ROTLIKE_X)) eul[0]= obeul[0];
1205                                 if(!(data->flag & ROTLIKE_Y)) eul[1]= obeul[1];
1206                                 if(!(data->flag & ROTLIKE_Z)) eul[2]= obeul[2];
1207                                 compatible_eul(eul, obeul);
1208                                 EulToMat3(eul, tmat);
1209                         }
1210
1211                         ob->obmat[0][0] = tmat[0][0]*size[0];
1212                         ob->obmat[0][1] = tmat[0][1]*size[1];
1213                         ob->obmat[0][2] = tmat[0][2]*size[2];
1214
1215                         ob->obmat[1][0] = tmat[1][0]*size[0];
1216                         ob->obmat[1][1] = tmat[1][1]*size[1];
1217                         ob->obmat[1][2] = tmat[1][2]*size[2];
1218
1219                         ob->obmat[2][0] = tmat[2][0]*size[0];
1220                         ob->obmat[2][1] = tmat[2][1]*size[1];
1221                         ob->obmat[2][2] = tmat[2][2]*size[2];
1222                 }
1223                 break;
1224         case CONSTRAINT_TYPE_SIZELIKE:
1225                 {
1226                         float obsize[3], size[3];
1227                         bSizeLikeConstraint *data;
1228  
1229                         data = constraint->data;
1230  
1231                         Mat4ToSize(targetmat, size);
1232                         Mat4ToSize(ob->obmat, obsize);
1233                         
1234                         if (data->flag & SIZELIKE_X && obsize[0] != 0)
1235                                 VecMulf(ob->obmat[0], size[0] / obsize[0]);
1236                         if (data->flag & SIZELIKE_Y && obsize[1] != 0)
1237                                 VecMulf(ob->obmat[1], size[1] / obsize[1]);
1238                         if (data->flag & SIZELIKE_Z && obsize[2] != 0)
1239                                 VecMulf(ob->obmat[2], size[2] / obsize[2]);
1240                 }
1241                 break;
1242         case CONSTRAINT_TYPE_NULL:
1243                 {
1244                 }
1245                 break;
1246         case CONSTRAINT_TYPE_MINMAX:
1247                 {
1248                         float val1, val2;
1249                         int index;
1250                         bMinMaxConstraint *data;
1251
1252                         data = constraint->data;
1253
1254                         switch (data->minmaxflag){
1255                         case TRACK_Z:
1256                                 val1 = targetmat[3][2];
1257                                 val2 = ob->obmat[3][2]-data->offset;
1258                                 index = 2;
1259                                 break;
1260                         case TRACK_Y:
1261                                 val1 = targetmat[3][1];
1262                                 val2 = ob->obmat[3][1]-data->offset;
1263                                 index = 1;
1264                                 break;
1265                         case TRACK_X:
1266                                 val1 = targetmat[3][0];
1267                                 val2 = ob->obmat[3][0]-data->offset;
1268                                 index = 0;
1269                                 break;
1270                         case TRACK_nZ:
1271                                 val2 = targetmat[3][2];
1272                                 val1 = ob->obmat[3][2]-data->offset;
1273                                 index = 2;
1274                                 break;
1275                         case TRACK_nY:
1276                                 val2 = targetmat[3][1];
1277                                 val1 = ob->obmat[3][1]-data->offset;
1278                                 index = 1;
1279                                 break;
1280                         case TRACK_nX:
1281                                 val2 = targetmat[3][0];
1282                                 val1 = ob->obmat[3][0]-data->offset;
1283                                 index = 0;
1284                                 break;
1285                         default:
1286                                 return;
1287                         }
1288                         
1289                         if (val1 > val2) {
1290                                 ob->obmat[3][index] = targetmat[3][index] + data->offset;
1291                                 if (data->sticky==1) {
1292                                         if (data->stuck==1) {
1293                                                 VECCOPY(ob->obmat[3], data->cache);
1294                                         } else {
1295                                                 VECCOPY(data->cache, ob->obmat[3]);
1296                                                 data->stuck = 1;
1297                                         }
1298                                 }
1299                         } else {
1300                                 data->stuck=0;
1301                         }
1302                 }
1303                 break;
1304         case CONSTRAINT_TYPE_TRACKTO:
1305                 {
1306                         bTrackToConstraint *data;
1307                         float size[3];
1308                         float *quat;
1309                         float vec[3];
1310                         float totmat[3][3];
1311                         float tmat[4][4];
1312
1313                         data=(bTrackToConstraint*)constraint->data;                     
1314                         
1315                         if (data->tar){
1316                                         
1317                                 /* Get size property, since ob->size is only the object's own relative size, not its global one */
1318                                 Mat4ToSize (ob->obmat, size);
1319         
1320                                 Mat4CpyMat4 (M_oldmat, ob->obmat);
1321
1322                                 // Clear the object's rotation  
1323                                 ob->obmat[0][0]=size[0];
1324                                 ob->obmat[0][1]=0;
1325                                 ob->obmat[0][2]=0;
1326                                 ob->obmat[1][0]=0;
1327                                 ob->obmat[1][1]=size[1];
1328                                 ob->obmat[1][2]=0;
1329                                 ob->obmat[2][0]=0;
1330                                 ob->obmat[2][1]=0;
1331                                 ob->obmat[2][2]=size[2];
1332         
1333                         
1334                                 VecSubf(vec, ob->obmat[3], targetmat[3]);
1335                                 quat= vectoquat(vec, (short)data->reserved1, (short)data->reserved2);
1336                                 QuatToMat3(quat, totmat);
1337
1338                                 Mat4CpyMat4(tmat, ob->obmat);
1339                                 
1340                                 Mat4MulMat34(ob->obmat, totmat, tmat);
1341                         }
1342                 }
1343                 break;
1344         case CONSTRAINT_TYPE_KINEMATIC:
1345                 {
1346                         /* removed */
1347                 }
1348                 break;
1349         case CONSTRAINT_TYPE_LOCKTRACK:
1350                 {
1351                         bLockTrackConstraint *data;
1352                         float vec[3],vec2[3];
1353                         float totmat[3][3];
1354                         float tmpmat[3][3];
1355                         float invmat[3][3];
1356                         float tmat[4][4];
1357                         float mdet;
1358
1359
1360                         data=(bLockTrackConstraint*)constraint->data;                   
1361                         
1362
1363                         if (data->tar){
1364         
1365                                 Mat4CpyMat4 (M_oldmat, ob->obmat);
1366
1367                                 /* Vector object -> target */
1368                                 VecSubf(vec, targetmat[3], ob->obmat[3]);
1369                                 switch (data->lockflag){
1370                                 case LOCK_X: /* LOCK X */
1371                                         {
1372                                         switch (data->trackflag){
1373                                         case TRACK_Y: /* LOCK X TRACK Y */
1374                                                 {
1375                                                 /* Projection of Vector on the plane */
1376                                                 Projf(vec2, vec, ob->obmat[0]);
1377                                                 VecSubf(totmat[1], vec, vec2);
1378                                                 Normalise(totmat[1]);
1379
1380                                                 /* the x axis is fixed*/
1381                                                 totmat[0][0] = ob->obmat[0][0];
1382                                                 totmat[0][1] = ob->obmat[0][1];
1383                                                 totmat[0][2] = ob->obmat[0][2];
1384                                                 Normalise(totmat[0]);
1385                                 
1386                                                 /* the z axis gets mapped onto
1387                                                 a third orthogonal vector */
1388                                                 Crossf(totmat[2], totmat[0], totmat[1]);
1389                                                 }
1390                                                 break;
1391                                         case TRACK_Z: /* LOCK X TRACK Z */
1392                                                 {
1393                                                 /* Projection of Vector on the plane */
1394                                                 Projf(vec2, vec, ob->obmat[0]);
1395                                                 VecSubf(totmat[2], vec, vec2);
1396                                                 Normalise(totmat[2]);
1397
1398                                                 /* the x axis is fixed*/
1399                                                 totmat[0][0] = ob->obmat[0][0];
1400                                                 totmat[0][1] = ob->obmat[0][1];
1401                                                 totmat[0][2] = ob->obmat[0][2];
1402                                                 Normalise(totmat[0]);
1403                                 
1404                                                 /* the z axis gets mapped onto
1405                                                 a third orthogonal vector */
1406                                                 Crossf(totmat[1], totmat[2], totmat[0]);
1407                                                 }
1408                                                 break;
1409                                         case TRACK_nY: /* LOCK X TRACK -Y */
1410                                                 {
1411                                                 /* Projection of Vector on the plane */
1412                                                 Projf(vec2, vec, ob->obmat[0]);
1413                                                 VecSubf(totmat[1], vec, vec2);
1414                                                 Normalise(totmat[1]);
1415                                                 VecMulf(totmat[1],-1);
1416
1417                                                 /* the x axis is fixed*/
1418                                                 totmat[0][0] = ob->obmat[0][0];
1419                                                 totmat[0][1] = ob->obmat[0][1];
1420                                                 totmat[0][2] = ob->obmat[0][2];
1421                                                 Normalise(totmat[0]);
1422                                 
1423                                                 /* the z axis gets mapped onto
1424                                                 a third orthogonal vector */
1425                                                 Crossf(totmat[2], totmat[0], totmat[1]);
1426                                                 }
1427                                                 break;
1428                                         case TRACK_nZ: /* LOCK X TRACK -Z */
1429                                                 {
1430                                                 /* Projection of Vector on the plane */
1431                                                 Projf(vec2, vec, ob->obmat[0]);
1432                                                 VecSubf(totmat[2], vec, vec2);
1433                                                 Normalise(totmat[2]);
1434                                                 VecMulf(totmat[2],-1);
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                                         default:
1448                                                 {
1449                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1450                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1451                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1452                                                 }
1453                                                 break;
1454                                         }
1455                                         }
1456                                         break;
1457                                 case LOCK_Y: /* LOCK Y */
1458                                         {
1459                                         switch (data->trackflag){
1460                                         case TRACK_X: /* LOCK Y TRACK X */
1461                                                 {
1462                                                 /* Projection of Vector on the plane */
1463                                                 Projf(vec2, vec, ob->obmat[1]);
1464                                                 VecSubf(totmat[0], vec, vec2);
1465                                                 Normalise(totmat[0]);
1466
1467                                                 /* the y axis is fixed*/
1468                                                 totmat[1][0] = ob->obmat[1][0];
1469                                                 totmat[1][1] = ob->obmat[1][1];
1470                                                 totmat[1][2] = ob->obmat[1][2];
1471                                                 Normalise(totmat[1]);
1472                                                 
1473                                                 /* the z axis gets mapped onto
1474                                                 a third orthogonal vector */
1475                                                 Crossf(totmat[2], totmat[0], totmat[1]);
1476                                                 }
1477                                                 break;
1478                                         case TRACK_Z: /* LOCK Y TRACK Z */
1479                                                 {
1480                                                 /* Projection of Vector on the plane */
1481                                                 Projf(vec2, vec, ob->obmat[1]);
1482                                                 VecSubf(totmat[2], vec, vec2);
1483                                                 Normalise(totmat[2]);
1484
1485                                                 /* the y axis is fixed*/
1486                                                 totmat[1][0] = ob->obmat[1][0];
1487                                                 totmat[1][1] = ob->obmat[1][1];
1488                                                 totmat[1][2] = ob->obmat[1][2];
1489                                                 Normalise(totmat[1]);
1490                                                 
1491                                                 /* the z axis gets mapped onto
1492                                                 a third orthogonal vector */
1493                                                 Crossf(totmat[0], totmat[1], totmat[2]);
1494                                                 }
1495                                                 break;
1496                                         case TRACK_nX: /* LOCK Y TRACK -X */
1497                                                 {
1498                                                 /* Projection of Vector on the plane */
1499                                                 Projf(vec2, vec, ob->obmat[1]);
1500                                                 VecSubf(totmat[0], vec, vec2);
1501                                                 Normalise(totmat[0]);
1502                                                 VecMulf(totmat[0],-1);
1503
1504                                                 /* the y axis is fixed*/
1505                                                 totmat[1][0] = ob->obmat[1][0];
1506                                                 totmat[1][1] = ob->obmat[1][1];
1507                                                 totmat[1][2] = ob->obmat[1][2];
1508                                                 Normalise(totmat[1]);
1509                                                 
1510                                                 /* the z axis gets mapped onto
1511                                                 a third orthogonal vector */
1512                                                 Crossf(totmat[2], totmat[0], totmat[1]);
1513                                                 }
1514                                                 break;
1515                                         case TRACK_nZ: /* LOCK Y TRACK -Z */
1516                                                 {
1517                                                 /* Projection of Vector on the plane */
1518                                                 Projf(vec2, vec, ob->obmat[1]);
1519                                                 VecSubf(totmat[2], vec, vec2);
1520                                                 Normalise(totmat[2]);
1521                                                 VecMulf(totmat[2],-1);
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                                         default:
1535                                                 {
1536                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1537                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1538                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1539                                                 }
1540                                                 break;
1541                                         }
1542                                         }
1543                                         break;
1544                                 case LOCK_Z: /* LOCK Z */
1545                                         {
1546                                         switch (data->trackflag){
1547                                         case TRACK_X: /* LOCK Z TRACK X */
1548                                                 {
1549                                                 /* Projection of Vector on the plane */
1550                                                 Projf(vec2, vec, ob->obmat[2]);
1551                                                 VecSubf(totmat[0], vec, vec2);
1552                                                 Normalise(totmat[0]);
1553
1554                                                 /* the z axis is fixed*/
1555                                                 totmat[2][0] = ob->obmat[2][0];
1556                                                 totmat[2][1] = ob->obmat[2][1];
1557                                                 totmat[2][2] = ob->obmat[2][2];
1558                                                 Normalise(totmat[2]);
1559                                                 
1560                                                 /* the x axis gets mapped onto
1561                                                 a third orthogonal vector */
1562                                                 Crossf(totmat[1], totmat[2], totmat[0]);
1563                                                 }
1564                                                 break;
1565                                         case TRACK_Y: /* LOCK Z TRACK Y */
1566                                                 {
1567                                                 /* Projection of Vector on the plane */
1568                                                 Projf(vec2, vec, ob->obmat[2]);
1569                                                 VecSubf(totmat[1], vec, vec2);
1570                                                 Normalise(totmat[1]);
1571
1572                                                 /* the z axis is fixed*/
1573                                                 totmat[2][0] = ob->obmat[2][0];
1574                                                 totmat[2][1] = ob->obmat[2][1];
1575                                                 totmat[2][2] = ob->obmat[2][2];
1576                                                 Normalise(totmat[2]);
1577                                                 
1578                                                 /* the x axis gets mapped onto
1579                                                 a third orthogonal vector */
1580                                                 Crossf(totmat[0], totmat[1], totmat[2]);
1581                                                 }
1582                                                 break;
1583                                         case TRACK_nX: /* LOCK Z TRACK -X */
1584                                                 {
1585                                                 /* Projection of Vector on the plane */
1586                                                 Projf(vec2, vec, ob->obmat[2]);
1587                                                 VecSubf(totmat[0], vec, vec2);
1588                                                 Normalise(totmat[0]);
1589                                                 VecMulf(totmat[0],-1);
1590
1591                                                 /* the z axis is fixed*/
1592                                                 totmat[2][0] = ob->obmat[2][0];
1593                                                 totmat[2][1] = ob->obmat[2][1];
1594                                                 totmat[2][2] = ob->obmat[2][2];
1595                                                 Normalise(totmat[2]);
1596                                                 
1597                                                 /* the x axis gets mapped onto
1598                                                 a third orthogonal vector */
1599                                                 Crossf(totmat[1], totmat[2], totmat[0]);
1600                                                 }
1601                                                 break;
1602                                         case TRACK_nY: /* LOCK Z TRACK -Y */
1603                                                 {
1604                                                 /* Projection of Vector on the plane */
1605                                                 Projf(vec2, vec, ob->obmat[2]);
1606                                                 VecSubf(totmat[1], vec, vec2);
1607                                                 Normalise(totmat[1]);
1608                                                 VecMulf(totmat[1],-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                                         default:
1622                                                 {
1623                                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1624                                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1625                                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1626                                                 }
1627                                                 break;
1628                                         }
1629                                         }
1630                                         break;
1631                                 default:
1632                                         {
1633                                                 totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1634                                                 totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1635                                                 totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1636                                         }
1637                                         break;
1638                                 }
1639                                 /* Block to keep matrix heading */
1640                                 tmpmat[0][0] = ob->obmat[0][0];tmpmat[0][1] = ob->obmat[0][1];tmpmat[0][2] = ob->obmat[0][2];
1641                                 tmpmat[1][0] = ob->obmat[1][0];tmpmat[1][1] = ob->obmat[1][1];tmpmat[1][2] = ob->obmat[1][2];
1642                                 tmpmat[2][0] = ob->obmat[2][0];tmpmat[2][1] = ob->obmat[2][1];tmpmat[2][2] = ob->obmat[2][2];
1643                                 Normalise(tmpmat[0]);
1644                                 Normalise(tmpmat[1]);
1645                                 Normalise(tmpmat[2]);
1646                                 Mat3Inv(invmat,tmpmat);
1647                                 Mat3MulMat3(tmpmat,totmat,invmat);
1648                                 totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
1649                                 totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
1650                                 totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
1651
1652                                 Mat4CpyMat4(tmat, ob->obmat);
1653
1654                                 mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
1655                                                                 totmat[1][0],totmat[1][1],totmat[1][2],
1656                                                                 totmat[2][0],totmat[2][1],totmat[2][2]);
1657                                 if (mdet==0)
1658                                 {
1659                                         totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
1660                                         totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
1661                                         totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
1662                                 }
1663
1664                                 /* apply out transformaton to the object */
1665                                 Mat4MulMat34(ob->obmat, totmat, tmat);
1666                         }
1667                 }
1668                 break;
1669         case CONSTRAINT_TYPE_FOLLOWPATH:
1670                 {
1671                         bFollowPathConstraint *data;
1672                         float obmat[4][4];
1673
1674                         data=(bFollowPathConstraint*)constraint->data;                  
1675
1676                         if (data->tar) {
1677                                 // weird, this is needed? doesnt work for workob (ton)
1678                                 object_to_mat4(ob, obmat);
1679
1680                                 Mat4MulSerie(ob->obmat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1681                         }
1682                 }
1683                 break;
1684         case CONSTRAINT_TYPE_STRETCHTO:
1685         {
1686             bStretchToConstraint *data;
1687             float size[3],scale[3],vec[3],xx[3],zz[3],orth[3];
1688             float totmat[3][3];
1689             float tmat[4][4];
1690             float dist;
1691             data=(bStretchToConstraint*)constraint->data;            
1692             Mat4ToSize (ob->obmat, size);
1693
1694             
1695             if (data->tar){
1696                 
1697                 /* store X orientation before destroying obmat */
1698                 xx[0] = ob->obmat[0][0];
1699                 xx[1] = ob->obmat[0][1];
1700                 xx[2] = ob->obmat[0][2];
1701                 Normalise(xx);
1702
1703                 /* store Z orientation before destroying obmat */
1704                 zz[0] = ob->obmat[2][0];
1705                 zz[1] = ob->obmat[2][1];
1706                 zz[2] = ob->obmat[2][2];
1707                 Normalise(zz);
1708
1709                                 VecSubf(vec, ob->obmat[3], targetmat[3]);
1710                                 vec[0] /= size[0];
1711                                 vec[1] /= size[1];
1712                                 vec[2] /= size[2];
1713
1714                                 dist = Normalise(vec);
1715                 //dist = VecLenf( ob->obmat[3], targetmat[3]);
1716
1717                 if (data->orglength == 0)  data->orglength = dist;
1718                 if (data->bulge ==0) data->bulge = 1.0;
1719
1720                 scale[1] = dist/data->orglength;
1721                 switch (data->volmode){
1722                 /* volume preserving scaling */
1723                 case VOLUME_XZ :
1724                     scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
1725                     scale[2] = scale[0];
1726                     break;
1727                 case VOLUME_X:
1728                     scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
1729                     scale[2] = 1.0;
1730                     break;
1731                 case VOLUME_Z:
1732                     scale[0] = 1.0;
1733                     scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
1734                     break;
1735                     /* don't care for volume */
1736                 case NO_VOLUME:
1737                     scale[0] = 1.0;
1738                     scale[2] = 1.0;
1739                     break;
1740                 default: /* should not happen, but in case*/
1741                     return;    
1742                 } /* switch (data->volmode) */
1743
1744                 /* Clear the object's rotation and scale */
1745                 ob->obmat[0][0]=size[0]*scale[0];
1746                 ob->obmat[0][1]=0;
1747                 ob->obmat[0][2]=0;
1748                 ob->obmat[1][0]=0;
1749                 ob->obmat[1][1]=size[1]*scale[1];
1750                 ob->obmat[1][2]=0;
1751                 ob->obmat[2][0]=0;
1752                 ob->obmat[2][1]=0;
1753                 ob->obmat[2][2]=size[2]*scale[2];
1754                 
1755                 VecSubf(vec, ob->obmat[3], targetmat[3]);
1756                 Normalise(vec);
1757                 /* new Y aligns  object target connection*/
1758                 totmat[1][0] = -vec[0];
1759                 totmat[1][1] = -vec[1];
1760                 totmat[1][2] = -vec[2];
1761                 switch (data->plane){
1762                 case PLANE_X:
1763                     /* build new Z vector */
1764                     /* othogonal to "new Y" "old X! plane */
1765                     Crossf(orth, vec, xx);
1766                     Normalise(orth);
1767                     
1768                     /* new Z*/
1769                     totmat[2][0] = orth[0];
1770                     totmat[2][1] = orth[1];
1771                     totmat[2][2] = orth[2];
1772                     
1773                     /* we decided to keep X plane*/
1774                     Crossf(xx,orth, vec);
1775                     Normalise(xx);
1776                     totmat[0][0] = xx[0];
1777                     totmat[0][1] = xx[1];
1778                     totmat[0][2] = xx[2];
1779                     break;
1780                 case PLANE_Z:
1781                     /* build new X vector */
1782                     /* othogonal to "new Y" "old Z! plane */
1783                     Crossf(orth, vec, zz);
1784                     Normalise(orth);
1785                     
1786                     /* new X*/
1787                     totmat[0][0] = -orth[0];
1788                     totmat[0][1] = -orth[1];
1789                     totmat[0][2] = -orth[2];
1790                     
1791                     /* we decided to keep Z */
1792                     Crossf(zz,orth, vec);
1793                     Normalise(zz);
1794                     totmat[2][0] = zz[0];
1795                     totmat[2][1] = zz[1];
1796                     totmat[2][2] = zz[2];
1797                     break;
1798                 } /* switch (data->plane) */
1799                 
1800
1801                 Mat4CpyMat4(tmat, ob->obmat);
1802                 
1803                 Mat4MulMat34(ob->obmat, totmat, tmat);
1804
1805             }
1806         }
1807         break;
1808         case CONSTRAINT_TYPE_LOCLIMIT:
1809                 {
1810                         bLocLimitConstraint *data;
1811
1812                         data = constraint->data;
1813                         
1814                         /* limit location relative to origin or parent   */
1815                         if (data->flag2 & LIMIT_NOPARENT) {
1816                                 /* limiting relative to parent */
1817                                 float parmat[4][4]; /* matrix of parent */
1818                                 float objLoc[3], parLoc[3]; /* location of object, and location of parent */
1819                                 float relLoc[3]; /* objLoc  - parLoc*/
1820                                 
1821                                 /* get matrix of parent */
1822                                 Mat4CpyMat4(parmat, ob->parent->obmat);
1823                                 
1824                                 /* get locations as vectors */
1825                                 objLoc[0] = ob->obmat[3][0];
1826                                 objLoc[1] = ob->obmat[3][1];
1827                                 objLoc[2] = ob->obmat[3][2];
1828                                 
1829                                 parLoc[0] = parmat[3][0];
1830                                 parLoc[1] = parmat[3][1];
1831                                 parLoc[2] = parmat[3][2];
1832                                 
1833                                 /* get relative location of obj from parent */
1834                                 VecSubf(relLoc, objLoc, parLoc);
1835                                 
1836                                 /* limiting location */
1837                                 if (data->flag & LIMIT_XMIN) {
1838                                         if(relLoc[0] < data->xmin) 
1839                                                 ob->obmat[3][0] = (parLoc[0]+data->xmin);
1840                                 }
1841                                 if (data->flag & LIMIT_XMAX) {
1842                                         if (relLoc[0] > data->xmax) 
1843                                                 ob->obmat[3][0] = (parLoc[0]+data->xmax);
1844                                 }
1845                                 if (data->flag & LIMIT_YMIN) {
1846                                         if(relLoc[1] < data->ymin) 
1847                                                 ob->obmat[3][1] = (parLoc[1]+data->ymin);
1848                                 }
1849                                 if (data->flag & LIMIT_YMAX) {
1850                                         if (relLoc[1] > data->ymax) 
1851                                                 ob->obmat[3][1] = (parLoc[1]+data->ymax);
1852                                 }
1853                                 if (data->flag & LIMIT_ZMIN) {
1854                                         if(relLoc[2] < data->zmin) 
1855                                                 ob->obmat[3][2] = (parLoc[2]+data->zmin);
1856                                 }
1857                                 if (data->flag & LIMIT_ZMAX) {
1858                                         if (relLoc[2] > data->zmax) 
1859                                                 ob->obmat[3][2] = (parLoc[2]+data->zmax);
1860                                 }
1861                         } else {
1862                                 /* limiting relative to origin */
1863                                 if (data->flag & LIMIT_XMIN) {
1864                                         if(ob->obmat[3][0] < data->xmin)
1865                                                 ob->obmat[3][0] = data->xmin;
1866                                 }
1867                                 if (data->flag & LIMIT_XMAX) {
1868                                         if (ob->obmat[3][0] > data->xmax)
1869                                                 ob->obmat[3][0] = data->xmax;
1870                                 }
1871                                 if (data->flag & LIMIT_YMIN) {
1872                                         if(ob->obmat[3][1] < data->ymin)
1873                                                 ob->obmat[3][1] = data->ymin;
1874                                 }
1875                                 if (data->flag & LIMIT_YMAX) {
1876                                         if (ob->obmat[3][1] > data->ymax)
1877                                                 ob->obmat[3][1] = data->ymax;
1878                                 }
1879                                 if (data->flag & LIMIT_ZMIN) {
1880                                         if(ob->obmat[3][2] < data->zmin) 
1881                                                 ob->obmat[3][2] = data->zmin;
1882                                 }
1883                                 if (data->flag & LIMIT_ZMAX) {
1884                                         if (ob->obmat[3][2] > data->zmax)
1885                                                 ob->obmat[3][2] = data->zmax;
1886                                 }
1887                         }
1888                 }
1889                 break;
1890         case CONSTRAINT_TYPE_ROTLIMIT:
1891                 {
1892                         bRotLimitConstraint *data;
1893                         float tmat[3][3];
1894                         float eul[3];
1895                         float size[3];
1896                         
1897                         data = constraint->data;
1898                         
1899                         Mat4ToSize(ob->obmat, size);
1900                         
1901                         Mat3CpyMat4(tmat, ob->obmat);
1902                         Mat3Ortho(tmat); 
1903                         Mat3ToEul(tmat, eul);
1904                         
1905                         /* eulers: radians to degrees! */
1906                         eul[0] = (eul[0] / M_PI * 180);
1907                         eul[1] = (eul[1] / M_PI * 180);
1908                         eul[2] = (eul[2] / M_PI * 180);
1909                         
1910                         /* limiting of euler values... */
1911                         if (data->flag & LIMIT_XROT) {
1912                                 if (eul[0] < data->xmin) 
1913                                         eul[0] = data->xmin;
1914                                         
1915                                 if (eul[0] > data->xmax)
1916                                         eul[0] = data->xmax;
1917                         }
1918                         if (data->flag & LIMIT_YROT) {
1919                                 if (eul[1] < data->ymin)
1920                                         eul[1] = data->ymin;
1921                                         
1922                                 if (eul[1] > data->ymax)
1923                                         eul[1] = data->ymax;
1924                         }
1925                         if (data->flag & LIMIT_ZROT) {
1926                                 if (eul[2] < data->zmin)
1927                                         eul[2] = data->zmin;
1928                                         
1929                                 if (eul[2] > data->zmax)
1930                                         eul[2] = data->zmax;
1931                         }
1932                                 
1933                         /* eulers: degrees to radians ! */
1934                         eul[0] = (eul[0] / 180 * M_PI); 
1935                         eul[1] = (eul[1] / 180 * M_PI);
1936                         eul[2] = (eul[2] / 180 * M_PI);
1937                         
1938                         EulToMat3(eul, tmat);
1939                         
1940                         ob->obmat[0][0] = tmat[0][0]*size[0];
1941                         ob->obmat[0][1] = tmat[0][1]*size[1];
1942                         ob->obmat[0][2] = tmat[0][2]*size[2];
1943
1944                         ob->obmat[1][0] = tmat[1][0]*size[0];
1945                         ob->obmat[1][1] = tmat[1][1]*size[1];
1946                         ob->obmat[1][2] = tmat[1][2]*size[2];
1947
1948                         ob->obmat[2][0] = tmat[2][0]*size[0];
1949                         ob->obmat[2][1] = tmat[2][1]*size[1];
1950                         ob->obmat[2][2] = tmat[2][2]*size[2];
1951                 }
1952                 break;
1953         case CONSTRAINT_TYPE_SIZELIMIT:
1954                 {
1955                         bSizeLimitConstraint *data;
1956                         float obsize[3], size[3];
1957                         int clearNegScale=0;
1958                         
1959                         data = constraint->data;
1960                         
1961                         Mat4ToSize(ob->obmat, size);
1962                         Mat4ToSize(ob->obmat, obsize);
1963                         
1964                         if (data->flag & LIMIT_XMIN) {
1965                                 if (ob->transflag & OB_NEG_SCALE) {
1966                                         size[0] *= -1;
1967                                         
1968                                         if (size[0] < data->xmin) { 
1969                                                 size[0] = data->xmin;
1970                                                 clearNegScale += 1;
1971                                         }
1972                                 } else {
1973                                         if (size[0] < data->xmin) 
1974                                                 size[0] = data->xmin;   
1975                                 }       
1976                         }
1977                         if (data->flag & LIMIT_XMAX) {
1978                                 if (size[0] > data->xmax) 
1979                                         size[0] = data->xmax;
1980                         }
1981                         if (data->flag & LIMIT_YMIN) {
1982                                 if (ob->transflag & OB_NEG_SCALE) {
1983                                         size[1] *= -1;
1984                                         
1985                                         if (size[1] < data->ymin) { 
1986                                                 size[1] = data->ymin;
1987                                                 clearNegScale += 1;
1988                                         }
1989                                 } else {
1990                                         if (size[1] < data->ymin) 
1991                                                 size[1] = data->ymin;   
1992                                 }       
1993                         }
1994                         if (data->flag & LIMIT_YMAX) {
1995                                 if (size[1] > data->ymax) 
1996                                         size[1] = data->ymax;
1997                         }
1998                         if (data->flag & LIMIT_ZMIN) {
1999                                 if (ob->transflag & OB_NEG_SCALE) {
2000                                         size[2] *= -1;
2001                                         
2002                                         if (size[2] < data->zmin) { 
2003                                                 size[2] = data->zmin;
2004                                                 clearNegScale += 1;
2005                                         }
2006                                 } else {
2007                                         if (size[2] < data->zmin) 
2008                                                 size[2] = data->zmin;   
2009                                 }       
2010                         }
2011                         if (data->flag & LIMIT_ZMAX) {
2012                                 if (size[2] > data->zmax) 
2013                                         size[2] = data->zmax;
2014                         }
2015                         
2016                         if (clearNegScale != 0) {
2017                                 ob->transflag &= ~OB_NEG_SCALE;  /* is this how we remove that flag? */ 
2018                         }
2019                         
2020                         VecMulf(ob->obmat[0], size[0]/obsize[0]);
2021                         VecMulf(ob->obmat[1], size[1]/obsize[1]);
2022                         VecMulf(ob->obmat[2], size[2]/obsize[2]);
2023                 }
2024                 break;
2025         default:
2026                 printf ("Error: Unknown constraint type\n");
2027                 break;
2028         }
2029 }