Two wonderful new NLA & Armature editing features!
[blender.git] / source / blender / blenkernel / intern / lattice.c
1 /**
2  * lattice.c
3  *
4  *
5  * $Id$
6  *
7  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version. The Blender
13  * Foundation also sells licenses for use in proprietary software under
14  * the Blender License.  See http://www.blender.org/BL/ for information
15  * about this.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  *
26  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
27  * All rights reserved.
28  *
29  * The Original Code is: all of this file.
30  *
31  * Contributor(s): none yet.
32  *
33  * ***** END GPL/BL DUAL LICENSE BLOCK *****
34  */
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <math.h>
39 #include <stdlib.h>
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45
46 #include "DNA_armature_types.h"
47 #include "DNA_mesh_types.h"
48 #include "DNA_meshdata_types.h"
49 #include "DNA_modifier_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_lattice_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_key_types.h"
55
56 #include "BKE_anim.h"
57 #include "BKE_armature.h"
58 #include "BKE_curve.h"
59 #include "BKE_cdderivedmesh.h"
60 #include "BKE_DerivedMesh.h"
61 #include "BKE_deform.h"
62 #include "BKE_displist.h"
63 #include "BKE_global.h"
64 #include "BKE_key.h"
65 #include "BKE_lattice.h"
66 #include "BKE_library.h"
67 #include "BKE_main.h"
68 #include "BKE_mesh.h"
69 #include "BKE_modifier.h"
70 #include "BKE_object.h"
71 #include "BKE_screen.h"
72 #include "BKE_utildefines.h"
73
74 #include "BIF_editdeform.h"
75
76 #ifdef HAVE_CONFIG_H
77 #include <config.h>
78 #endif
79
80 #include "blendef.h"
81
82 Lattice *editLatt=0;
83 static Lattice *deformLatt=0;
84
85 static float *latticedata=0, latmat[4][4];
86
87 void calc_lat_fudu(int flag, int res, float *fu, float *du)
88 {
89         if(res==1) {
90                 *fu= 0.0;
91                 *du= 0.0;
92         }
93         else if(flag & LT_GRID) {
94                 *fu= -0.5f*(res-1);
95                 *du= 1.0f;
96         }
97         else {
98                 *fu= -1.0f;
99                 *du= 2.0f/(res-1);
100         }
101 }
102
103 void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
104 {
105         BPoint *bp;
106         int i, u, v, w;
107         float fu, fv, fw, uc, vc, wc, du=0.0, dv=0.0, dw=0.0;
108         float *co, (*vertexCos)[3] = NULL;
109         
110         /* vertex weight groups are just freed all for now */
111         if(lt->dvert) {
112                 free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
113                 lt->dvert= NULL;
114         }
115         
116         while(uNew*vNew*wNew > 32000) {
117                 if( uNew>=vNew && uNew>=wNew) uNew--;
118                 else if( vNew>=uNew && vNew>=wNew) vNew--;
119                 else wNew--;
120         }
121
122         vertexCos = MEM_mallocN(sizeof(*vertexCos)*uNew*vNew*wNew, "tmp_vcos");
123
124         calc_lat_fudu(lt->flag, uNew, &fu, &du);
125         calc_lat_fudu(lt->flag, vNew, &fv, &dv);
126         calc_lat_fudu(lt->flag, wNew, &fw, &dw);
127
128                 /* If old size is different then resolution changed in interface,
129                  * try to do clever reinit of points. Pretty simply idea, we just
130                  * deform new verts by old lattice, but scaling them to match old
131                  * size first.
132                  */
133         if (ltOb) {
134                 if (uNew!=1 && lt->pntsu!=1) {
135                         fu = lt->fu;
136                         du = (lt->pntsu-1)*lt->du/(uNew-1);
137                 }
138
139                 if (vNew!=1 && lt->pntsv!=1) {
140                         fv = lt->fv;
141                         dv = (lt->pntsv-1)*lt->dv/(vNew-1);
142                 }
143
144                 if (wNew!=1 && lt->pntsw!=1) {
145                         fw = lt->fw;
146                         dw = (lt->pntsw-1)*lt->dw/(wNew-1);
147                 }
148         }
149
150         co = vertexCos[0];
151         for(w=0,wc=fw; w<wNew; w++,wc+=dw) {
152                 for(v=0,vc=fv; v<vNew; v++,vc+=dv) {
153                         for(u=0,uc=fu; u<uNew; u++,co+=3,uc+=du) {
154                                 co[0] = uc;
155                                 co[1] = vc;
156                                 co[2] = wc;
157                         }
158                 }
159         }
160         
161         if (ltOb) {
162                 float mat[4][4];
163                 int typeu = lt->typeu, typev = lt->typev, typew = lt->typew;
164
165                         /* works best if we force to linear type (endpoints match) */
166                 lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
167
168                         /* prevent using deformed locations */
169                 freedisplist(&ltOb->disp);
170
171                 Mat4CpyMat4(mat, ltOb->obmat);
172                 Mat4One(ltOb->obmat);
173                 lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew*vNew*wNew, NULL);
174                 Mat4CpyMat4(ltOb->obmat, mat);
175
176                 lt->typeu = typeu;
177                 lt->typev = typev;
178                 lt->typew = typew;
179         }
180
181         lt->fu = fu;
182         lt->fv = fv;
183         lt->fw = fw;
184         lt->du = du;
185         lt->dv = dv;
186         lt->dw = dw;
187
188         lt->pntsu = uNew;
189         lt->pntsv = vNew;
190         lt->pntsw = wNew;
191
192         MEM_freeN(lt->def);
193         lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
194         
195         bp= lt->def;
196         
197         for (i=0; i<lt->pntsu*lt->pntsv*lt->pntsw; i++,bp++) {
198                 VECCOPY(bp->vec, vertexCos[i]);
199         }
200
201         MEM_freeN(vertexCos);
202 }
203
204 Lattice *add_lattice()
205 {
206         Lattice *lt;
207         
208         lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
209         
210         lt->flag= LT_GRID;
211         
212         lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
213         
214         lt->def= MEM_callocN(sizeof(BPoint), "lattvert"); /* temporary */
215         resizelattice(lt, 2, 2, 2, NULL);       /* creates a uniform lattice */
216                 
217         return lt;
218 }
219
220 Lattice *copy_lattice(Lattice *lt)
221 {
222         Lattice *ltn;
223
224         ltn= copy_libblock(lt);
225         ltn->def= MEM_dupallocN(lt->def);
226                 
227         id_us_plus((ID *)ltn->ipo);
228
229         ltn->key= copy_key(ltn->key);
230         if(ltn->key) ltn->key->from= (ID *)ltn;
231         
232         if(lt->dvert) {
233                 int tot= lt->pntsu*lt->pntsv*lt->pntsw;
234                 ltn->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
235                 copy_dverts(ltn->dvert, lt->dvert, tot);
236         }
237         
238         return ltn;
239 }
240
241 void free_lattice(Lattice *lt)
242 {
243         if(lt->def) MEM_freeN(lt->def);
244         if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
245 }
246
247
248 void make_local_lattice(Lattice *lt)
249 {
250         Object *ob;
251         Lattice *ltn;
252         int local=0, lib=0;
253
254         /* - only lib users: do nothing
255          * - only local users: set flag
256          * - mixed: make copy
257          */
258         
259         if(lt->id.lib==0) return;
260         if(lt->id.us==1) {
261                 lt->id.lib= 0;
262                 lt->id.flag= LIB_LOCAL;
263                 new_id(0, (ID *)lt, 0);
264                 return;
265         }
266         
267         ob= G.main->object.first;
268         while(ob) {
269                 if(ob->data==lt) {
270                         if(ob->id.lib) lib= 1;
271                         else local= 1;
272                 }
273                 ob= ob->id.next;
274         }
275         
276         if(local && lib==0) {
277                 lt->id.lib= 0;
278                 lt->id.flag= LIB_LOCAL;
279                 new_id(0, (ID *)lt, 0);
280         }
281         else if(local && lib) {
282                 ltn= copy_lattice(lt);
283                 ltn->id.us= 0;
284                 
285                 ob= G.main->object.first;
286                 while(ob) {
287                         if(ob->data==lt) {
288                                 
289                                 if(ob->id.lib==0) {
290                                         ob->data= ltn;
291                                         ltn->id.us++;
292                                         lt->id.us--;
293                                 }
294                         }
295                         ob= ob->id.next;
296                 }
297         }
298 }
299
300 void init_latt_deform(Object *oblatt, Object *ob)
301 {
302                 /* we make an array with all differences */
303         Lattice *lt = deformLatt = (oblatt==G.obedit)?editLatt:oblatt->data;
304         BPoint *bp = lt->def;
305         DispList *dl = find_displist(&oblatt->disp, DL_VERTS);
306         float *co = dl?dl->verts:NULL;
307         float *fp, imat[4][4];
308         float fu, fv, fw;
309         int u, v, w;
310
311         fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
312         
313                 /* for example with a particle system: ob==0 */
314         if(ob==0) {
315                 /* in deformspace, calc matrix  */
316                 Mat4Invert(latmat, oblatt->obmat);
317         
318                 /* back: put in deform array */
319                 Mat4Invert(imat, latmat);
320         }
321         else {
322                 /* in deformspace, calc matrix */
323                 Mat4Invert(imat, oblatt->obmat);
324                 Mat4MulMat4(latmat, ob->obmat, imat);
325         
326                 /* back: put in deform array */
327                 Mat4Invert(imat, latmat);
328         }
329         
330         for(w=0,fw=lt->fw; w<lt->pntsw; w++,fw+=lt->dw) {
331                 for(v=0,fv=lt->fv; v<lt->pntsv; v++, fv+=lt->dv) {
332                         for(u=0,fu=lt->fu; u<lt->pntsu; u++, bp++, co+=3, fp+=3, fu+=lt->du) {
333                                 if (dl) {
334                                         fp[0] = co[0] - fu;
335                                         fp[1] = co[1] - fv;
336                                         fp[2] = co[2] - fw;
337                                 } else {
338                                         fp[0] = bp->vec[0] - fu;
339                                         fp[1] = bp->vec[1] - fv;
340                                         fp[2] = bp->vec[2] - fw;
341                                 }
342
343                                 Mat4Mul3Vecfl(imat, fp);
344                         }
345                 }
346         }
347 }
348
349 void calc_latt_deform(float *co, float weight)
350 {
351         Lattice *lt;
352         float u, v, w, tu[4], tv[4], tw[4];
353         float *fpw, *fpv, *fpu, vec[3];
354         int ui, vi, wi, uu, vv, ww;
355         
356         if(latticedata==0) return;
357         
358         lt= deformLatt; /* just for shorter notation! */
359         
360         /* co is in local coords, treat with latmat */
361         
362         VECCOPY(vec, co);
363         Mat4MulVecfl(latmat, vec);
364         
365         /* u v w coords */
366         
367         if(lt->pntsu>1) {
368                 u= (vec[0]-lt->fu)/lt->du;
369                 ui= (int)floor(u);
370                 u -= ui;
371                 set_four_ipo(u, tu, lt->typeu);
372         }
373         else {
374                 tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
375                 ui= 0;
376         }
377         
378         if(lt->pntsv>1) {
379                 v= (vec[1]-lt->fv)/lt->dv;
380                 vi= (int)floor(v);
381                 v -= vi;
382                 set_four_ipo(v, tv, lt->typev);
383         }
384         else {
385                 tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
386                 vi= 0;
387         }
388         
389         if(lt->pntsw>1) {
390                 w= (vec[2]-lt->fw)/lt->dw;
391                 wi= (int)floor(w);
392                 w -= wi;
393                 set_four_ipo(w, tw, lt->typew);
394         }
395         else {
396                 tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
397                 wi= 0;
398         }
399         
400         for(ww= wi-1; ww<=wi+2; ww++) {
401                 w= tw[ww-wi+1];
402                 
403                 if(w!=0.0) {
404                         if(ww>0) {
405                                 if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
406                                 else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
407                         }
408                         else fpw= latticedata;
409                         
410                         for(vv= vi-1; vv<=vi+2; vv++) {
411                                 v= w*tv[vv-vi+1];
412                                 
413                                 if(v!=0.0) {
414                                         if(vv>0) {
415                                                 if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
416                                                 else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
417                                         }
418                                         else fpv= fpw;
419                                         
420                                         for(uu= ui-1; uu<=ui+2; uu++) {
421                                                 u= weight*v*tu[uu-ui+1];
422                                                 
423                                                 if(u!=0.0) {
424                                                         if(uu>0) {
425                                                                 if(uu<lt->pntsu) fpu= fpv + 3*uu;
426                                                                 else fpu= fpv + 3*(lt->pntsu-1);
427                                                         }
428                                                         else fpu= fpv;
429                                                         
430                                                         co[0]+= u*fpu[0];
431                                                         co[1]+= u*fpu[1];
432                                                         co[2]+= u*fpu[2];
433                                                 }
434                                         }
435                                 }
436                         }
437                 }
438         }
439 }
440
441 void end_latt_deform()
442 {
443
444         MEM_freeN(latticedata);
445         latticedata= 0;
446 }
447
448         /* calculations is in local space of deformed object
449            so we store in latmat transform from path coord inside object 
450          */
451 typedef struct {
452         float dmin[3], dmax[3], dsize, dloc[3];
453         float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
454         int no_rot_axis;
455 } CurveDeform;
456
457 static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc)
458 {
459         Mat4Invert(ob->imat, ob->obmat);
460         Mat4MulMat4(cd->objectspace, par->obmat, ob->imat);
461         Mat4Invert(cd->curvespace, cd->objectspace);
462         Mat3CpyMat4(cd->objectspace3, cd->objectspace);
463         
464         // offset vector for 'no smear'
465         if(dloc) {
466                 Mat4Invert(par->imat, par->obmat);
467                 VecMat4MulVecfl(cd->dloc, par->imat, ob->obmat[3]);
468         }
469         else cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f;
470         
471         cd->no_rot_axis= 0;
472 }
473
474 /* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
475 static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir)        /* returns OK */
476 {
477         Curve *cu= ob->data;
478         BevList *bl;
479         float ctime1;
480         int cycl=0;
481         
482         /* test for cyclic */
483         bl= cu->bev.first;
484         if(bl && bl->poly> -1) cycl= 1;
485
486         if(cycl==0) {
487                 ctime1= CLAMPIS(ctime, 0.0, 1.0);
488         }
489         else ctime1= ctime;
490         
491         /* vec needs 4 items */
492         if(where_on_path(ob, ctime1, vec, dir)) {
493                 
494                 if(cycl==0) {
495                         Path *path= cu->path;
496                         float dvec[3];
497                         
498                         if(ctime < 0.0) {
499                                 VecSubf(dvec, path->data+4, path->data);
500                                 VecMulf(dvec, ctime*(float)path->len);
501                                 VECADD(vec, vec, dvec);
502                         }
503                         else if(ctime > 1.0) {
504                                 VecSubf(dvec, path->data+4*path->len-4, path->data+4*path->len-8);
505                                 VecMulf(dvec, (ctime-1.0)*(float)path->len);
506                                 VECADD(vec, vec, dvec);
507                         }
508                 }
509                 return 1;
510         }
511         return 0;
512 }
513
514         /* for each point, rotate & translate to curve */
515         /* use path, since it has constant distances */
516         /* co: local coord, result local too */
517         /* returns quaternion for rotation, using cd->no_rot_axis */
518         /* axis is using another define!!! */
519 static float *calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd)
520 {
521         Curve *cu= par->data;
522         float fac, loc[4], dir[3], cent[3];
523         short upflag, index;
524         
525         if(axis==MOD_CURVE_POSX || axis==MOD_CURVE_NEGX) {
526                 upflag= OB_POSZ;
527                 cent[0]= 0.0;
528                 cent[1]= co[1];
529                 cent[2]= co[2];
530                 index= 0;
531         }
532         else if(axis==MOD_CURVE_POSY || axis==MOD_CURVE_NEGY) {
533                 upflag= OB_POSZ;
534                 cent[0]= co[0];
535                 cent[1]= 0.0;
536                 cent[2]= co[2];
537                 index= 1;
538         }
539         else {
540                 upflag= OB_POSY;
541                 cent[0]= co[0];
542                 cent[1]= co[1];
543                 cent[2]= 0.0;
544                 index= 2;
545         }
546         /* to be sure, mostly after file load */
547         if(cu->path==NULL) {
548                 makeDispListCurveTypes(par, 0);
549                 if(cu->path==NULL) return NULL; // happens on append...
550         }
551         
552         /* options */
553         if(ELEM3(axis, OB_NEGX, OB_NEGY, OB_NEGZ)) {
554                 if(cu->flag & CU_STRETCH)
555                         fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]);
556                 else
557                         fac= (cd->dloc[index])/(cu->path->totdist) - (co[index]-cd->dmax[index])/(cu->path->totdist);
558         }
559         else {
560                 if(cu->flag & CU_STRETCH)
561                         fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
562                 else
563                         fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
564         }
565         
566         
567         if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */
568                 float q[4], mat[3][3];
569                 float *quat;
570                 
571                 if(cd->no_rot_axis)     /* set by caller */
572                         dir[cd->no_rot_axis-1]= 0.0f;
573                 
574                 /* -1 for compatibility with old track defines */
575                 quat= vectoquat(dir, axis-1, upflag);   /* gives static quat */
576                 
577                 /* the tilt */
578                 if(loc[3]!=0.0) {
579                         Normalise(dir);
580                         q[0]= (float)cos(0.5*loc[3]);
581                         fac= (float)sin(0.5*loc[3]);
582                         q[1]= -fac*dir[0];
583                         q[2]= -fac*dir[1];
584                         q[3]= -fac*dir[2];
585                         QuatMul(quat, q, quat);
586                 }               
587                 QuatToMat3(quat, mat);
588         
589                 /* local rotation */
590                 Mat3MulVecfl(mat, cent);
591                 
592                 /* translation */
593                 VECADD(co, cent, loc);
594                 
595                 return quat;
596         }
597         return NULL;
598 }
599
600 void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup, short defaxis)
601 {
602         Curve *cu = cuOb->data;
603         int a, flag = cu->flag;
604         CurveDeform cd;
605         int use_vgroups;
606         
607         cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
608
609         init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0);
610                 
611         /* check whether to use vertex groups (only possible if target is a Mesh)
612          * we want either a Mesh with no derived data, or derived data with
613          * deformverts
614          */
615         if(target && target->type==OB_MESH) {
616                 /* if there's derived data without deformverts, don't use vgroups */
617                 if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
618                         use_vgroups = 0;
619                 else
620                         use_vgroups = 1;
621         } else
622                 use_vgroups = 0;
623         
624         if(vgroup && vgroup[0] && use_vgroups) {
625                 bDeformGroup *curdef;
626                 Mesh *me= target->data;
627                 int index;
628                 
629                 /* find the group (weak loop-in-loop) */
630                 for(index = 0, curdef = target->defbase.first; curdef;
631                     curdef = curdef->next, index++)
632                         if (!strcmp(curdef->name, vgroup))
633                                 break;
634
635                 if(curdef && (me->dvert || dm)) {
636                         MDeformVert *dvert = me->dvert;
637                         float vec[3];
638                         int j;
639
640                         INIT_MINMAX(cd.dmin, cd.dmax);
641
642                         for(a = 0; a < numVerts; a++, dvert++) {
643                                 if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
644
645                                 for(j = 0; j < dvert->totweight; j++) {
646                                         if(dvert->dw[j].def_nr == index) {
647                                                 Mat4MulVecfl(cd.curvespace, vertexCos[a]);
648                                                 DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
649                                                 break;
650                                         }
651                                 }
652                         }
653
654                         dvert = me->dvert;
655                         for(a = 0; a < numVerts; a++, dvert++) {
656                                 if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
657
658                                 for(j = 0; j < dvert->totweight; j++) {
659                                         if(dvert->dw[j].def_nr == index) {
660                                                 VECCOPY(vec, vertexCos[a]);
661                                                 calc_curve_deform(cuOb, vec, defaxis, &cd);
662                                                 VecLerpf(vertexCos[a], vertexCos[a], vec,
663                                                          dvert->dw[j].weight);
664                                                 Mat4MulVecfl(cd.objectspace, vertexCos[a]);
665                                                 break;
666                                         }
667                                 }
668                         }
669                 }
670         } else {
671                 INIT_MINMAX(cd.dmin, cd.dmax);
672                         
673                 for(a = 0; a < numVerts; a++) {
674                         Mat4MulVecfl(cd.curvespace, vertexCos[a]);
675                         DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
676                 }
677
678                 for(a = 0; a < numVerts; a++) {
679                         calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd);
680                         Mat4MulVecfl(cd.objectspace, vertexCos[a]);
681                 }
682         }
683         cu->flag = flag;
684 }
685
686 /* input vec and orco = local coord in armature space */
687 /* orco is original not-animated or deformed reference point */
688 /* result written in vec and mat */
689 void curve_deform_vector(Object *cuOb, Object *target, float *orco, float *vec, float mat[][3], int no_rot_axis)
690 {
691         CurveDeform cd;
692         float *quat;
693         
694         init_curve_deform(cuOb, target, &cd, 0);        /* 0 no dloc */
695         cd.no_rot_axis= no_rot_axis;                            /* option to only rotate for XY, for example */
696         
697         VECCOPY(cd.dmin, orco);
698         VECCOPY(cd.dmax, orco);
699
700         Mat4MulVecfl(cd.curvespace, vec);
701         
702         quat= calc_curve_deform(cuOb, vec, target->trackflag+1, &cd);
703         if(quat) {
704                 float qmat[3][3];
705                 
706                 QuatToMat3(quat, qmat);
707                 Mat3MulMat3(mat, qmat, cd.objectspace3);
708         }
709         else
710                 Mat3One(mat);
711         
712         Mat4MulVecfl(cd.objectspace, vec);
713
714 }
715
716 void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
717                           float (*vertexCos)[3], int numVerts, char *vgroup)
718 {
719         int a;
720         int use_vgroups;
721
722         init_latt_deform(laOb, target);
723
724         /* check whether to use vertex groups (only possible if target is a Mesh)
725          * we want either a Mesh with no derived data, or derived data with
726          * deformverts
727          */
728         if(target && target->type==OB_MESH) {
729                 /* if there's derived data without deformverts, don't use vgroups */
730                 if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
731                         use_vgroups = 0;
732                 else
733                         use_vgroups = 1;
734         } else
735                 use_vgroups = 0;
736         
737         if(vgroup && vgroup[0] && use_vgroups) {
738                 bDeformGroup *curdef;
739                 Mesh *me = target->data;
740                 int index = 0;
741                 
742                 /* find the group (weak loop-in-loop) */
743                 for(curdef = target->defbase.first; curdef;
744                     curdef = curdef->next, index++)
745                         if(!strcmp(curdef->name, vgroup)) break;
746
747                 if(curdef && (me->dvert || dm)) {
748                         MDeformVert *dvert = me->dvert;
749                         int j;
750                         
751                         for(a = 0; a < numVerts; a++, dvert++) {
752                                 if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
753                                 for(j = 0; j < dvert->totweight; j++) {
754                                         if (dvert->dw[j].def_nr == index) {
755                                                 calc_latt_deform(vertexCos[a], dvert->dw[j].weight);
756                                         }
757                                 }
758                         }
759                 }
760         } else {
761                 for(a = 0; a < numVerts; a++) {
762                         calc_latt_deform(vertexCos[a], 1.0f);
763                 }
764         }
765         end_latt_deform();
766 }
767
768 int object_deform_mball(Object *ob)
769 {
770         if(ob->parent && ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
771                 DispList *dl;
772
773                 for (dl=ob->disp.first; dl; dl=dl->next) {
774                         lattice_deform_verts(ob->parent, ob, NULL,
775                                              (float(*)[3]) dl->verts, dl->nr, NULL);
776                 }
777
778                 return 1;
779         } else {
780                 return 0;
781         }
782 }
783
784 static BPoint *latt_bp(Lattice *lt, int u, int v, int w)
785 {
786         return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
787 }
788
789 void outside_lattice(Lattice *lt)
790 {
791         BPoint *bp, *bp1, *bp2;
792         int u, v, w;
793         float fac1, du=0.0, dv=0.0, dw=0.0;
794
795         bp= lt->def;
796
797         if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
798         if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
799         if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
800                 
801         for(w=0; w<lt->pntsw; w++) {
802                 
803                 for(v=0; v<lt->pntsv; v++) {
804                 
805                         for(u=0; u<lt->pntsu; u++, bp++) {
806                                 if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
807                                 else {
808                                 
809                                         bp->hide= 1;
810                                         bp->f1 &= ~SELECT;
811                                         
812                                         /* u extrema */
813                                         bp1= latt_bp(lt, 0, v, w);
814                                         bp2= latt_bp(lt, lt->pntsu-1, v, w);
815                                         
816                                         fac1= du*u;
817                                         bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
818                                         bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
819                                         bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
820                                         
821                                         /* v extrema */
822                                         bp1= latt_bp(lt, u, 0, w);
823                                         bp2= latt_bp(lt, u, lt->pntsv-1, w);
824                                         
825                                         fac1= dv*v;
826                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
827                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
828                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
829                                         
830                                         /* w extrema */
831                                         bp1= latt_bp(lt, u, v, 0);
832                                         bp2= latt_bp(lt, u, v, lt->pntsw-1);
833                                         
834                                         fac1= dw*w;
835                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
836                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
837                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
838                                         
839                                         VecMulf(bp->vec, 0.3333333f);
840                                         
841                                 }
842                         }
843                         
844                 }
845                 
846         }
847         
848 }
849
850 float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3]
851 {
852         Lattice *lt = (G.obedit==ob)?editLatt:ob->data;
853         int i, numVerts = *numVerts_r = lt->pntsu*lt->pntsv*lt->pntsw;
854         float (*vertexCos)[3] = MEM_mallocN(sizeof(*vertexCos)*numVerts,"lt_vcos");
855
856         for (i=0; i<numVerts; i++) {
857                 VECCOPY(vertexCos[i], lt->def[i].vec);
858         }
859
860         return vertexCos;
861 }
862
863 void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3])
864 {
865         Lattice *lt = ob->data;
866         int i, numVerts = lt->pntsu*lt->pntsv*lt->pntsw;
867
868         for (i=0; i<numVerts; i++) {
869                 VECCOPY(lt->def[i].vec, vertexCos[i]);
870         }
871 }
872
873 void lattice_calc_modifiers(Object *ob)
874 {
875         float (*vertexCos)[3] = NULL;
876         ModifierData *md = modifiers_getVirtualModifierList(ob);
877         int numVerts, editmode = G.obedit==ob;
878
879         freedisplist(&ob->disp);
880
881         if (!editmode) {
882                 do_ob_key(ob);
883         }
884
885         for (; md; md=md->next) {
886                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
887
888                 if (!(md->mode&eModifierMode_Realtime)) continue;
889                 if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
890                 if (mti->isDisabled && mti->isDisabled(md)) continue;
891                 if (mti->type!=eModifierTypeType_OnlyDeform) continue;
892
893                 if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts);
894                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
895         }
896
897         if (vertexCos) {
898                 DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl");
899                 dl->type = DL_VERTS;
900                 dl->parts = 1;
901                 dl->nr = numVerts;
902                 dl->verts = (float*) vertexCos;
903                 
904                 BLI_addtail(&ob->disp, dl);
905         }
906 }