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