Blender V2.61 - r43446

lattice.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <math.h>
00037 #include <stdlib.h>
00038 
00039 #include "MEM_guardedalloc.h"
00040 
00041 #include "BLI_blenlib.h"
00042 #include "BLI_bpath.h"
00043 #include "BLI_math.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "DNA_mesh_types.h"
00047 #include "DNA_meshdata_types.h"
00048 #include "DNA_scene_types.h"
00049 #include "DNA_object_types.h"
00050 #include "DNA_lattice_types.h"
00051 #include "DNA_curve_types.h"
00052 #include "DNA_key_types.h"
00053 
00054 #include "BKE_animsys.h"
00055 #include "BKE_anim.h"
00056 #include "BKE_cdderivedmesh.h"
00057 #include "BKE_displist.h"
00058 #include "BKE_global.h"
00059 #include "BKE_key.h"
00060 #include "BKE_lattice.h"
00061 #include "BKE_library.h"
00062 #include "BKE_main.h"
00063 #include "BKE_mesh.h"
00064 #include "BKE_modifier.h"
00065 
00066 #include "BKE_deform.h"
00067 
00068 //XXX #include "BIF_editdeform.h"
00069 
00070 void calc_lat_fudu(int flag, int res, float *fu, float *du)
00071 {
00072     if(res==1) {
00073         *fu= 0.0;
00074         *du= 0.0;
00075     }
00076     else if(flag & LT_GRID) {
00077         *fu= -0.5f*(res-1);
00078         *du= 1.0f;
00079     }
00080     else {
00081         *fu= -1.0f;
00082         *du= 2.0f/(res-1);
00083     }
00084 }
00085 
00086 void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
00087 {
00088     BPoint *bp;
00089     int i, u, v, w;
00090     float fu, fv, fw, uc, vc, wc, du=0.0, dv=0.0, dw=0.0;
00091     float *co, (*vertexCos)[3] = NULL;
00092     
00093     /* vertex weight groups are just freed all for now */
00094     if(lt->dvert) {
00095         free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
00096         lt->dvert= NULL;
00097     }
00098     
00099     while(uNew*vNew*wNew > 32000) {
00100         if( uNew>=vNew && uNew>=wNew) uNew--;
00101         else if( vNew>=uNew && vNew>=wNew) vNew--;
00102         else wNew--;
00103     }
00104 
00105     vertexCos = MEM_mallocN(sizeof(*vertexCos)*uNew*vNew*wNew, "tmp_vcos");
00106 
00107     calc_lat_fudu(lt->flag, uNew, &fu, &du);
00108     calc_lat_fudu(lt->flag, vNew, &fv, &dv);
00109     calc_lat_fudu(lt->flag, wNew, &fw, &dw);
00110 
00111         /* If old size is different then resolution changed in interface,
00112          * try to do clever reinit of points. Pretty simply idea, we just
00113          * deform new verts by old lattice, but scaling them to match old
00114          * size first.
00115          */
00116     if (ltOb) {
00117         if (uNew!=1 && lt->pntsu!=1) {
00118             fu = lt->fu;
00119             du = (lt->pntsu-1)*lt->du/(uNew-1);
00120         }
00121 
00122         if (vNew!=1 && lt->pntsv!=1) {
00123             fv = lt->fv;
00124             dv = (lt->pntsv-1)*lt->dv/(vNew-1);
00125         }
00126 
00127         if (wNew!=1 && lt->pntsw!=1) {
00128             fw = lt->fw;
00129             dw = (lt->pntsw-1)*lt->dw/(wNew-1);
00130         }
00131     }
00132 
00133     co = vertexCos[0];
00134     for(w=0,wc=fw; w<wNew; w++,wc+=dw) {
00135         for(v=0,vc=fv; v<vNew; v++,vc+=dv) {
00136             for(u=0,uc=fu; u<uNew; u++,co+=3,uc+=du) {
00137                 co[0] = uc;
00138                 co[1] = vc;
00139                 co[2] = wc;
00140             }
00141         }
00142     }
00143     
00144     if (ltOb) {
00145         float mat[4][4];
00146         int typeu = lt->typeu, typev = lt->typev, typew = lt->typew;
00147 
00148             /* works best if we force to linear type (endpoints match) */
00149         lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
00150 
00151             /* prevent using deformed locations */
00152         freedisplist(&ltOb->disp);
00153 
00154         copy_m4_m4(mat, ltOb->obmat);
00155         unit_m4(ltOb->obmat);
00156         lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew*vNew*wNew, NULL);
00157         copy_m4_m4(ltOb->obmat, mat);
00158 
00159         lt->typeu = typeu;
00160         lt->typev = typev;
00161         lt->typew = typew;
00162     }
00163 
00164     lt->fu = fu;
00165     lt->fv = fv;
00166     lt->fw = fw;
00167     lt->du = du;
00168     lt->dv = dv;
00169     lt->dw = dw;
00170 
00171     lt->pntsu = uNew;
00172     lt->pntsv = vNew;
00173     lt->pntsw = wNew;
00174 
00175     MEM_freeN(lt->def);
00176     lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp");
00177     
00178     bp= lt->def;
00179     
00180     for (i=0; i<lt->pntsu*lt->pntsv*lt->pntsw; i++,bp++) {
00181         copy_v3_v3(bp->vec, vertexCos[i]);
00182     }
00183 
00184     MEM_freeN(vertexCos);
00185 }
00186 
00187 Lattice *add_lattice(const char *name)
00188 {
00189     Lattice *lt;
00190     
00191     lt= alloc_libblock(&G.main->latt, ID_LT, name);
00192     
00193     lt->flag= LT_GRID;
00194     
00195     lt->typeu= lt->typev= lt->typew= KEY_BSPLINE;
00196     
00197     lt->def= MEM_callocN(sizeof(BPoint), "lattvert"); /* temporary */
00198     resizelattice(lt, 2, 2, 2, NULL);   /* creates a uniform lattice */
00199         
00200     return lt;
00201 }
00202 
00203 Lattice *copy_lattice(Lattice *lt)
00204 {
00205     Lattice *ltn;
00206 
00207     ltn= copy_libblock(&lt->id);
00208     ltn->def= MEM_dupallocN(lt->def);
00209 
00210     ltn->key= copy_key(ltn->key);
00211     if(ltn->key) ltn->key->from= (ID *)ltn;
00212     
00213     if(lt->dvert) {
00214         int tot= lt->pntsu*lt->pntsv*lt->pntsw;
00215         ltn->dvert = MEM_mallocN (sizeof (MDeformVert)*tot, "Lattice MDeformVert");
00216         copy_dverts(ltn->dvert, lt->dvert, tot);
00217     }
00218 
00219     ltn->editlatt= NULL;
00220 
00221     return ltn;
00222 }
00223 
00224 void free_lattice(Lattice *lt)
00225 {
00226     if(lt->def) MEM_freeN(lt->def);
00227     if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
00228     if(lt->editlatt) {
00229         Lattice *editlt= lt->editlatt->latt;
00230 
00231         if(editlt->def) MEM_freeN(editlt->def);
00232         if(editlt->dvert) free_dverts(editlt->dvert, lt->pntsu*lt->pntsv*lt->pntsw);
00233 
00234         MEM_freeN(editlt);
00235         MEM_freeN(lt->editlatt);
00236     }
00237     
00238     /* free animation data */
00239     if (lt->adt) {
00240         BKE_free_animdata(&lt->id);
00241         lt->adt= NULL;
00242     }
00243 }
00244 
00245 
00246 void make_local_lattice(Lattice *lt)
00247 {
00248     Main *bmain= G.main;
00249     Object *ob;
00250     int is_local= FALSE, is_lib= FALSE;
00251 
00252     /* - only lib users: do nothing
00253      * - only local users: set flag
00254      * - mixed: make copy
00255      */
00256     
00257     if(lt->id.lib==NULL) return;
00258     if(lt->id.us==1) {
00259         id_clear_lib_data(bmain, &lt->id);
00260         return;
00261     }
00262     
00263     for(ob= bmain->object.first; ob && ELEM(FALSE, is_lib, is_local); ob= ob->id.next) {
00264         if(ob->data==lt) {
00265             if(ob->id.lib) is_lib= TRUE;
00266             else is_local= TRUE;
00267         }
00268     }
00269     
00270     if(is_local && is_lib==FALSE) {
00271         id_clear_lib_data(bmain, &lt->id);
00272     }
00273     else if(is_local && is_lib) {
00274         Lattice *lt_new= copy_lattice(lt);
00275         lt_new->id.us= 0;
00276 
00277         /* Remap paths of new ID using old library as base. */
00278         BKE_id_lib_local_paths(bmain, lt->id.lib, &lt_new->id);
00279 
00280         for(ob= bmain->object.first; ob; ob= ob->id.next) {
00281             if(ob->data==lt) {
00282                 if(ob->id.lib==NULL) {
00283                     ob->data= lt_new;
00284                     lt_new->id.us++;
00285                     lt->id.us--;
00286                 }
00287             }
00288         }
00289     }
00290 }
00291 
00292 void init_latt_deform(Object *oblatt, Object *ob)
00293 {
00294         /* we make an array with all differences */
00295     Lattice *lt= oblatt->data;
00296     BPoint *bp;
00297     DispList *dl = find_displist(&oblatt->disp, DL_VERTS);
00298     float *co = dl?dl->verts:NULL;
00299     float *fp, imat[4][4];
00300     float fu, fv, fw;
00301     int u, v, w;
00302 
00303     if(lt->editlatt) lt= lt->editlatt->latt;
00304     bp = lt->def;
00305     
00306     fp= lt->latticedata= MEM_mallocN(sizeof(float)*3*lt->pntsu*lt->pntsv*lt->pntsw, "latticedata");
00307     
00308         /* for example with a particle system: ob==0 */
00309     if(ob==NULL) {
00310         /* in deformspace, calc matrix  */
00311         invert_m4_m4(lt->latmat, oblatt->obmat);
00312     
00313         /* back: put in deform array */
00314         invert_m4_m4(imat, lt->latmat);
00315     }
00316     else {
00317         /* in deformspace, calc matrix */
00318         invert_m4_m4(imat, oblatt->obmat);
00319         mult_m4_m4m4(lt->latmat, imat, ob->obmat);
00320     
00321         /* back: put in deform array */
00322         invert_m4_m4(imat, lt->latmat);
00323     }
00324     
00325     for(w=0,fw=lt->fw; w<lt->pntsw; w++,fw+=lt->dw) {
00326         for(v=0,fv=lt->fv; v<lt->pntsv; v++, fv+=lt->dv) {
00327             for(u=0,fu=lt->fu; u<lt->pntsu; u++, bp++, co+=3, fp+=3, fu+=lt->du) {
00328                 if (dl) {
00329                     fp[0] = co[0] - fu;
00330                     fp[1] = co[1] - fv;
00331                     fp[2] = co[2] - fw;
00332                 } else {
00333                     fp[0] = bp->vec[0] - fu;
00334                     fp[1] = bp->vec[1] - fv;
00335                     fp[2] = bp->vec[2] - fw;
00336                 }
00337 
00338                 mul_mat3_m4_v3(imat, fp);
00339             }
00340         }
00341     }
00342 }
00343 
00344 void calc_latt_deform(Object *ob, float *co, float weight)
00345 {
00346     Lattice *lt= ob->data;
00347     float u, v, w, tu[4], tv[4], tw[4];
00348     float vec[3];
00349     int idx_w, idx_v, idx_u;
00350     int ui, vi, wi, uu, vv, ww;
00351 
00352     /* vgroup influence */
00353     int defgroup_nr= -1;
00354     float co_prev[3], weight_blend= 0.0f;
00355     MDeformVert *dvert= lattice_get_deform_verts(ob);
00356 
00357 
00358     if(lt->editlatt) lt= lt->editlatt->latt;
00359     if(lt->latticedata==NULL) return;
00360 
00361     if(lt->vgroup[0] && dvert) {
00362         defgroup_nr= defgroup_name_index(ob, lt->vgroup);
00363         copy_v3_v3(co_prev, co);
00364     }
00365 
00366     /* co is in local coords, treat with latmat */
00367     mul_v3_m4v3(vec, lt->latmat, co);
00368 
00369     /* u v w coords */
00370 
00371     if(lt->pntsu>1) {
00372         u= (vec[0]-lt->fu)/lt->du;
00373         ui= (int)floor(u);
00374         u -= ui;
00375         key_curve_position_weights(u, tu, lt->typeu);
00376     }
00377     else {
00378         tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0;
00379         ui= 0;
00380     }
00381 
00382     if(lt->pntsv>1) {
00383         v= (vec[1]-lt->fv)/lt->dv;
00384         vi= (int)floor(v);
00385         v -= vi;
00386         key_curve_position_weights(v, tv, lt->typev);
00387     }
00388     else {
00389         tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0;
00390         vi= 0;
00391     }
00392 
00393     if(lt->pntsw>1) {
00394         w= (vec[2]-lt->fw)/lt->dw;
00395         wi= (int)floor(w);
00396         w -= wi;
00397         key_curve_position_weights(w, tw, lt->typew);
00398     }
00399     else {
00400         tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0;
00401         wi= 0;
00402     }
00403 
00404     for(ww= wi-1; ww<=wi+2; ww++) {
00405         w= tw[ww-wi+1];
00406 
00407         if(w != 0.0f) {
00408             if(ww>0) {
00409                 if(ww<lt->pntsw) idx_w= ww*lt->pntsu*lt->pntsv;
00410                 else idx_w= (lt->pntsw-1)*lt->pntsu*lt->pntsv;
00411             }
00412             else idx_w= 0;
00413 
00414             for(vv= vi-1; vv<=vi+2; vv++) {
00415                 v= w*tv[vv-vi+1];
00416 
00417                 if(v != 0.0f) {
00418                     if(vv>0) {
00419                         if(vv<lt->pntsv) idx_v= idx_w + vv*lt->pntsu;
00420                         else idx_v= idx_w + (lt->pntsv-1)*lt->pntsu;
00421                     }
00422                     else idx_v= idx_w;
00423 
00424                     for(uu= ui-1; uu<=ui+2; uu++) {
00425                         u= weight*v*tu[uu-ui+1];
00426 
00427                         if(u != 0.0f) {
00428                             if(uu>0) {
00429                                 if(uu<lt->pntsu) idx_u= idx_v + uu;
00430                                 else idx_u= idx_v + (lt->pntsu-1);
00431                             }
00432                             else idx_u= idx_v;
00433 
00434                             madd_v3_v3fl(co, &lt->latticedata[idx_u * 3], u);
00435 
00436                             if(defgroup_nr != -1)
00437                                 weight_blend += (u * defvert_find_weight(dvert + idx_u, defgroup_nr));
00438                         }
00439                     }
00440                 }
00441             }
00442         }
00443     }
00444 
00445     if(defgroup_nr != -1)
00446         interp_v3_v3v3(co, co_prev, co, weight_blend);
00447 
00448 }
00449 
00450 void end_latt_deform(Object *ob)
00451 {
00452     Lattice *lt= ob->data;
00453     
00454     if(lt->editlatt) lt= lt->editlatt->latt;
00455     
00456     if(lt->latticedata)
00457         MEM_freeN(lt->latticedata);
00458     lt->latticedata= NULL;
00459 }
00460 
00461     /* calculations is in local space of deformed object
00462        so we store in latmat transform from path coord inside object 
00463      */
00464 typedef struct {
00465     float dmin[3], dmax[3], dscale, dloc[3];
00466     float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
00467     int no_rot_axis;
00468 } CurveDeform;
00469 
00470 static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc)
00471 {
00472     invert_m4_m4(ob->imat, ob->obmat);
00473     mult_m4_m4m4(cd->objectspace, ob->imat, par->obmat);
00474     invert_m4_m4(cd->curvespace, cd->objectspace);
00475     copy_m3_m4(cd->objectspace3, cd->objectspace);
00476     
00477     // offset vector for 'no smear'
00478     if(dloc) {
00479         invert_m4_m4(par->imat, par->obmat);
00480         mul_v3_m4v3(cd->dloc, par->imat, ob->obmat[3]);
00481     }
00482     else {
00483         cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f;
00484     }
00485     
00486     cd->no_rot_axis= 0;
00487 }
00488 
00489 /* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
00490 static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius)    /* returns OK */
00491 {
00492     Curve *cu= ob->data;
00493     BevList *bl;
00494     float ctime1;
00495     int cycl=0;
00496     
00497     /* test for cyclic */
00498     bl= cu->bev.first;
00499     if (!bl->nr) return 0;
00500     if(bl && bl->poly> -1) cycl= 1;
00501 
00502     if(cycl==0) {
00503         ctime1= CLAMPIS(ctime, 0.0f, 1.0f);
00504     }
00505     else ctime1= ctime;
00506     
00507     /* vec needs 4 items */
00508     if(where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
00509         
00510         if(cycl==0) {
00511             Path *path= cu->path;
00512             float dvec[3];
00513             
00514             if(ctime < 0.0f) {
00515                 sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
00516                 mul_v3_fl(dvec, ctime*(float)path->len);
00517                 add_v3_v3(vec, dvec);
00518                 if(quat) copy_qt_qt(quat, path->data[0].quat);
00519                 if(radius) *radius= path->data[0].radius;
00520             }
00521             else if(ctime > 1.0f) {
00522                 sub_v3_v3v3(dvec, path->data[path->len-1].vec, path->data[path->len-2].vec);
00523                 mul_v3_fl(dvec, (ctime-1.0f)*(float)path->len);
00524                 add_v3_v3(vec, dvec);
00525                 if(quat) copy_qt_qt(quat, path->data[path->len-1].quat);
00526                 if(radius) *radius= path->data[path->len-1].radius;
00527                 /* weight - not used but could be added */
00528             }
00529         }
00530         return 1;
00531     }
00532     return 0;
00533 }
00534 
00535     /* for each point, rotate & translate to curve */
00536     /* use path, since it has constant distances */
00537     /* co: local coord, result local too */
00538     /* returns quaternion for rotation, using cd->no_rot_axis */
00539     /* axis is using another define!!! */
00540 static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp)
00541 {
00542     Curve *cu= par->data;
00543     float fac, loc[4], dir[3], new_quat[4], radius;
00544     short /*upflag, */ index;
00545 
00546     index= axis-1;
00547     if(index>2)
00548         index -= 3; /* negative  */
00549 
00550     /* to be sure, mostly after file load */
00551     if(cu->path==NULL) {
00552         makeDispListCurveTypes(scene, par, 0);
00553         if(cu->path==NULL) return 0;    // happens on append...
00554     }
00555     
00556     /* options */
00557     if(ELEM3(axis, OB_NEGX+1, OB_NEGY+1, OB_NEGZ+1)) { /* OB_NEG# 0-5, MOD_CURVE_POS# 1-6 */
00558         if(cu->flag & CU_STRETCH)
00559             fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]);
00560         else
00561             fac= (cd->dloc[index])/(cu->path->totdist) - (co[index]-cd->dmax[index])/(cu->path->totdist);
00562     }
00563     else {
00564         if(cu->flag & CU_STRETCH)
00565             fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
00566         else
00567             fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
00568     }
00569     
00570 #if 0 // XXX old animation system
00571     /* we want the ipo to work on the default 100 frame range, because there's no  
00572        actual time involved in path position */
00573     // huh? by WHY!!!!???? - Aligorith
00574     if(cu->ipo) {
00575         fac*= 100.0f;
00576         if(calc_ipo_spec(cu->ipo, CU_SPEED, &fac)==0)
00577             fac/= 100.0;
00578     }
00579 #endif // XXX old animation system
00580     
00581     if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) {  /* returns OK */
00582         float quat[4], cent[3];
00583 
00584 #if 0   // XXX - 2.4x Z-Up, Now use bevel tilt.
00585         if(cd->no_rot_axis) /* set by caller */
00586             dir[cd->no_rot_axis-1]= 0.0f;
00587         
00588         /* -1 for compatibility with old track defines */
00589         vec_to_quat( quat,dir, axis-1, upflag);
00590         
00591         /* the tilt */
00592         if(loc[3]!=0.0) {
00593             normalize_v3(dir);
00594             q[0]= (float)cos(0.5*loc[3]);
00595             fac= (float)sin(0.5*loc[3]);
00596             q[1]= -fac*dir[0];
00597             q[2]= -fac*dir[1];
00598             q[3]= -fac*dir[2];
00599             mul_qt_qtqt(quat, q, quat);
00600         }
00601 #endif
00602 
00603         if(cd->no_rot_axis) {   /* set by caller */
00604 
00605             /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather than
00606              * changing the axis before calculating the tilt but serves much the same purpose */
00607             float dir_flat[3]={0,0,0}, q[4];
00608             copy_v3_v3(dir_flat, dir);
00609             dir_flat[cd->no_rot_axis-1]= 0.0f;
00610 
00611             normalize_v3(dir);
00612             normalize_v3(dir_flat);
00613 
00614             rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
00615 
00616             mul_qt_qtqt(new_quat, q, new_quat);
00617         }
00618 
00619 
00620         /* Logic for 'cent' orientation *
00621          *
00622          * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
00623          *
00624          * Use a curve modifier to stretch a cube out, color each side RGB, positive side light, negative dark.
00625          * view with X up (default), from the angle that you can see 3 faces RGB colors (light), anti-clockwise
00626          * Notice X,Y,Z Up all have light colors and each ordered CCW.
00627          *
00628          * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
00629          *
00630          * note: moved functions into quat_apply_track/vec_apply_track
00631          * */
00632         copy_qt_qt(quat, new_quat);
00633         copy_v3_v3(cent, co);
00634 
00635         /* zero the axis which is not used,
00636          * the big block of text above now applies to these 3 lines */
00637         quat_apply_track(quat, axis-1, (axis==1 || axis==3) ? 1:0); /* up flag is a dummy, set so no rotation is done */
00638         vec_apply_track(cent, axis-1);
00639         cent[axis < 4 ? axis-1 : axis-4]= 0.0f;
00640 
00641 
00642         /* scale if enabled */
00643         if(cu->flag & CU_PATH_RADIUS)
00644             mul_v3_fl(cent, radius);
00645         
00646         /* local rotation */
00647         normalize_qt(quat);
00648         mul_qt_v3(quat, cent);
00649 
00650         /* translation */
00651         add_v3_v3v3(co, cent, loc);
00652 
00653         if(quatp)
00654             copy_qt_qt(quatp, quat);
00655 
00656         return 1;
00657     }
00658     return 0;
00659 }
00660 
00661 void curve_deform_verts(Scene *scene, Object *cuOb, Object *target,
00662                         DerivedMesh *dm, float (*vertexCos)[3],
00663                         int numVerts, const char *vgroup, short defaxis)
00664 {
00665     Curve *cu;
00666     int a, flag;
00667     CurveDeform cd;
00668     int use_vgroups;
00669 
00670     if(cuOb->type != OB_CURVE)
00671         return;
00672 
00673     cu = cuOb->data;
00674     flag = cu->flag;
00675     cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
00676 
00677     init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0);
00678 
00679     /* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
00680     if(defaxis < 3) {
00681         cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= 0.0f;
00682         cd.dmax[0]= cd.dmax[1]= cd.dmax[2]= 1.0f;
00683     }
00684     else {
00685         /* negative, these bounds give a good rest position */
00686         cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= -1.0f;
00687         cd.dmax[0]= cd.dmax[1]= cd.dmax[2]=  0.0f;
00688     }
00689     
00690     /* check whether to use vertex groups (only possible if target is a Mesh)
00691      * we want either a Mesh with no derived data, or derived data with
00692      * deformverts
00693      */
00694     if(target && target->type==OB_MESH) {
00695         /* if there's derived data without deformverts, don't use vgroups */
00696         if(dm && !dm->getVertData(dm, 0, CD_MDEFORMVERT))
00697             use_vgroups = 0;
00698         else
00699             use_vgroups = 1;
00700     } else
00701         use_vgroups = 0;
00702     
00703     if(vgroup && vgroup[0] && use_vgroups) {
00704         Mesh *me= target->data;
00705         int index= defgroup_name_index(target, vgroup);
00706 
00707         if(index != -1 && (me->dvert || dm)) {
00708             MDeformVert *dvert = me->dvert;
00709             float vec[3];
00710             float weight;
00711     
00712 
00713             if(cu->flag & CU_DEFORM_BOUNDS_OFF) {
00714                 /* dummy bounds */
00715                 cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= 0.0f;
00716                 cd.dmax[0]= cd.dmax[1]= cd.dmax[2]= 1.0f;
00717                 
00718                 dvert = me->dvert;
00719                 for(a = 0; a < numVerts; a++, dvert++) {
00720                     if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
00721                     weight= defvert_find_weight(dvert, index);
00722     
00723                     if(weight > 0.0f) {
00724                         mul_m4_v3(cd.curvespace, vertexCos[a]);
00725                         copy_v3_v3(vec, vertexCos[a]);
00726                         calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
00727                         interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
00728                         mul_m4_v3(cd.objectspace, vertexCos[a]);
00729                     }
00730                 }
00731             }
00732             else {
00733                 /* set mesh min/max bounds */
00734                 INIT_MINMAX(cd.dmin, cd.dmax);
00735     
00736                 for(a = 0; a < numVerts; a++, dvert++) {
00737                     if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
00738                     
00739                     if(defvert_find_weight(dvert, index) > 0.0f) {
00740                         mul_m4_v3(cd.curvespace, vertexCos[a]);
00741                         DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
00742                     }
00743                 }
00744     
00745                 dvert = me->dvert;
00746                 for(a = 0; a < numVerts; a++, dvert++) {
00747                     if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
00748                     
00749                     weight= defvert_find_weight(dvert, index);
00750     
00751                     if(weight > 0.0f) {
00752                         copy_v3_v3(vec, vertexCos[a]);
00753                         calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
00754                         interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
00755                         mul_m4_v3(cd.objectspace, vertexCos[a]);
00756                     }
00757                 }
00758             }
00759         }
00760     }
00761     else {
00762         if(cu->flag & CU_DEFORM_BOUNDS_OFF) {
00763             for(a = 0; a < numVerts; a++) {
00764                 mul_m4_v3(cd.curvespace, vertexCos[a]);
00765                 calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
00766                 mul_m4_v3(cd.objectspace, vertexCos[a]);
00767             }
00768         }
00769         else {
00770             /* set mesh min max bounds */
00771             INIT_MINMAX(cd.dmin, cd.dmax);
00772                 
00773             for(a = 0; a < numVerts; a++) {
00774                 mul_m4_v3(cd.curvespace, vertexCos[a]);
00775                 DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
00776             }
00777     
00778             for(a = 0; a < numVerts; a++) {
00779                 calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
00780                 mul_m4_v3(cd.objectspace, vertexCos[a]);
00781             }
00782         }
00783     }
00784     cu->flag = flag;
00785 }
00786 
00787 /* input vec and orco = local coord in armature space */
00788 /* orco is original not-animated or deformed reference point */
00789 /* result written in vec and mat */
00790 void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, float *orco, float *vec, float mat[][3], int no_rot_axis)
00791 {
00792     CurveDeform cd;
00793     float quat[4];
00794     
00795     if(cuOb->type != OB_CURVE) {
00796         unit_m3(mat);
00797         return;
00798     }
00799 
00800     init_curve_deform(cuOb, target, &cd, 0);    /* 0 no dloc */
00801     cd.no_rot_axis= no_rot_axis;                /* option to only rotate for XY, for example */
00802     
00803     copy_v3_v3(cd.dmin, orco);
00804     copy_v3_v3(cd.dmax, orco);
00805 
00806     mul_m4_v3(cd.curvespace, vec);
00807     
00808     if(calc_curve_deform(scene, cuOb, vec, target->trackflag+1, &cd, quat)) {
00809         float qmat[3][3];
00810         
00811         quat_to_mat3( qmat,quat);
00812         mul_m3_m3m3(mat, qmat, cd.objectspace3);
00813     }
00814     else
00815         unit_m3(mat);
00816     
00817     mul_m4_v3(cd.objectspace, vec);
00818 
00819 }
00820 
00821 void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
00822                           float (*vertexCos)[3], int numVerts, const char *vgroup)
00823 {
00824     int a;
00825     int use_vgroups;
00826 
00827     if(laOb->type != OB_LATTICE)
00828         return;
00829 
00830     init_latt_deform(laOb, target);
00831 
00832     /* check whether to use vertex groups (only possible if target is a Mesh)
00833      * we want either a Mesh with no derived data, or derived data with
00834      * deformverts
00835      */
00836     if(target && target->type==OB_MESH) {
00837         /* if there's derived data without deformverts, don't use vgroups */
00838         if(dm && !dm->getVertData(dm, 0, CD_MDEFORMVERT))
00839             use_vgroups = 0;
00840         else
00841             use_vgroups = 1;
00842     } else
00843         use_vgroups = 0;
00844     
00845     if(vgroup && vgroup[0] && use_vgroups) {
00846         Mesh *me = target->data;
00847         int index = defgroup_name_index(target, vgroup);
00848         float weight;
00849 
00850         if(index >= 0 && (me->dvert || dm)) {
00851             MDeformVert *dvert = me->dvert;
00852             
00853             for(a = 0; a < numVerts; a++, dvert++) {
00854                 if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
00855 
00856                 weight= defvert_find_weight(dvert, index);
00857 
00858                 if(weight > 0.0f)
00859                     calc_latt_deform(laOb, vertexCos[a], weight);
00860             }
00861         }
00862     } else {
00863         for(a = 0; a < numVerts; a++) {
00864             calc_latt_deform(laOb, vertexCos[a], 1.0f);
00865         }
00866     }
00867     end_latt_deform(laOb);
00868 }
00869 
00870 int object_deform_mball(Object *ob, ListBase *dispbase)
00871 {
00872     if(ob->parent && ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
00873         DispList *dl;
00874 
00875         for (dl=dispbase->first; dl; dl=dl->next) {
00876             lattice_deform_verts(ob->parent, ob, NULL,
00877                                  (float(*)[3]) dl->verts, dl->nr, NULL);
00878         }
00879 
00880         return 1;
00881     } else {
00882         return 0;
00883     }
00884 }
00885 
00886 static BPoint *latt_bp(Lattice *lt, int u, int v, int w)
00887 {
00888     return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv;
00889 }
00890 
00891 void outside_lattice(Lattice *lt)
00892 {
00893     BPoint *bp, *bp1, *bp2;
00894     int u, v, w;
00895     float fac1, du=0.0, dv=0.0, dw=0.0;
00896 
00897     if(lt->flag & LT_OUTSIDE) {
00898         bp= lt->def;
00899 
00900         if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1);
00901         if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1);
00902         if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1);
00903             
00904         for(w=0; w<lt->pntsw; w++) {
00905             
00906             for(v=0; v<lt->pntsv; v++) {
00907             
00908                 for(u=0; u<lt->pntsu; u++, bp++) {
00909                     if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1);
00910                     else {
00911                     
00912                         bp->hide= 1;
00913                         bp->f1 &= ~SELECT;
00914                         
00915                         /* u extrema */
00916                         bp1= latt_bp(lt, 0, v, w);
00917                         bp2= latt_bp(lt, lt->pntsu-1, v, w);
00918                         
00919                         fac1= du*u;
00920                         bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
00921                         bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
00922                         bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
00923                         
00924                         /* v extrema */
00925                         bp1= latt_bp(lt, u, 0, w);
00926                         bp2= latt_bp(lt, u, lt->pntsv-1, w);
00927                         
00928                         fac1= dv*v;
00929                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
00930                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
00931                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
00932                         
00933                         /* w extrema */
00934                         bp1= latt_bp(lt, u, v, 0);
00935                         bp2= latt_bp(lt, u, v, lt->pntsw-1);
00936                         
00937                         fac1= dw*w;
00938                         bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0];
00939                         bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1];
00940                         bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2];
00941                         
00942                         mul_v3_fl(bp->vec, 0.3333333f);
00943                         
00944                     }
00945                 }
00946                 
00947             }
00948             
00949         }
00950     }
00951     else {
00952         bp= lt->def;
00953 
00954         for(w=0; w<lt->pntsw; w++)
00955             for(v=0; v<lt->pntsv; v++)
00956                 for(u=0; u<lt->pntsu; u++, bp++)
00957                     bp->hide= 0;
00958     }
00959 }
00960 
00961 float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3]
00962 {
00963     Lattice *lt = ob->data;
00964     int i, numVerts;
00965     float (*vertexCos)[3];
00966 
00967     if(lt->editlatt) lt= lt->editlatt->latt;
00968     numVerts = *numVerts_r = lt->pntsu*lt->pntsv*lt->pntsw;
00969     
00970     vertexCos = MEM_mallocN(sizeof(*vertexCos)*numVerts,"lt_vcos");
00971     
00972     for (i=0; i<numVerts; i++) {
00973         copy_v3_v3(vertexCos[i], lt->def[i].vec);
00974     }
00975 
00976     return vertexCos;
00977 }
00978 
00979 void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3])
00980 {
00981     Lattice *lt = ob->data;
00982     int i, numVerts = lt->pntsu*lt->pntsv*lt->pntsw;
00983 
00984     for (i=0; i<numVerts; i++) {
00985         copy_v3_v3(lt->def[i].vec, vertexCos[i]);
00986     }
00987 }
00988 
00989 void lattice_calc_modifiers(Scene *scene, Object *ob)
00990 {
00991     Lattice *lt= ob->data;
00992     ModifierData *md = modifiers_getVirtualModifierList(ob);
00993     float (*vertexCos)[3] = NULL;
00994     int numVerts, editmode = (lt->editlatt!=NULL);
00995 
00996     freedisplist(&ob->disp);
00997 
00998     for (; md; md=md->next) {
00999         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
01000 
01001         md->scene= scene;
01002         
01003         if (!(md->mode&eModifierMode_Realtime)) continue;
01004         if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
01005         if (mti->isDisabled && mti->isDisabled(md, 0)) continue;
01006         if (mti->type!=eModifierTypeType_OnlyDeform) continue;
01007 
01008         if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts);
01009         mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0);
01010     }
01011 
01012     /* always displist to make this work like derivedmesh */
01013     if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts);
01014     
01015     {
01016         DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl");
01017         dl->type = DL_VERTS;
01018         dl->parts = 1;
01019         dl->nr = numVerts;
01020         dl->verts = (float*) vertexCos;
01021         
01022         BLI_addtail(&ob->disp, dl);
01023     }
01024 }
01025 
01026 struct MDeformVert* lattice_get_deform_verts(struct Object *oblatt)
01027 {
01028     Lattice *lt = (Lattice*)oblatt->data;
01029     BLI_assert(oblatt->type == OB_LATTICE);
01030     if(lt->editlatt) lt= lt->editlatt->latt;
01031     return lt->dvert;
01032 }