Bug fix 823
[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 #include "DNA_ika_types.h"
55
56 #include "BKE_utildefines.h"
57 #include "BKE_armature.h"
58 #include "BKE_library.h"
59 #include "BKE_global.h"
60 #include "BKE_main.h"
61 #include "BKE_screen.h"
62 #include "BKE_displist.h"
63 #include "BKE_lattice.h"
64 #include "BKE_key.h"
65 #include "BKE_object.h"
66 #include "BKE_ika.h"
67 #include "BKE_curve.h"
68
69 #ifdef HAVE_CONFIG_H
70 #include <config.h>
71 #endif
72
73 Lattice *editLatt=0, *deformLatt=0;
74
75 float *latticedata=0, latmat[4][4];
76
77 void resizelattice(Lattice *lt)
78 {
79         BPoint *bp;
80         int u, v, w;
81         float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
82         
83
84         MEM_freeN(lt->def);
85         lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
86         
87         bp= lt->def;
88         
89         while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) {
90                 if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--;
91                 else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--;
92                 else lt->pntsw--;
93         }
94         
95         calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
96         calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv);
97         calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw);
98         
99         vec[2]= fw;
100         for(w=0; w<lt->pntsw; w++) {
101                 vec[1]= fv;
102                 for(v=0; v<lt->pntsv; v++) {
103                         vec[0]= fu;
104                         for(u=0; u<lt->pntsu; u++, bp++) {
105                                 VECCOPY(bp->vec, vec);
106                                 vec[0]+= du;
107                         }
108                         vec[1]+= dv;
109                 }
110                 vec[2]+= dw;
111         }
112 }
113
114 Lattice *add_lattice()
115 {
116         Lattice *lt;
117         
118         lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
119         
120         lt->pntsu=lt->pntsv=lt->pntsw= 2;
121         lt->flag= LT_GRID;
122         
123         lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
124         
125         /* temporally */
126         lt->def= MEM_callocN(sizeof(BPoint), "lattvert");
127         
128         resizelattice(lt);      /* creates a uniform lattice */
129                 
130         return lt;
131 }
132
133 Lattice *copy_lattice(Lattice *lt)
134 {
135         Lattice *ltn;
136
137         ltn= copy_libblock(lt);
138         ltn->def= MEM_dupallocN(lt->def);
139                 
140         id_us_plus((ID *)ltn->ipo);
141
142         ltn->key= copy_key(ltn->key);
143         if(ltn->key) ltn->key->from= (ID *)ltn;
144         
145         return ltn;
146 }
147
148 void free_lattice(Lattice *lt)
149 {
150         if(lt->def) MEM_freeN(lt->def);
151 }
152
153
154 void make_local_lattice(Lattice *lt)
155 {
156         Object *ob;
157         Lattice *ltn;
158         int local=0, lib=0;
159
160         /* - only lib users: do nothing
161          * - only local users: set flag
162          * - mixed: make copy
163          */
164         
165         if(lt->id.lib==0) return;
166         if(lt->id.us==1) {
167                 lt->id.lib= 0;
168                 lt->id.flag= LIB_LOCAL;
169                 new_id(0, (ID *)lt, 0);
170                 return;
171         }
172         
173         ob= G.main->object.first;
174         while(ob) {
175                 if(ob->data==lt) {
176                         if(ob->id.lib) lib= 1;
177                         else local= 1;
178                 }
179                 ob= ob->id.next;
180         }
181         
182         if(local && lib==0) {
183                 lt->id.lib= 0;
184                 lt->id.flag= LIB_LOCAL;
185                 new_id(0, (ID *)lt, 0);
186         }
187         else if(local && lib) {
188                 ltn= copy_lattice(lt);
189                 ltn->id.us= 0;
190                 
191                 ob= G.main->object.first;
192                 while(ob) {
193                         if(ob->data==lt) {
194                                 
195                                 if(ob->id.lib==0) {
196                                         ob->data= ltn;
197                                         ltn->id.us++;
198                                         lt->id.us--;
199                                 }
200                         }
201                         ob= ob->id.next;
202                 }
203         }
204 }
205
206
207
208 void calc_lat_fudu(int flag, int res, float *fu, float *du)
209 {
210         
211         if(res==1) {
212                 *fu= 0.0;
213                 *du= 0.0;
214         }
215         else if(flag & LT_GRID) {
216                 *fu= -0.5f*(res-1);
217                 *du= 1.0f;
218         }
219         else {
220                 *fu= -1.0f;
221                 *du= 2.0f/(res-1);
222         }
223         
224 }
225
226 void init_latt_deform(Object *oblatt, Object *ob)
227 {
228         /* we make an array with all differences */
229         BPoint *bp;
230         float *fp, imat[4][4];
231         float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
232         int u, v, w;
233         
234         if(oblatt==G.obedit) deformLatt= editLatt;
235         else deformLatt= oblatt->data;
236         
237         fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
238         
239         bp= deformLatt->def;
240
241         if(ob) where_is_object(ob);
242
243         /* for example with a particle system: ob==0 */
244         if(ob==0) {
245                 /* in deformspace, calc matrix  */
246                 Mat4Invert(latmat, oblatt->obmat);
247         
248                 /* back: put in deform array */
249                 Mat4Invert(imat, latmat);
250         }
251         else {
252                 /* in deformspace, calc matrix */
253                 Mat4Invert(imat, oblatt->obmat);
254                 Mat4MulMat4(latmat, ob->obmat, imat);
255         
256                 /* back: put in deform array */
257                 Mat4Invert(imat, latmat);
258         }
259         calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du);
260         calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv);
261         calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw);
262         
263         /* we keep calculating the u v w lattice coordinates, not enough reason to store that */
264         
265         vec[2]= fw;
266         for(w=0; w<deformLatt->pntsw; w++) {
267                 vec[1]= fv;
268                 for(v=0; v<deformLatt->pntsv; v++) {
269                         vec[0]= fu;
270                         for(u=0; u<deformLatt->pntsu; u++, bp++) {
271                                 
272                                 VecSubf(fp, bp->vec, vec);
273                                 Mat4Mul3Vecfl(imat, fp);
274                 
275                                 vec[0]+= du;
276                                 fp+= 3;
277                         }
278                         vec[1]+= dv;
279                 }
280                 vec[2]+= dw;
281         }
282 }
283
284 void calc_latt_deform(float *co)
285 {
286         Lattice *lt;
287         float fu, du, u, v, w, tu[4], tv[4], tw[4];
288         float *fpw, *fpv, *fpu, vec[3];
289         int ui, vi, wi, uu, vv, ww;
290         
291         if(latticedata==0) return;
292         
293         lt= deformLatt; /* just for shorter notation! */
294         
295         /* co is in local coords, treat with latmat */
296         
297         VECCOPY(vec, co);
298         Mat4MulVecfl(latmat, vec);
299         
300         /* u v w coords */
301         
302         if(lt->pntsu>1) {
303                 calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
304                 u= (vec[0]-fu)/du;
305                 ui= (int)floor(u);
306                 u -= ui;
307                 set_four_ipo(u, tu, lt->typeu);
308         }
309         else {
310                 tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
311                 ui= 0;
312         }
313         
314         if(lt->pntsv>1) {
315                 calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du);
316                 v= (vec[1]-fu)/du;
317                 vi= (int)floor(v);
318                 v -= vi;
319                 set_four_ipo(v, tv, lt->typev);
320         }
321         else {
322                 tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
323                 vi= 0;
324         }
325         
326         if(lt->pntsw>1) {
327                 calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du);
328                 w= (vec[2]-fu)/du;
329                 wi= (int)floor(w);
330                 w -= wi;
331                 set_four_ipo(w, tw, lt->typew);
332         }
333         else {
334                 tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
335                 wi= 0;
336         }
337         
338         for(ww= wi-1; ww<=wi+2; ww++) {
339                 w= tw[ww-wi+1];
340                 
341                 if(w!=0.0) {
342                         if(ww>0) {
343                                 if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
344                                 else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
345                         }
346                         else fpw= latticedata;
347                         
348                         for(vv= vi-1; vv<=vi+2; vv++) {
349                                 v= w*tv[vv-vi+1];
350                                 
351                                 if(v!=0.0) {
352                                         if(vv>0) {
353                                                 if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
354                                                 else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
355                                         }
356                                         else fpv= fpw;
357                                         
358                                         for(uu= ui-1; uu<=ui+2; uu++) {
359                                                 u= v*tu[uu-ui+1];
360                                                 
361                                                 if(u!=0.0) {
362                                                         if(uu>0) {
363                                                                 if(uu<lt->pntsu) fpu= fpv + 3*uu;
364                                                                 else fpu= fpv + 3*(lt->pntsu-1);
365                                                         }
366                                                         else fpu= fpv;
367                                                         
368                                                         co[0]+= u*fpu[0];
369                                                         co[1]+= u*fpu[1];
370                                                         co[2]+= u*fpu[2];
371                                                 }
372                                         }
373                                 }
374                         }
375                 }
376         }
377 }
378
379 void end_latt_deform()
380 {
381
382         MEM_freeN(latticedata);
383         latticedata= 0;
384 }
385
386
387 static int _object_deform(Object *ob, int applyflag)
388 {
389         Mesh *me;
390         Curve *cu;
391         DispList *dl;
392         MVert *mvert;
393         float *fp;
394         int a, tot;
395
396         if(ob->parent==0) return 0;
397         
398         /* always try to do the entire deform in this function: apply! */
399         
400         if(ob->parent->type==OB_LATTICE) {
401                 
402                 init_latt_deform(ob->parent, ob);
403                 
404                 if(ob->type==OB_MESH) {
405                         me= ob->data;
406                         
407                         dl= find_displist_create(&ob->disp, DL_VERTS);
408                         
409                         mvert= me->mvert;
410                         if(dl->verts) MEM_freeN(dl->verts);
411                         dl->nr= me->totvert;
412                         dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
413
414                         for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
415                                 if(applyflag) calc_latt_deform(mvert->co);
416                                 else {
417                                         VECCOPY(fp, mvert->co);
418                                         calc_latt_deform(fp);
419                                 }
420                         }
421                 }
422                 else if(ob->type==OB_MBALL) {
423                         dl=ob->disp.first;
424                         while(dl) {
425                                 fp = dl->verts;
426                                 for(a=0;a<dl->nr;a++,fp+=3)
427                                         calc_latt_deform(fp);
428                                 dl=dl->next;
429                         }
430                 }
431                 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
432                 
433                         cu= ob->data;
434                         if(applyflag) {
435                                 Nurb *nu;
436                                 BPoint *bp;
437                                 BezTriple *bezt;
438                                 
439                                 nu= cu->nurb.first;
440                                 while(nu) {
441                                         if(nu->bp) {
442                                                 a= nu->pntsu*nu->pntsv;
443                                                 bp= nu->bp;
444                                                 while(a--) {
445                                                         calc_latt_deform(bp->vec);
446                                                         bp++;
447                                                 }
448                                         }
449                                         else if(nu->bezt) {
450                                                 a= nu->pntsu;
451                                                 bezt= nu->bezt;
452                                                 while(a--) {
453                                                         calc_latt_deform(bezt->vec[0]);
454                                                         calc_latt_deform(bezt->vec[1]);
455                                                         calc_latt_deform(bezt->vec[2]);
456                                                         bezt++;
457                                                 }
458                                                 test2DNurb(nu);
459                                         }
460                                         nu= nu->next;
461                                 }
462                         }
463                         else {
464                                 /* apply deform on displist */
465                                 dl= cu->disp.first;
466                                 while(dl) {
467                                         
468                                         fp= dl->verts;
469                                         
470                                         if(dl->type==DL_INDEX3) tot=dl->parts;
471                                         else tot= dl->nr*dl->parts;
472                                         
473                                         for(a=0; a<tot; a++, fp+=3) {
474                                                 calc_latt_deform(fp);
475                                         }
476                                         
477                                         dl= dl->next;
478                                 }
479                         }
480                 }
481                 end_latt_deform();
482
483                 boundbox_displist(ob);  
484
485                 return 1;
486         }
487         else if(ob->parent->type==OB_ARMATURE) {
488                 if (ob->partype != PARSKEL){
489                         return 0;
490                 }
491                 
492                 init_armature_deform (ob->parent, ob);
493
494                 switch (ob->type){
495                 case OB_MESH:
496                         me= ob->data;
497                         
498                         dl= find_displist_create(&ob->disp, DL_VERTS);
499                         
500                         mvert= me->mvert;
501                         if(dl->verts) MEM_freeN(dl->verts);
502                         dl->nr= me->totvert;
503                         dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
504
505                         for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
506                                 if(applyflag){
507                                         calc_armature_deform(ob->parent, mvert->co, a);
508                                 }
509                                 else {
510                                         VECCOPY(fp, mvert->co);
511                                         calc_armature_deform(ob->parent, fp, a);
512                                 }
513                         }
514
515                         break;
516                 default:
517                         break;
518                 }
519                 
520                 boundbox_displist(ob);  
521                 return 1;
522         }
523         else if(ob->parent->type==OB_IKA) {
524
525                 Ika *ika;
526                 
527                 if(ob->partype!=PARSKEL) return 0;
528                 
529                 ika= ob->parent->data;
530                 if(ika->def==0) return 0;
531                 
532                 init_skel_deform(ob->parent, ob);
533                 
534                 if(ob->type==OB_MESH) {
535                         me= ob->data;
536                         
537                         dl= find_displist_create(&ob->disp, DL_VERTS);
538                         
539                         mvert= me->mvert;
540                         if(dl->verts) MEM_freeN(dl->verts);
541                         dl->nr= me->totvert;
542                         dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
543
544                         for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
545                                 if(applyflag) calc_skel_deform(ika, mvert->co);
546                                 else {
547                                         VECCOPY(fp, mvert->co);
548                                         calc_skel_deform(ika, fp);
549                                 }
550                         }
551                 }
552                 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
553                 
554                         cu= ob->data;
555                         if(applyflag) {
556                                 Nurb *nu;
557                                 BPoint *bp;
558                                 
559                                 nu= cu->nurb.first;
560                                 while(nu) {
561                                         if(nu->bp) {
562                                                 a= nu->pntsu*nu->pntsv;
563                                                 bp= nu->bp;
564                                                 while(a--) {
565                                                         calc_skel_deform(ika, bp->vec);
566                                                         bp++;
567                                                 }
568                                         }
569                                         nu= nu->next;
570                                 }
571                         }
572                         
573                         /* when apply, do this too, looks more interactive */
574                         dl= cu->disp.first;
575                         while(dl) {
576                                 
577                                 fp= dl->verts;
578                                 tot= dl->nr*dl->parts;
579                                 for(a=0; a<tot; a++, fp+=3) {
580                                         calc_skel_deform(ika, fp);
581                                 }
582                                 
583                                 dl= dl->next;
584                         }
585                 }
586                 
587                 boundbox_displist(ob);
588                 
589                 return 1;
590         }
591         
592         return 0;
593
594 }
595
596 int object_deform(Object *ob)
597 {
598         return _object_deform(ob, 0);
599 }
600 int object_apply_deform(Object *ob)
601 {
602         return _object_deform(ob, 1);
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 }