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