Integration of the Google Summer of Code Modifier Stack Upgrade project. The
[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_modifier.h"
69 #include "BKE_object.h"
70 #include "BKE_screen.h"
71 #include "BKE_utildefines.h"
72
73 #include "BIF_editdeform.h"
74
75 #ifdef HAVE_CONFIG_H
76 #include <config.h>
77 #endif
78
79 #include "blendef.h"
80
81 Lattice *editLatt=0;
82 static Lattice *deformLatt=0;
83
84 static float *latticedata=0, latmat[4][4];
85
86 void calc_lat_fudu(int flag, int res, float *fu, float *du)
87 {
88         if(res==1) {
89                 *fu= 0.0;
90                 *du= 0.0;
91         }
92         else if(flag & LT_GRID) {
93                 *fu= -0.5f*(res-1);
94                 *du= 1.0f;
95         }
96         else {
97                 *fu= -1.0f;
98                 *du= 2.0f/(res-1);
99         }
100 }
101
102 void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
103 {
104         BPoint *bp;
105         int i, u, v, w;
106         float fu, fv, fw, uc, vc, wc, du=0.0, dv=0.0, dw=0.0;
107         float *co, (*vertexCos)[3] = NULL;
108         
109         while(uNew*vNew*wNew > 32000) {
110                 if( uNew>=vNew && uNew>=wNew) uNew--;
111                 else if( vNew>=uNew && vNew>=wNew) vNew--;
112                 else wNew--;
113         }
114
115         vertexCos = MEM_mallocN(sizeof(*vertexCos)*uNew*vNew*wNew, "tmp_vcos");
116
117         calc_lat_fudu(lt->flag, uNew, &fu, &du);
118         calc_lat_fudu(lt->flag, vNew, &fv, &dv);
119         calc_lat_fudu(lt->flag, wNew, &fw, &dw);
120
121                 /* If old size is different then resolution changed in interface,
122                  * try to do clever reinit of points. Pretty simply idea, we just
123                  * deform new verts by old lattice, but scaling them to match old
124                  * size first.
125                  */
126         if (ltOb) {
127                 if (uNew!=1 && lt->pntsu!=1) {
128                         fu = lt->fu;
129                         du = (lt->pntsu-1)*lt->du/(uNew-1);
130                 }
131
132                 if (vNew!=1 && lt->pntsv!=1) {
133                         fv = lt->fv;
134                         dv = (lt->pntsv-1)*lt->dv/(vNew-1);
135                 }
136
137                 if (wNew!=1 && lt->pntsw!=1) {
138                         fw = lt->fw;
139                         dw = (lt->pntsw-1)*lt->dw/(wNew-1);
140                 }
141         }
142
143         co = vertexCos[0];
144         for(w=0,wc=fw; w<wNew; w++,wc+=dw) {
145                 for(v=0,vc=fv; v<vNew; v++,vc+=dv) {
146                         for(u=0,uc=fu; u<uNew; u++,co+=3,uc+=du) {
147                                 co[0] = uc;
148                                 co[1] = vc;
149                                 co[2] = wc;
150                         }
151                 }
152         }
153         
154         if (ltOb) {
155                 float mat[4][4];
156                 int typeu = lt->typeu, typev = lt->typev, typew = lt->typew;
157
158                         /* works best if we force to linear type (endpoints match) */
159                 lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
160
161                         /* prevent using deformed locations */
162                 freedisplist(&ltOb->disp);
163
164                 Mat4CpyMat4(mat, ltOb->obmat);
165                 Mat4One(ltOb->obmat);
166                 lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew*vNew*wNew, NULL);
167                 Mat4CpyMat4(ltOb->obmat, mat);
168
169                 lt->typeu = typeu;
170                 lt->typev = typev;
171                 lt->typew = typew;
172         }
173
174         lt->fu = fu;
175         lt->fv = fv;
176         lt->fw = fw;
177         lt->du = du;
178         lt->dv = dv;
179         lt->dw = dw;
180
181         lt->pntsu = uNew;
182         lt->pntsv = vNew;
183         lt->pntsw = wNew;
184
185         MEM_freeN(lt->def);
186         lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
187         
188         bp= lt->def;
189         
190         for (i=0; i<lt->pntsu*lt->pntsv*lt->pntsw; i++,bp++) {
191                 VECCOPY(bp->vec, vertexCos[i]);
192         }
193
194         MEM_freeN(vertexCos);
195 }
196
197 Lattice *add_lattice()
198 {
199         Lattice *lt;
200         
201         lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
202         
203         lt->flag= LT_GRID;
204         
205         lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
206         
207         lt->def= MEM_callocN(sizeof(BPoint), "lattvert"); /* temporary */
208         resizelattice(lt, 2, 2, 2, NULL);       /* creates a uniform lattice */
209                 
210         return lt;
211 }
212
213 Lattice *copy_lattice(Lattice *lt)
214 {
215         Lattice *ltn;
216
217         ltn= copy_libblock(lt);
218         ltn->def= MEM_dupallocN(lt->def);
219                 
220         id_us_plus((ID *)ltn->ipo);
221
222         ltn->key= copy_key(ltn->key);
223         if(ltn->key) ltn->key->from= (ID *)ltn;
224         
225         return ltn;
226 }
227
228 void free_lattice(Lattice *lt)
229 {
230         if(lt->def) MEM_freeN(lt->def);
231 }
232
233
234 void make_local_lattice(Lattice *lt)
235 {
236         Object *ob;
237         Lattice *ltn;
238         int local=0, lib=0;
239
240         /* - only lib users: do nothing
241          * - only local users: set flag
242          * - mixed: make copy
243          */
244         
245         if(lt->id.lib==0) return;
246         if(lt->id.us==1) {
247                 lt->id.lib= 0;
248                 lt->id.flag= LIB_LOCAL;
249                 new_id(0, (ID *)lt, 0);
250                 return;
251         }
252         
253         ob= G.main->object.first;
254         while(ob) {
255                 if(ob->data==lt) {
256                         if(ob->id.lib) lib= 1;
257                         else local= 1;
258                 }
259                 ob= ob->id.next;
260         }
261         
262         if(local && lib==0) {
263                 lt->id.lib= 0;
264                 lt->id.flag= LIB_LOCAL;
265                 new_id(0, (ID *)lt, 0);
266         }
267         else if(local && lib) {
268                 ltn= copy_lattice(lt);
269                 ltn->id.us= 0;
270                 
271                 ob= G.main->object.first;
272                 while(ob) {
273                         if(ob->data==lt) {
274                                 
275                                 if(ob->id.lib==0) {
276                                         ob->data= ltn;
277                                         ltn->id.us++;
278                                         lt->id.us--;
279                                 }
280                         }
281                         ob= ob->id.next;
282                 }
283         }
284 }
285
286 void init_latt_deform(Object *oblatt, Object *ob)
287 {
288                 /* we make an array with all differences */
289         Lattice *lt = deformLatt = (oblatt==G.obedit)?editLatt:oblatt->data;
290         BPoint *bp = lt->def;
291         DispList *dl = find_displist(&oblatt->disp, DL_VERTS);
292         float *co = dl?dl->verts:NULL;
293         float *fp, imat[4][4];
294         float fu, fv, fw;
295         int u, v, w;
296
297         fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
298         
299                 /* for example with a particle system: ob==0 */
300         if(ob==0) {
301                 /* in deformspace, calc matrix  */
302                 Mat4Invert(latmat, oblatt->obmat);
303         
304                 /* back: put in deform array */
305                 Mat4Invert(imat, latmat);
306         }
307         else {
308                 /* in deformspace, calc matrix */
309                 Mat4Invert(imat, oblatt->obmat);
310                 Mat4MulMat4(latmat, ob->obmat, imat);
311         
312                 /* back: put in deform array */
313                 Mat4Invert(imat, latmat);
314         }
315         
316         for(w=0,fw=lt->fw; w<lt->pntsw; w++,fw+=lt->dw) {
317                 for(v=0,fv=lt->fv; v<lt->pntsv; v++, fv+=lt->dv) {
318                         for(u=0,fu=lt->fu; u<lt->pntsu; u++, bp++, co+=3, fp+=3, fu+=lt->du) {
319                                 if (dl) {
320                                         fp[0] = co[0] - fu;
321                                         fp[1] = co[1] - fv;
322                                         fp[2] = co[2] - fw;
323                                 } else {
324                                         fp[0] = bp->vec[0] - fu;
325                                         fp[1] = bp->vec[1] - fv;
326                                         fp[2] = bp->vec[2] - fw;
327                                 }
328
329                                 Mat4Mul3Vecfl(imat, fp);
330                         }
331                 }
332         }
333 }
334
335 void calc_latt_deform(float *co, float weight)
336 {
337         Lattice *lt;
338         float u, v, w, tu[4], tv[4], tw[4];
339         float *fpw, *fpv, *fpu, vec[3];
340         int ui, vi, wi, uu, vv, ww;
341         
342         if(latticedata==0) return;
343         
344         lt= deformLatt; /* just for shorter notation! */
345         
346         /* co is in local coords, treat with latmat */
347         
348         VECCOPY(vec, co);
349         Mat4MulVecfl(latmat, vec);
350         
351         /* u v w coords */
352         
353         if(lt->pntsu>1) {
354                 u= (vec[0]-lt->fu)/lt->du;
355                 ui= (int)floor(u);
356                 u -= ui;
357                 set_four_ipo(u, tu, lt->typeu);
358         }
359         else {
360                 tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
361                 ui= 0;
362         }
363         
364         if(lt->pntsv>1) {
365                 v= (vec[1]-lt->fv)/lt->dv;
366                 vi= (int)floor(v);
367                 v -= vi;
368                 set_four_ipo(v, tv, lt->typev);
369         }
370         else {
371                 tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
372                 vi= 0;
373         }
374         
375         if(lt->pntsw>1) {
376                 w= (vec[2]-lt->fw)/lt->dw;
377                 wi= (int)floor(w);
378                 w -= wi;
379                 set_four_ipo(w, tw, lt->typew);
380         }
381         else {
382                 tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
383                 wi= 0;
384         }
385         
386         for(ww= wi-1; ww<=wi+2; ww++) {
387                 w= tw[ww-wi+1];
388                 
389                 if(w!=0.0) {
390                         if(ww>0) {
391                                 if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
392                                 else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
393                         }
394                         else fpw= latticedata;
395                         
396                         for(vv= vi-1; vv<=vi+2; vv++) {
397                                 v= w*tv[vv-vi+1];
398                                 
399                                 if(v!=0.0) {
400                                         if(vv>0) {
401                                                 if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
402                                                 else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
403                                         }
404                                         else fpv= fpw;
405                                         
406                                         for(uu= ui-1; uu<=ui+2; uu++) {
407                                                 u= weight*v*tu[uu-ui+1];
408                                                 
409                                                 if(u!=0.0) {
410                                                         if(uu>0) {
411                                                                 if(uu<lt->pntsu) fpu= fpv + 3*uu;
412                                                                 else fpu= fpv + 3*(lt->pntsu-1);
413                                                         }
414                                                         else fpu= fpv;
415                                                         
416                                                         co[0]+= u*fpu[0];
417                                                         co[1]+= u*fpu[1];
418                                                         co[2]+= u*fpu[2];
419                                                 }
420                                         }
421                                 }
422                         }
423                 }
424         }
425 }
426
427 void end_latt_deform()
428 {
429
430         MEM_freeN(latticedata);
431         latticedata= 0;
432 }
433
434         /* calculations is in local space of deformed object
435            so we store in latmat transform from path coord inside object 
436          */
437 typedef struct {
438         float dmin[3], dmax[3], dsize, dloc[3];
439         float curvespace[4][4], objectspace[4][4];
440 } CurveDeform;
441
442 static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
443 {
444         Mat4Invert(ob->imat, ob->obmat);
445         Mat4MulMat4(cd->objectspace, par->obmat, ob->imat);
446         Mat4Invert(cd->curvespace, cd->objectspace);
447
448         // offset vector for 'no smear'
449         Mat4Invert(par->imat, par->obmat);
450         VecMat4MulVecfl(cd->dloc, par->imat, ob->obmat[3]);
451
452 }
453
454 /* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
455 static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir)        /* returns OK */
456 {
457         Curve *cu= ob->data;
458         BevList *bl;
459         float ctime1;
460         int cycl=0;
461         
462         /* test for cyclic */
463         bl= cu->bev.first;
464         if(bl && bl->poly> -1) cycl= 1;
465
466         if(cycl==0) {
467                 ctime1= CLAMPIS(ctime, 0.0, 1.0);
468         }
469         else ctime1= ctime;
470         
471         /* vec needs 4 items */
472         if(where_on_path(ob, ctime1, vec, dir)) {
473                 
474                 if(cycl==0) {
475                         Path *path= cu->path;
476                         float dvec[3];
477                         
478                         if(ctime < 0.0) {
479                                 VecSubf(dvec, path->data+4, path->data);
480                                 VecMulf(dvec, ctime*(float)path->len);
481                                 VECADD(vec, vec, dvec);
482                         }
483                         else if(ctime > 1.0) {
484                                 VecSubf(dvec, path->data+4*path->len-4, path->data+4*path->len-8);
485                                 VecMulf(dvec, (ctime-1.0)*(float)path->len);
486                                 VECADD(vec, vec, dvec);
487                         }
488                 }
489                 return 1;
490         }
491         return 0;
492 }
493
494         /* for each point, rotate & translate to curve */
495         /* use path, since it has constant distances */
496         /* co: local coord, result local too */
497 static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd)
498 {
499         Curve *cu= par->data;
500         float fac, loc[4], dir[3], *quat, q[4], mat[3][3], cent[3];
501         short upflag, index;
502         
503         if(axis==OB_POSX || axis==OB_NEGX) {
504                 upflag= OB_POSZ;
505                 cent[0]= 0.0;
506                 cent[1]= co[1];
507                 cent[2]= co[2];
508                 index= 0;
509         }
510         else if(axis==OB_POSY || axis==OB_NEGY) {
511                 upflag= OB_POSZ;
512                 cent[0]= co[0];
513                 cent[1]= 0.0;
514                 cent[2]= co[2];
515                 index= 1;
516         }
517         else {
518                 upflag= OB_POSY;
519                 cent[0]= co[0];
520                 cent[1]= co[1];
521                 cent[2]= 0.0;
522                 index= 2;
523         }
524         /* to be sure, mostly after file load */
525         if(cu->path==NULL) {
526                 makeDispListCurveTypes(par, 0);
527                 if(cu->path==NULL) return;      // happens on append...
528         }
529         /* options */
530         if(cu->flag & CU_STRETCH)
531                 fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
532         else
533                 fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
534         
535         if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */
536
537                 quat= vectoquat(dir, axis, upflag);
538                 
539                 /* the tilt */
540                 if(loc[3]!=0.0) {
541                         Normalise(dir);
542                         q[0]= (float)cos(0.5*loc[3]);
543                         fac= (float)sin(0.5*loc[3]);
544                         q[1]= -fac*dir[0];
545                         q[2]= -fac*dir[1];
546                         q[3]= -fac*dir[2];
547                         QuatMul(quat, q, quat);
548                 }               
549                 QuatToMat3(quat, mat);
550         
551                 /* local rotation */
552                 Mat3MulVecfl(mat, cent);
553                 
554                 /* translation */
555                 VECADD(co, cent, loc);
556                 
557         }
558
559 }
560
561 void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup)
562 {
563         Curve *cu = cuOb->data;
564         int a, flag = cu->flag;
565         CurveDeform cd;
566         int use_vgroups;
567         
568         cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
569
570         init_curve_deform(cuOb, target, &cd);
571                 
572         /* check whether to use vertex groups (only possible if target is a Mesh)
573          * we want either a Mesh with no derived data, or derived data with
574          * deformverts
575          */
576         if(target && target->type==OB_MESH) {
577                 /* if there's derived data without deformverts, don't use vgroups */
578                 if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
579                         use_vgroups = 0;
580                 else
581                         use_vgroups = 1;
582         } else
583                 use_vgroups = 0;
584         
585         if(vgroup && vgroup[0] && use_vgroups) {
586                 bDeformGroup *curdef;
587                 Mesh *me= target->data;
588                 int index;
589                 
590                 /* find the group (weak loop-in-loop) */
591                 for(index = 0, curdef = target->defbase.first; curdef;
592                     curdef = curdef->next, index++)
593                         if (!strcmp(curdef->name, vgroup))
594                                 break;
595
596                 if(curdef && (me->dvert || dm)) {
597                         MDeformVert *dvert = me->dvert;
598                         float vec[3];
599                         int j;
600
601                         INIT_MINMAX(cd.dmin, cd.dmax);
602
603                         for(a = 0; a < numVerts; a++, dvert++) {
604                                 if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
605
606                                 for(j = 0; j < dvert->totweight; j++) {
607                                         if(dvert->dw[j].def_nr == index) {
608                                                 Mat4MulVecfl(cd.curvespace, vertexCos[a]);
609                                                 DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
610                                                 break;
611                                         }
612                                 }
613                         }
614
615                         dvert = me->dvert;
616                         for(a = 0; a < numVerts; a++, dvert++) {
617                                 if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
618
619                                 for(j = 0; j < dvert->totweight; j++) {
620                                         if(dvert->dw[j].def_nr == index) {
621                                                 VECCOPY(vec, vertexCos[a]);
622                                                 calc_curve_deform(cuOb, vec, target->trackflag, &cd);
623                                                 VecLerpf(vertexCos[a], vertexCos[a], vec,
624                                                          dvert->dw[j].weight);
625                                                 Mat4MulVecfl(cd.objectspace, vertexCos[a]);
626                                                 break;
627                                         }
628                                 }
629                         }
630                 }
631         } else {
632                 INIT_MINMAX(cd.dmin, cd.dmax);
633                         
634                 for(a = 0; a < numVerts; a++) {
635                         Mat4MulVecfl(cd.curvespace, vertexCos[a]);
636                         DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
637                 }
638
639                 for(a = 0; a < numVerts; a++) {
640                         calc_curve_deform(cuOb, vertexCos[a], target->trackflag, &cd);
641                         Mat4MulVecfl(cd.objectspace, vertexCos[a]);
642                 }
643         }
644         cu->flag = flag;
645 }
646
647 void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
648                           float (*vertexCos)[3], int numVerts, char *vgroup)
649 {
650         int a;
651         int use_vgroups;
652
653         init_latt_deform(laOb, target);
654
655         /* check whether to use vertex groups (only possible if target is a Mesh)
656          * we want either a Mesh with no derived data, or derived data with
657          * deformverts
658          */
659         if(target && target->type==OB_MESH) {
660                 /* if there's derived data without deformverts, don't use vgroups */
661                 if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
662                         use_vgroups = 0;
663                 else
664                         use_vgroups = 1;
665         } else
666                 use_vgroups = 0;
667         
668         if(vgroup && vgroup[0] && use_vgroups) {
669                 bDeformGroup *curdef;
670                 Mesh *me = target->data;
671                 int index = 0;
672                 
673                 /* find the group (weak loop-in-loop) */
674                 for(curdef = target->defbase.first; curdef;
675                     curdef = curdef->next, index++)
676                         if(!strcmp(curdef->name, vgroup)) break;
677
678                 if(curdef && (me->dvert || dm)) {
679                         MDeformVert *dvert = me->dvert;
680                         int j;
681                         
682                         for(a = 0; a < numVerts; a++, dvert++) {
683                                 if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
684                                 for(j = 0; j < dvert->totweight; j++) {
685                                         if (dvert->dw[j].def_nr == index) {
686                                                 calc_latt_deform(vertexCos[a], dvert->dw[j].weight);
687                                         }
688                                 }
689                         }
690                 }
691         } else {
692                 for(a = 0; a < numVerts; a++) {
693                         calc_latt_deform(vertexCos[a], 1.0f);
694                 }
695         }
696         end_latt_deform();
697 }
698
699 int object_deform_mball(Object *ob)
700 {
701         if(ob->parent && ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
702                 DispList *dl;
703
704                 for (dl=ob->disp.first; dl; dl=dl->next) {
705                         lattice_deform_verts(ob->parent, ob, NULL,
706                                              (float(*)[3]) dl->verts, dl->nr, NULL);
707                 }
708
709                 return 1;
710         } else {
711                 return 0;
712         }
713 }
714
715 static BPoint *latt_bp(Lattice *lt, int u, int v, int w)
716 {
717         return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
718 }
719
720 void outside_lattice(Lattice *lt)
721 {
722         BPoint *bp, *bp1, *bp2;
723         int u, v, w;
724         float fac1, du=0.0, dv=0.0, dw=0.0;
725
726         bp= lt->def;
727
728         if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
729         if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
730         if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
731                 
732         for(w=0; w<lt->pntsw; w++) {
733                 
734                 for(v=0; v<lt->pntsv; v++) {
735                 
736                         for(u=0; u<lt->pntsu; u++, bp++) {
737                                 if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
738                                 else {
739                                 
740                                         bp->hide= 1;
741                                         bp->f1 &= ~SELECT;
742                                         
743                                         /* u extrema */
744                                         bp1= latt_bp(lt, 0, v, w);
745                                         bp2= latt_bp(lt, lt->pntsu-1, v, w);
746                                         
747                                         fac1= du*u;
748                                         bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
749                                         bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
750                                         bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
751                                         
752                                         /* v extrema */
753                                         bp1= latt_bp(lt, u, 0, w);
754                                         bp2= latt_bp(lt, u, lt->pntsv-1, w);
755                                         
756                                         fac1= dv*v;
757                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
758                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
759                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
760                                         
761                                         /* w extrema */
762                                         bp1= latt_bp(lt, u, v, 0);
763                                         bp2= latt_bp(lt, u, v, lt->pntsw-1);
764                                         
765                                         fac1= dw*w;
766                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
767                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
768                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
769                                         
770                                         VecMulf(bp->vec, 0.3333333f);
771                                         
772                                 }
773                         }
774                         
775                 }
776                 
777         }
778         
779 }
780
781 float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3]
782 {
783         Lattice *lt = (G.obedit==ob)?editLatt:ob->data;
784         int i, numVerts = *numVerts_r = lt->pntsu*lt->pntsv*lt->pntsw;
785         float (*vertexCos)[3] = MEM_mallocN(sizeof(*vertexCos)*numVerts,"lt_vcos");
786
787         for (i=0; i<numVerts; i++) {
788                 VECCOPY(vertexCos[i], lt->def[i].vec);
789         }
790
791         return vertexCos;
792 }
793
794 void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3])
795 {
796         Lattice *lt = ob->data;
797         int i, numVerts = lt->pntsu*lt->pntsv*lt->pntsw;
798
799         for (i=0; i<numVerts; i++) {
800                 VECCOPY(lt->def[i].vec, vertexCos[i]);
801         }
802 }
803
804 void lattice_calc_modifiers(Object *ob)
805 {
806         float (*vertexCos)[3] = NULL;
807         ModifierData *md = modifiers_getVirtualModifierList(ob);
808         int numVerts, editmode = G.obedit==ob;
809
810         freedisplist(&ob->disp);
811
812         if (!editmode) {
813                 do_ob_key(ob);
814         }
815
816         for (; md; md=md->next) {
817                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
818
819                 if (!(md->mode&eModifierMode_Realtime)) continue;
820                 if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
821                 if (mti->isDisabled && mti->isDisabled(md)) continue;
822                 if (mti->type!=eModifierTypeType_OnlyDeform) continue;
823
824                 if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts);
825                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
826         }
827
828         if (vertexCos) {
829                 DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl");
830                 dl->type = DL_VERTS;
831                 dl->parts = 1;
832                 dl->nr = numVerts;
833                 dl->verts = (float*) vertexCos;
834                 
835                 BLI_addtail(&ob->disp, dl);
836         }
837 }