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