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