some small optimizations
[blender.git] / source / blender / blenkernel / intern / lattice.c
1 /**
2  * lattice.c      MIXED MODEL
3  * june 2001 ton
4  * $Id$
5  *
6  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  */
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38 #include <stdlib.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_arithb.h"
44
45 #include "DNA_armature_types.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_key_types.h"
52 #include "DNA_ika_types.h"
53
54 #include "BKE_utildefines.h"
55 #include "BKE_armature.h"
56 #include "BKE_library.h"
57 #include "BKE_global.h"
58 #include "BKE_main.h"
59 #include "BKE_screen.h"
60 #include "BKE_displist.h"
61 #include "BKE_lattice.h"
62 #include "BKE_key.h"
63 #include "BKE_object.h"
64 #include "BKE_ika.h"
65
66 Lattice *editLatt=0, *deformLatt=0;
67
68 float *latticedata=0, latmat[4][4];
69 int lt_applyflag= 0;
70
71 void resizelattice(Lattice *lt)
72 {
73         BPoint *bp;
74         int u, v, w;
75         float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
76         
77
78         MEM_freeN(lt->def);
79         lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
80         
81         bp= lt->def;
82         
83         while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) {
84                 if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--;
85                 else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--;
86                 else lt->pntsw--;
87         }
88         
89         calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
90         calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv);
91         calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw);
92         
93         vec[2]= fw;
94         for(w=0; w<lt->pntsw; w++) {
95                 vec[1]= fv;
96                 for(v=0; v<lt->pntsv; v++) {
97                         vec[0]= fu;
98                         for(u=0; u<lt->pntsu; u++, bp++) {
99                                 VECCOPY(bp->vec, vec);
100                                 vec[0]+= du;
101                         }
102                         vec[1]+= dv;
103                 }
104                 vec[2]+= dw;
105         }
106 }
107
108 Lattice *add_lattice()
109 {
110         Lattice *lt;
111         
112         lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
113         
114         lt->pntsu=lt->pntsv=lt->pntsw= 2;
115         lt->flag= LT_GRID;
116         
117         lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
118         
119         /* tijdelijk */
120         lt->def= MEM_callocN(sizeof(BPoint), "lattvert");
121         
122         resizelattice(lt);      /* maakt een regelmatige lattice */
123                 
124         return lt;
125 }
126
127 Lattice *copy_lattice(Lattice *lt)
128 {
129         Lattice *ltn;
130
131         ltn= copy_libblock(lt);
132         ltn->def= MEM_dupallocN(lt->def);
133                 
134         id_us_plus((ID *)ltn->ipo);
135
136         ltn->key= copy_key(ltn->key);
137         if(ltn->key) ltn->key->from= (ID *)ltn;
138         
139         return ltn;
140 }
141
142 void free_lattice(Lattice *lt)
143 {
144         if(lt->def) MEM_freeN(lt->def);
145 }
146
147
148 void make_local_lattice(Lattice *lt)
149 {
150         Object *ob;
151         Lattice *ltn;
152         int local=0, lib=0;
153         
154         /* - zijn er alleen lib users: niet doen
155          * - zijn er alleen locale users: flag zetten
156          * - mixed: copy
157          */
158         
159         if(lt->id.lib==0) return;
160         if(lt->id.us==1) {
161                 lt->id.lib= 0;
162                 lt->id.flag= LIB_LOCAL;
163                 new_id(0, (ID *)lt, 0);
164                 return;
165         }
166         
167         ob= G.main->object.first;
168         while(ob) {
169                 if(ob->data==lt) {
170                         if(ob->id.lib) lib= 1;
171                         else local= 1;
172                 }
173                 ob= ob->id.next;
174         }
175         
176         if(local && lib==0) {
177                 lt->id.lib= 0;
178                 lt->id.flag= LIB_LOCAL;
179                 new_id(0, (ID *)lt, 0);
180         }
181         else if(local && lib) {
182                 ltn= copy_lattice(lt);
183                 ltn->id.us= 0;
184                 
185                 ob= G.main->object.first;
186                 while(ob) {
187                         if(ob->data==lt) {
188                                 
189                                 if(ob->id.lib==0) {
190                                         ob->data= ltn;
191                                         ltn->id.us++;
192                                         lt->id.us--;
193                                 }
194                         }
195                         ob= ob->id.next;
196                 }
197         }
198 }
199
200
201
202 void calc_lat_fudu(int flag, int res, float *fu, float *du)
203 {
204         
205         if(res==1) {
206                 *fu= 0.0;
207                 *du= 0.0;
208         }
209         else if(flag & LT_GRID) {
210                 *fu= -0.5f*(res-1);
211                 *du= 1.0f;
212         }
213         else {
214                 *fu= -1.0f;
215                 *du= 2.0f/(res-1);
216         }
217         
218 }
219
220 void init_latt_deform(Object *oblatt, Object *ob)
221 {
222         /* we maken een array met alle verschillen */
223         BPoint *bp;
224         float *fp, imat[4][4];
225         float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0;
226         int u, v, w;
227         
228         if(oblatt==G.obedit) deformLatt= editLatt;
229         else deformLatt= oblatt->data;
230         
231         fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata");
232         
233         bp= deformLatt->def;
234
235         if(ob) where_is_object(ob);
236
237         /* bijv bij particle systeem: ob==0 */
238         if(ob==0) {
239                 /* in deformspace, matrix berekenen */
240                 Mat4Invert(latmat, oblatt->obmat);
241         
242                 /* terug: in deform array verwerken */
243                 Mat4Invert(imat, latmat);
244         }
245         else {
246                 /* in deformspace, matrix berekenen */
247                 Mat4Invert(imat, oblatt->obmat);
248                 Mat4MulMat4(latmat, ob->obmat, imat);
249         
250                 /* terug: in deform array verwerken */
251                 Mat4Invert(imat, latmat);
252         }
253         calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du);
254         calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv);
255         calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw);
256         
257         /* we berekenen hier steeds de u v w lattice coordinaten, weinig reden ze te onthouden */
258         
259         vec[2]= fw;
260         for(w=0; w<deformLatt->pntsw; w++) {
261                 vec[1]= fv;
262                 for(v=0; v<deformLatt->pntsv; v++) {
263                         vec[0]= fu;
264                         for(u=0; u<deformLatt->pntsu; u++, bp++) {
265                                 
266                                 VecSubf(fp, bp->vec, vec);
267                                 Mat4Mul3Vecfl(imat, fp);
268                 
269                                 vec[0]+= du;
270                                 fp+= 3;
271                         }
272                         vec[1]+= dv;
273                 }
274                 vec[2]+= dw;
275         }
276 }
277
278 void calc_latt_deform(float *co)
279 {
280         Lattice *lt;
281         float fu, du, u, v, w, tu[4], tv[4], tw[4];
282         float *fpw, *fpv, *fpu, vec[3];
283         int ui, vi, wi, uu, vv, ww, end, end2;
284         
285         if(latticedata==0) return;
286         
287         lt= deformLatt; /* kortere notatie! */
288         
289         /* co is in lokale coords, met latmat behandelen */
290         
291         VECCOPY(vec, co);
292         Mat4MulVecfl(latmat, vec);
293         
294         /* u v w coords */
295         
296         if(lt->pntsu>1) {
297                 calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du);
298                 u= (vec[0]-fu)/du;
299                 ui= (int)floor(u);
300                 u -= ui;
301                 set_four_ipo(u, tu, lt->typeu);
302         }
303         else {
304                 tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
305                 ui= 0;
306         }
307         
308         if(lt->pntsv>1) {
309                 calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du);
310                 v= (vec[1]-fu)/du;
311                 vi= (int)floor(v);
312                 v -= vi;
313                 set_four_ipo(v, tv, lt->typev);
314         }
315         else {
316                 tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
317                 vi= 0;
318         }
319         
320         if(lt->pntsw>1) {
321                 calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du);
322                 w= (vec[2]-fu)/du;
323                 wi= (int)floor(w);
324                 w -= wi;
325                 set_four_ipo(w, tw, lt->typew);
326         }
327         else {
328                 tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
329                 wi= 0;
330         }
331         
332         end = wi+2;
333         for(ww= wi-1; ww<=end; ww++) {
334                 w= tw[ww-wi+1];
335                 
336                 if(w!=0.0) {
337                         if(ww>0) {
338                                 if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv;
339                                 else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv;
340                         }
341                         else fpw= latticedata;
342                         
343                         end2 = vi+2;
344                         for(vv= vi-1; vv<=end; vv++) {
345                                 v= w*tv[vv-vi+1];
346                                 
347                                 if(v!=0.0) {
348                                         if(vv>0) {
349                                                 if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu;
350                                                 else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu;
351                                         }
352                                         else fpv= fpw;
353                                         
354                                         for(uu= ui-1; uu<=ui+2; uu++) {
355                                                 u= v*tu[uu-ui+1];
356                                                 
357                                                 if(u!=0.0) {
358                                                         if(uu>0) {
359                                                                 if(uu<lt->pntsu) fpu= fpv + 3*uu;
360                                                                 else fpu= fpv + 3*(lt->pntsu-1);
361                                                         }
362                                                         else fpu= fpv;
363                                                         
364                                                         co[0]+= u*fpu[0];
365                                                         co[1]+= u*fpu[1];
366                                                         co[2]+= u*fpu[2];
367                                                 }
368                                         }
369                                 }
370                         }
371                 }
372         }
373 }
374
375
376 void end_latt_deform()
377 {
378
379         MEM_freeN(latticedata);
380         latticedata= 0;
381 }
382
383
384 int object_deform(Object *ob)
385 {
386         Mesh *me;
387         Curve *cu;
388         DispList *dl;
389         MVert *mvert;
390         float *fp;
391         int a, tot;
392
393         if(ob->parent==0) return 0;
394         
395         /* altijd proberen in deze fie de hele deform te doen: apply! */
396         
397         if(ob->parent->type==OB_LATTICE) {
398                 
399                 init_latt_deform(ob->parent, ob);
400                 
401                 if(ob->type==OB_MESH) {
402                         me= ob->data;
403                         
404                         dl= find_displist_create(&ob->disp, DL_VERTS);
405                         
406                         mvert= me->mvert;
407                         if(dl->verts) MEM_freeN(dl->verts);
408                         dl->nr= me->totvert;
409                         dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
410
411                         for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
412                                 if(lt_applyflag) calc_latt_deform(mvert->co);
413                                 else {
414                                         VECCOPY(fp, mvert->co);
415                                         calc_latt_deform(fp);
416                                 }
417                         }
418                 }
419                 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
420                 
421                         cu= ob->data;
422                         if(lt_applyflag) {
423                                 Nurb *nu;
424                                 BPoint *bp;
425                                 
426                                 nu= cu->nurb.first;
427                                 while(nu) {
428                                         if(nu->bp) {
429                                                 a= nu->pntsu*nu->pntsv;
430                                                 bp= nu->bp;
431                                                 while(a--) {
432                                                         calc_latt_deform(bp->vec);
433                                                         bp++;
434                                                 }
435                                         }
436                                         nu= nu->next;
437                                 }
438                         }
439                         
440                         /* when apply, do this too, looks more interactive */
441                         dl= cu->disp.first;
442                         while(dl) {
443                                 
444                                 fp= dl->verts;
445                                 
446                                 if(dl->type==DL_INDEX3) tot=dl->parts;
447                                 else tot= dl->nr*dl->parts;
448                                 
449                                 for(a=0; a<tot; a++, fp+=3) {
450                                         calc_latt_deform(fp);
451                                 }
452                                 
453                                 dl= dl->next;
454                         }
455                 }
456                 end_latt_deform();
457
458                 boundbox_displist(ob);  
459
460                 return 1;
461         }
462         else if(ob->parent->type==OB_ARMATURE) {
463                 if (ob->partype != PARSKEL){
464                         return 0;
465                 }
466                 
467                 init_armature_deform (ob->parent, ob);
468
469                 switch (ob->type){
470                 case OB_MESH:
471                         me= ob->data;
472                         
473                         dl= find_displist_create(&ob->disp, DL_VERTS);
474                         
475                         mvert= me->mvert;
476                         if(dl->verts) MEM_freeN(dl->verts);
477                         dl->nr= me->totvert;
478                         dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
479
480                         for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
481                                 if(lt_applyflag){
482                                         calc_armature_deform(ob->parent, mvert->co, a);
483                                 }
484                                 else {
485                                         VECCOPY(fp, mvert->co);
486                                         calc_armature_deform(ob->parent, fp, a);
487                                 }
488                         }
489
490                         break;
491                 default:
492                         break;
493                 }
494                 
495                 boundbox_displist(ob);  
496                 return 1;
497         }
498         else if(ob->parent->type==OB_IKA) {
499
500                 Ika *ika;
501                 
502                 if(ob->partype!=PARSKEL) return 0;
503                 
504                 ika= ob->parent->data;
505                 if(ika->def==0) return 0;
506                 
507                 init_skel_deform(ob->parent, ob);
508                 
509                 if(ob->type==OB_MESH) {
510                         me= ob->data;
511                         
512                         dl= find_displist_create(&ob->disp, DL_VERTS);
513                         
514                         mvert= me->mvert;
515                         if(dl->verts) MEM_freeN(dl->verts);
516                         dl->nr= me->totvert;
517                         dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
518
519                         for(a=0; a<me->totvert; a++, mvert++, fp+=3) {
520                                 if(lt_applyflag) calc_skel_deform(ika, mvert->co);
521                                 else {
522                                         VECCOPY(fp, mvert->co);
523                                         calc_skel_deform(ika, fp);
524                                 }
525                         }
526                 }
527                 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
528                 
529                         cu= ob->data;
530                         if(lt_applyflag) {
531                                 Nurb *nu;
532                                 BPoint *bp;
533                                 
534                                 nu= cu->nurb.first;
535                                 while(nu) {
536                                         if(nu->bp) {
537                                                 a= nu->pntsu*nu->pntsv;
538                                                 bp= nu->bp;
539                                                 while(a--) {
540                                                         calc_skel_deform(ika, bp->vec);
541                                                         bp++;
542                                                 }
543                                         }
544                                         nu= nu->next;
545                                 }
546                         }
547                         
548                         /* when apply, do this too, looks more interactive */
549                         dl= cu->disp.first;
550                         while(dl) {
551                                 
552                                 fp= dl->verts;
553                                 tot= dl->nr*dl->parts;
554                                 for(a=0; a<tot; a++, fp+=3) {
555                                         calc_skel_deform(ika, fp);
556                                 }
557                                 
558                                 dl= dl->next;
559                         }
560                 }
561                 
562                 boundbox_displist(ob);
563                 
564                 return 1;
565         }
566         
567         return 0;
568
569 }
570
571 BPoint *latt_bp(Lattice *lt, int u, int v, int w)
572 {
573         return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
574 }
575
576 void outside_lattice(Lattice *lt)
577 {
578         BPoint *bp, *bp1, *bp2;
579         int u, v, w;
580         float fac1, du=0.0, dv=0.0, dw=0.0;
581
582         bp= lt->def;
583
584         if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
585         if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
586         if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
587                 
588         for(w=0; w<lt->pntsw; w++) {
589                 
590                 for(v=0; v<lt->pntsv; v++) {
591                 
592                         for(u=0; u<lt->pntsu; u++, bp++) {
593                                 if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
594                                 else {
595                                 
596                                         bp->hide= 1;
597                                         bp->f1 &= ~SELECT;
598                                         
599                                         /* u extrema */
600                                         bp1= latt_bp(lt, 0, v, w);
601                                         bp2= latt_bp(lt, lt->pntsu-1, v, w);
602                                         
603                                         fac1= du*u;
604                                         bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
605                                         bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
606                                         bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
607                                         
608                                         /* v extrema */
609                                         bp1= latt_bp(lt, u, 0, w);
610                                         bp2= latt_bp(lt, u, lt->pntsv-1, w);
611                                         
612                                         fac1= dv*v;
613                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
614                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
615                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
616                                         
617                                         /* w extrema */
618                                         bp1= latt_bp(lt, u, v, 0);
619                                         bp2= latt_bp(lt, u, v, lt->pntsw-1);
620                                         
621                                         fac1= dw*w;
622                                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
623                                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
624                                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
625                                         
626                                         VecMulf(bp->vec, 0.3333333f);
627                                         
628                                 }
629                         }
630                         
631                 }
632                 
633         }
634         
635 }