- couldn't help myself, got distracted working on something else and
[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_object_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_lattice_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_key_types.h"
54
55 #include "BKE_anim.h"
56 #include "BKE_armature.h"
57 #include "BKE_curve.h"
58 #include "BKE_deform.h"
59 #include "BKE_displist.h"
60 #include "BKE_global.h"
61 #include "BKE_key.h"
62 #include "BKE_lattice.h"
63 #include "BKE_library.h"
64 #include "BKE_main.h"
65 #include "BKE_object.h"
66 #include "BKE_screen.h"
67 #include "BKE_utildefines.h"
68
69 #include "BIF_editdeform.h"
70
71 #ifdef HAVE_CONFIG_H
72 #include <config.h>
73 #endif
74
75 #include "blendef.h"
76
77 Lattice *editLatt=0, *deformLatt=0;
78
79 float *latticedata=0, latmat[4][4];
80
81 void resizelattice(Lattice *lt)
82 {
83         BPoint *bp;
84         int u, v, w;
85         float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
86         
87
88         MEM_freeN(lt->def);
89         lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
90         
91         bp= lt->def;
92         
93         while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) {
94                 if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--;
95                 else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--;
96                 else lt->pntsw--;
97         }
98         
99         calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
100         calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv);
101         calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw);
102         
103         vec[2]= fw;
104         for(w=0; w<lt->pntsw; w++) {
105                 vec[1]= fv;
106                 for(v=0; v<lt->pntsv; v++) {
107                         vec[0]= fu;
108                         for(u=0; u<lt->pntsu; u++, bp++) {
109                                 VECCOPY(bp->vec, vec);
110                                 vec[0]+= du;
111                         }
112                         vec[1]+= dv;
113                 }
114                 vec[2]+= dw;
115         }
116 }
117
118 Lattice *add_lattice()
119 {
120         Lattice *lt;
121         
122         lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
123         
124         lt->pntsu=lt->pntsv=lt->pntsw= 2;
125         lt->flag= LT_GRID;
126         
127         lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
128         
129         /* temporally */
130         lt->def= MEM_callocN(sizeof(BPoint), "lattvert");
131         
132         resizelattice(lt);      /* creates a uniform lattice */
133                 
134         return lt;
135 }
136
137 Lattice *copy_lattice(Lattice *lt)
138 {
139         Lattice *ltn;
140
141         ltn= copy_libblock(lt);
142         ltn->def= MEM_dupallocN(lt->def);
143                 
144         id_us_plus((ID *)ltn->ipo);
145
146         ltn->key= copy_key(ltn->key);
147         if(ltn->key) ltn->key->from= (ID *)ltn;
148         
149         return ltn;
150 }
151
152 void free_lattice(Lattice *lt)
153 {
154         if(lt->def) MEM_freeN(lt->def);
155 }
156
157
158 void make_local_lattice(Lattice *lt)
159 {
160         Object *ob;
161         Lattice *ltn;
162         int local=0, lib=0;
163
164         /* - only lib users: do nothing
165          * - only local users: set flag
166          * - mixed: make copy
167          */
168         
169         if(lt->id.lib==0) return;
170         if(lt->id.us==1) {
171                 lt->id.lib= 0;
172                 lt->id.flag= LIB_LOCAL;
173                 new_id(0, (ID *)lt, 0);
174                 return;
175         }
176         
177         ob= G.main->object.first;
178         while(ob) {
179                 if(ob->data==lt) {
180                         if(ob->id.lib) lib= 1;
181                         else local= 1;
182                 }
183                 ob= ob->id.next;
184         }
185         
186         if(local && lib==0) {
187                 lt->id.lib= 0;
188                 lt->id.flag= LIB_LOCAL;
189                 new_id(0, (ID *)lt, 0);
190         }
191         else if(local && lib) {
192                 ltn= copy_lattice(lt);
193                 ltn->id.us= 0;
194                 
195                 ob= G.main->object.first;
196                 while(ob) {
197                         if(ob->data==lt) {
198                                 
199                                 if(ob->id.lib==0) {
200                                         ob->data= ltn;
201                                         ltn->id.us++;
202                                         lt->id.us--;
203                                 }
204                         }
205                         ob= ob->id.next;
206                 }
207         }
208 }
209
210
211
212 void calc_lat_fudu(int flag, int res, float *fu, float *du)
213 {
214         
215         if(res==1) {
216                 *fu= 0.0;
217                 *du= 0.0;
218         }
219         else if(flag & LT_GRID) {
220                 *fu= -0.5f*(res-1);
221                 *du= 1.0f;
222         }
223         else {
224                 *fu= -1.0f;
225                 *du= 2.0f/(res-1);
226         }
227         
228 }
229
230 void init_latt_deform(Object *oblatt, Object *ob)
231 {
232         /* we make an array with all differences */
233         BPoint *bp;
234         float *fp, imat[4][4];
235         float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
236         int u, v, w;
237         
238         if(oblatt==G.obedit) deformLatt= editLatt;
239         else deformLatt= oblatt->data;
240         
241         fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
242         
243         lattice_modifier(oblatt, 's');
244         bp= deformLatt->def;
245
246         //if(ob) where_is_object(ob); causes lag here, but why! (ton)
247
248         /* for example with a particle system: ob==0 */
249         if(ob==0) {
250                 /* in deformspace, calc matrix  */
251                 Mat4Invert(latmat, oblatt->obmat);
252         
253                 /* back: put in deform array */
254                 Mat4Invert(imat, latmat);
255         }
256         else {
257                 /* in deformspace, calc matrix */
258                 Mat4Invert(imat, oblatt->obmat);
259                 Mat4MulMat4(latmat, ob->obmat, imat);
260         
261                 /* back: put in deform array */
262                 Mat4Invert(imat, latmat);
263         }
264         calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du);
265         calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv);
266         calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw);
267         
268         /* we keep calculating the u v w lattice coordinates, not enough reason to store that */
269         
270         vec[2]= fw;
271         for(w=0; w<deformLatt->pntsw; w++) {
272                 vec[1]= fv;
273                 for(v=0; v<deformLatt->pntsv; v++) {
274                         vec[0]= fu;
275                         for(u=0; u<deformLatt->pntsu; u++, bp++) {
276                                 
277                                 VecSubf(fp, bp->vec, vec);
278                                 Mat4Mul3Vecfl(imat, fp);
279                 
280                                 vec[0]+= du;
281                                 fp+= 3;
282                         }
283                         vec[1]+= dv;
284                 }
285                 vec[2]+= dw;
286         }
287
288         lattice_modifier(oblatt, 'e');
289
290 }
291
292 void calc_latt_deform(float *co)
293 {
294         Lattice *lt;
295         float fu, du, u, v, w, tu[4], tv[4], tw[4];
296         float *fpw, *fpv, *fpu, vec[3];
297         int ui, vi, wi, uu, vv, ww;
298         
299         if(latticedata==0) return;
300         
301         lt= deformLatt; /* just for shorter notation! */
302         
303         /* co is in local coords, treat with latmat */
304         
305         VECCOPY(vec, co);
306         Mat4MulVecfl(latmat, vec);
307         
308         /* u v w coords */
309         
310         if(lt->pntsu>1) {
311                 calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
312                 u= (vec[0]-fu)/du;
313                 ui= (int)floor(u);
314                 u -= ui;
315                 set_four_ipo(u, tu, lt->typeu);
316         }
317         else {
318                 tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
319                 ui= 0;
320         }
321         
322         if(lt->pntsv>1) {
323                 calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du);
324                 v= (vec[1]-fu)/du;
325                 vi= (int)floor(v);
326                 v -= vi;
327                 set_four_ipo(v, tv, lt->typev);
328         }
329         else {
330                 tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
331                 vi= 0;
332         }
333         
334         if(lt->pntsw>1) {
335                 calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du);
336                 w= (vec[2]-fu)/du;
337                 wi= (int)floor(w);
338                 w -= wi;
339                 set_four_ipo(w, tw, lt->typew);
340         }
341         else {
342                 tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
343                 wi= 0;
344         }
345         
346         for(ww= wi-1; ww<=wi+2; ww++) {
347                 w= tw[ww-wi+1];
348                 
349                 if(w!=0.0) {
350                         if(ww>0) {
351                                 if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
352                                 else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
353                         }
354                         else fpw= latticedata;
355                         
356                         for(vv= vi-1; vv<=vi+2; vv++) {
357                                 v= w*tv[vv-vi+1];
358                                 
359                                 if(v!=0.0) {
360                                         if(vv>0) {
361                                                 if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
362                                                 else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
363                                         }
364                                         else fpv= fpw;
365                                         
366                                         for(uu= ui-1; uu<=ui+2; uu++) {
367                                                 u= v*tu[uu-ui+1];
368                                                 
369                                                 if(u!=0.0) {
370                                                         if(uu>0) {
371                                                                 if(uu<lt->pntsu) fpu= fpv + 3*uu;
372                                                                 else fpu= fpv + 3*(lt->pntsu-1);
373                                                         }
374                                                         else fpu= fpv;
375                                                         
376                                                         co[0]+= u*fpu[0];
377                                                         co[1]+= u*fpu[1];
378                                                         co[2]+= u*fpu[2];
379                                                 }
380                                         }
381                                 }
382                         }
383                 }
384         }
385 }
386
387 void end_latt_deform()
388 {
389
390         MEM_freeN(latticedata);
391         latticedata= 0;
392 }
393
394         /* calculations is in local space of deformed object
395            so we store in latmat transform from path coord inside object 
396          */
397 typedef struct {
398         float dmin[3], dmax[3], dsize, dloc[3];
399         float curvespace[4][4], objectspace[4][4];
400 } CurveDeform;
401
402 static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
403 {
404         Mat4Invert(ob->imat, ob->obmat);
405         Mat4MulMat4(cd->objectspace, par->obmat, ob->imat);
406         Mat4Invert(cd->curvespace, cd->objectspace);
407
408         // offset vector for 'no smear'
409         Mat4Invert(par->imat, par->obmat);
410         VecMat4MulVecfl(cd->dloc, par->imat, ob->obmat[3]);
411
412 }
413
414 /* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
415 static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir)        /* returns OK */
416 {
417         Curve *cu= ob->data;
418         BevList *bl;
419         float ctime1;
420         int cycl=0;
421         
422         /* test for cyclic */
423         bl= cu->bev.first;
424         if(bl && bl->poly> -1) cycl= 1;
425
426         if(cycl==0) {
427                 ctime1= CLAMPIS(ctime, 0.0, 1.0);
428         }
429         else ctime1= ctime;
430         
431         /* vec needs 4 items */
432         if(where_on_path(ob, ctime1, vec, dir)) {
433                 
434                 if(cycl==0) {
435                         Path *path= cu->path;
436                         float dvec[3];
437                         
438                         if(ctime < 0.0) {
439                                 VecSubf(dvec, path->data+4, path->data);
440                                 VecMulf(dvec, ctime*(float)path->len);
441                                 VECADD(vec, vec, dvec);
442                         }
443                         else if(ctime > 1.0) {
444                                 VecSubf(dvec, path->data+4*path->len-4, path->data+4*path->len-8);
445                                 VecMulf(dvec, (ctime-1.0)*(float)path->len);
446                                 VECADD(vec, vec, dvec);
447                         }
448                 }
449                 return 1;
450         }
451         return 0;
452 }
453
454         /* for each point, rotate & translate to curve */
455         /* use path, since it has constant distances */
456         /* co: local coord, result local too */
457 static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd)
458 {
459         Curve *cu= par->data;
460         float fac, loc[4], dir[3], *quat, q[4], mat[3][3], cent[3];
461         short upflag, index;
462         
463         if(axis==OB_POSX || axis==OB_NEGX) {
464                 upflag= OB_POSZ;
465                 cent[0]= 0.0;
466                 cent[1]= co[1];
467                 cent[2]= co[2];
468                 index= 0;
469         }
470         else if(axis==OB_POSY || axis==OB_NEGY) {
471                 upflag= OB_POSZ;
472                 cent[0]= co[0];
473                 cent[1]= 0.0;
474                 cent[2]= co[2];
475                 index= 1;
476         }
477         else {
478                 upflag= OB_POSY;
479                 cent[0]= co[0];
480                 cent[1]= co[1];
481                 cent[2]= 0.0;
482                 index= 2;
483         }
484         /* to be sure */
485         if(cu->path==NULL) {
486                 calc_curvepath(par);
487                 if(cu->path==NULL) return;      // happens on append...
488         }
489         /* options */
490         if(cu->flag & CU_STRETCH)
491                 fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
492         else
493                 fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
494         
495         if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */
496
497                 quat= vectoquat(dir, axis, upflag);
498                 
499                 /* the tilt */
500                 if(loc[3]!=0.0) {
501                         Normalise(dir);
502                         q[0]= (float)cos(0.5*loc[3]);
503                         fac= (float)sin(0.5*loc[3]);
504                         q[1]= -fac*dir[0];
505                         q[2]= -fac*dir[1];
506                         q[3]= -fac*dir[2];
507                         QuatMul(quat, q, quat);
508                 }               
509                 QuatToMat3(quat, mat);
510         
511                 /* local rotation */
512                 Mat3MulVecfl(mat, cent);
513                 
514                 /* translation */
515                 VECADD(co, cent, loc);
516                 
517         }
518
519 }
520
521 void curve_deform_verts(Object *cuOb, Object *target, float (*vertexCos)[3], int numVerts)
522 {
523         Curve *cu = cuOb->data;
524         int a, flag = cu->flag;
525         CurveDeform cd;
526         
527         cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
528
529         init_curve_deform(cuOb, target, &cd);
530                 
531         INIT_MINMAX(cd.dmin, cd.dmax);
532                 
533         for(a=0; a<numVerts; a++) {
534                 Mat4MulVecfl(cd.curvespace, vertexCos[a]);
535                 DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
536         }
537
538         for(a=0; a<numVerts; a++) {
539                 calc_curve_deform(cuOb, vertexCos[a], target->trackflag, &cd);
540                 Mat4MulVecfl(cd.objectspace, vertexCos[a]);
541         }
542
543         cu->flag = flag;
544 }
545
546 void lattice_deform_verts(Object *laOb, Object *target, float (*vertexCos)[3], int numVerts)
547 {
548         int a;
549
550         init_latt_deform(laOb, target);
551
552         for(a=0; a<numVerts; a++) {
553                 calc_latt_deform(vertexCos[a]);
554         }
555
556         end_latt_deform();
557 }
558
559 int object_deform(Object *ob)
560 {
561         Curve *cu;
562         DispList *dl;
563         float *fp;
564         int a, tot;
565
566         if(ob->parent==NULL) return 0;
567         
568         if(ob->parent->type==OB_LATTICE) {
569                 init_latt_deform(ob->parent, ob);
570                 
571                 if(ob->type==OB_MBALL) {
572                         dl=ob->disp.first;
573                         while(dl) {
574                                 fp = dl->verts;
575                                 for(a=0;a<dl->nr;a++,fp+=3)
576                                         calc_latt_deform(fp);
577                                 dl=dl->next;
578                         }
579                 }
580                 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
581                         cu= ob->data;
582                         /* apply deform on displist */
583                         dl= cu->disp.first;
584                         while(dl) {
585                                 
586                                 fp= dl->verts;
587                                 
588                                 if(dl->type==DL_INDEX3) tot=dl->parts;
589                                 else tot= dl->nr*dl->parts;
590                                 
591                                 for(a=0; a<tot; a++, fp+=3) {
592                                         calc_latt_deform(fp);
593                                 }
594                                 
595                                 dl= dl->next;
596                         }
597                 }
598                 end_latt_deform();
599                 return 1;
600         }
601         
602         return 0;
603
604 }
605
606 BPoint *latt_bp(Lattice *lt, int u, int v, int w)
607 {
608         return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
609 }
610
611 void outside_lattice(Lattice *lt)
612 {
613         BPoint *bp, *bp1, *bp2;
614         int u, v, w;
615         float fac1, du=0.0, dv=0.0, dw=0.0;
616
617         bp= lt->def;
618
619         if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
620         if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
621         if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
622                 
623         for(w=0; w<lt->pntsw; w++) {
624                 
625                 for(v=0; v<lt->pntsv; v++) {
626                 
627                         for(u=0; u<lt->pntsu; u++, bp++) {
628                                 if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
629                                 else {
630                                 
631                                         bp->hide= 1;
632                                         bp->f1 &= ~SELECT;
633                                         
634                                         /* u extrema */
635                                         bp1= latt_bp(lt, 0, v, w);
636                                         bp2= latt_bp(lt, lt->pntsu-1, v, w);
637                                         
638                                         fac1= du*u;
639                                         bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
640                                         bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
641                                         bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
642                                         
643                                         /* v extrema */
644                                         bp1= latt_bp(lt, u, 0, w);
645                                         bp2= latt_bp(lt, u, lt->pntsv-1, w);
646                                         
647                                         fac1= dv*v;
648                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
649                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
650                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
651                                         
652                                         /* w extrema */
653                                         bp1= latt_bp(lt, u, v, 0);
654                                         bp2= latt_bp(lt, u, v, lt->pntsw-1);
655                                         
656                                         fac1= dw*w;
657                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
658                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
659                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
660                                         
661                                         VecMulf(bp->vec, 0.3333333f);
662                                         
663                                 }
664                         }
665                         
666                 }
667                 
668         }
669         
670 }