/** * lattice.c MIXED MODEL * june 2001 ton * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include #include #include #include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "DNA_armature_types.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_lattice_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_ika_types.h" #include "BKE_utildefines.h" #include "BKE_armature.h" #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_screen.h" #include "BKE_displist.h" #include "BKE_lattice.h" #include "BKE_key.h" #include "BKE_object.h" #include "BKE_ika.h" Lattice *editLatt=0, *deformLatt=0; float *latticedata=0, latmat[4][4]; int lt_applyflag= 0; void resizelattice(Lattice *lt) { BPoint *bp; int u, v, w; float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0; MEM_freeN(lt->def); lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp"); bp= lt->def; while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) { if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--; else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--; else lt->pntsw--; } calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du); calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv); calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw); vec[2]= fw; for(w=0; wpntsw; w++) { vec[1]= fv; for(v=0; vpntsv; v++) { vec[0]= fu; for(u=0; upntsu; u++, bp++) { VECCOPY(bp->vec, vec); vec[0]+= du; } vec[1]+= dv; } vec[2]+= dw; } } Lattice *add_lattice() { Lattice *lt; lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice"); lt->pntsu=lt->pntsv=lt->pntsw= 2; lt->flag= LT_GRID; lt->typeu= lt->typev= lt->typew= KEY_BSPLINE; /* tijdelijk */ lt->def= MEM_callocN(sizeof(BPoint), "lattvert"); resizelattice(lt); /* maakt een regelmatige lattice */ return lt; } Lattice *copy_lattice(Lattice *lt) { Lattice *ltn; ltn= copy_libblock(lt); ltn->def= MEM_dupallocN(lt->def); id_us_plus((ID *)ltn->ipo); ltn->key= copy_key(ltn->key); if(ltn->key) ltn->key->from= (ID *)ltn; return ltn; } void free_lattice(Lattice *lt) { if(lt->def) MEM_freeN(lt->def); } void make_local_lattice(Lattice *lt) { Object *ob; Lattice *ltn; int local=0, lib=0; /* - zijn er alleen lib users: niet doen * - zijn er alleen locale users: flag zetten * - mixed: copy */ if(lt->id.lib==0) return; if(lt->id.us==1) { lt->id.lib= 0; lt->id.flag= LIB_LOCAL; new_id(0, (ID *)lt, 0); return; } ob= G.main->object.first; while(ob) { if(ob->data==lt) { if(ob->id.lib) lib= 1; else local= 1; } ob= ob->id.next; } if(local && lib==0) { lt->id.lib= 0; lt->id.flag= LIB_LOCAL; new_id(0, (ID *)lt, 0); } else if(local && lib) { ltn= copy_lattice(lt); ltn->id.us= 0; ob= G.main->object.first; while(ob) { if(ob->data==lt) { if(ob->id.lib==0) { ob->data= ltn; ltn->id.us++; lt->id.us--; } } ob= ob->id.next; } } } void calc_lat_fudu(int flag, int res, float *fu, float *du) { if(res==1) { *fu= 0.0; *du= 0.0; } else if(flag & LT_GRID) { *fu= -0.5f*(res-1); *du= 1.0f; } else { *fu= -1.0f; *du= 2.0f/(res-1); } } void init_latt_deform(Object *oblatt, Object *ob) { /* we maken een array met alle verschillen */ BPoint *bp; float *fp, imat[4][4]; float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0; int u, v, w; if(oblatt==G.obedit) deformLatt= editLatt; else deformLatt= oblatt->data; fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata"); bp= deformLatt->def; if(ob) where_is_object(ob); /* bijv bij particle systeem: ob==0 */ if(ob==0) { /* in deformspace, matrix berekenen */ Mat4Invert(latmat, oblatt->obmat); /* terug: in deform array verwerken */ Mat4Invert(imat, latmat); } else { /* in deformspace, matrix berekenen */ Mat4Invert(imat, oblatt->obmat); Mat4MulMat4(latmat, ob->obmat, imat); /* terug: in deform array verwerken */ Mat4Invert(imat, latmat); } calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du); calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv); calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw); /* we berekenen hier steeds de u v w lattice coordinaten, weinig reden ze te onthouden */ vec[2]= fw; for(w=0; wpntsw; w++) { vec[1]= fv; for(v=0; vpntsv; v++) { vec[0]= fu; for(u=0; upntsu; u++, bp++) { VecSubf(fp, bp->vec, vec); Mat4Mul3Vecfl(imat, fp); vec[0]+= du; fp+= 3; } vec[1]+= dv; } vec[2]+= dw; } } void calc_latt_deform(float *co) { Lattice *lt; float fu, du, u, v, w, tu[4], tv[4], tw[4]; float *fpw, *fpv, *fpu, vec[3]; int ui, vi, wi, uu, vv, ww; if(latticedata==0) return; lt= deformLatt; /* kortere notatie! */ /* co is in lokale coords, met latmat behandelen */ VECCOPY(vec, co); Mat4MulVecfl(latmat, vec); /* u v w coords */ if(lt->pntsu>1) { calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du); u= (vec[0]-fu)/du; ui= (int)floor(u); u -= ui; set_four_ipo(u, tu, lt->typeu); } else { tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0; ui= 0; } if(lt->pntsv>1) { calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du); v= (vec[1]-fu)/du; vi= (int)floor(v); v -= vi; set_four_ipo(v, tv, lt->typev); } else { tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0; vi= 0; } if(lt->pntsw>1) { calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du); w= (vec[2]-fu)/du; wi= (int)floor(w); w -= wi; set_four_ipo(w, tw, lt->typew); } else { tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0; wi= 0; } for(ww= wi-1; ww<=wi+2; ww++) { w= tw[ww-wi+1]; if(w!=0.0) { if(ww>0) { if(wwpntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv; else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv; } else fpw= latticedata; for(vv= vi-1; vv<=vi+2; vv++) { v= w*tv[vv-vi+1]; if(v!=0.0) { if(vv>0) { if(vvpntsv) fpv= fpw + 3*vv*lt->pntsu; else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu; } else fpv= fpw; for(uu= ui-1; uu<=ui+2; uu++) { u= v*tu[uu-ui+1]; if(u!=0.0) { if(uu>0) { if(uupntsu) fpu= fpv + 3*uu; else fpu= fpv + 3*(lt->pntsu-1); } else fpu= fpv; co[0]+= u*fpu[0]; co[1]+= u*fpu[1]; co[2]+= u*fpu[2]; } } } } } } } void end_latt_deform() { MEM_freeN(latticedata); latticedata= 0; } int object_deform(Object *ob) { Mesh *me; Curve *cu; DispList *dl; MVert *mvert; float *fp; int a, tot; if(ob->parent==0) return 0; /* altijd proberen in deze fie de hele deform te doen: apply! */ if(ob->parent->type==OB_LATTICE) { init_latt_deform(ob->parent, ob); if(ob->type==OB_MESH) { me= ob->data; dl= find_displist_create(&ob->disp, DL_VERTS); mvert= me->mvert; if(dl->verts) MEM_freeN(dl->verts); dl->nr= me->totvert; dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); for(a=0; atotvert; a++, mvert++, fp+=3) { if(lt_applyflag) calc_latt_deform(mvert->co); else { VECCOPY(fp, mvert->co); calc_latt_deform(fp); } } } else if ELEM(ob->type, OB_CURVE, OB_SURF) { cu= ob->data; if(lt_applyflag) { Nurb *nu; BPoint *bp; nu= cu->nurb.first; while(nu) { if(nu->bp) { a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { calc_latt_deform(bp->vec); bp++; } } nu= nu->next; } } /* when apply, do this too, looks more interactive */ dl= cu->disp.first; while(dl) { fp= dl->verts; if(dl->type==DL_INDEX3) tot=dl->parts; else tot= dl->nr*dl->parts; for(a=0; anext; } } end_latt_deform(); boundbox_displist(ob); return 1; } else if(ob->parent->type==OB_ARMATURE) { if (ob->partype != PARSKEL){ return 0; } init_armature_deform (ob->parent, ob); switch (ob->type){ case OB_MESH: me= ob->data; dl= find_displist_create(&ob->disp, DL_VERTS); mvert= me->mvert; if(dl->verts) MEM_freeN(dl->verts); dl->nr= me->totvert; dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); for(a=0; atotvert; a++, mvert++, fp+=3) { if(lt_applyflag){ calc_armature_deform(ob->parent, mvert->co, a); } else { VECCOPY(fp, mvert->co); calc_armature_deform(ob->parent, fp, a); } } break; default: break; } boundbox_displist(ob); return 1; } else if(ob->parent->type==OB_IKA) { Ika *ika; if(ob->partype!=PARSKEL) return 0; ika= ob->parent->data; if(ika->def==0) return 0; init_skel_deform(ob->parent, ob); if(ob->type==OB_MESH) { me= ob->data; dl= find_displist_create(&ob->disp, DL_VERTS); mvert= me->mvert; if(dl->verts) MEM_freeN(dl->verts); dl->nr= me->totvert; dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); for(a=0; atotvert; a++, mvert++, fp+=3) { if(lt_applyflag) calc_skel_deform(ika, mvert->co); else { VECCOPY(fp, mvert->co); calc_skel_deform(ika, fp); } } } else if ELEM(ob->type, OB_CURVE, OB_SURF) { cu= ob->data; if(lt_applyflag) { Nurb *nu; BPoint *bp; nu= cu->nurb.first; while(nu) { if(nu->bp) { a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { calc_skel_deform(ika, bp->vec); bp++; } } nu= nu->next; } } /* when apply, do this too, looks more interactive */ dl= cu->disp.first; while(dl) { fp= dl->verts; tot= dl->nr*dl->parts; for(a=0; anext; } } boundbox_displist(ob); return 1; } return 0; } BPoint *latt_bp(Lattice *lt, int u, int v, int w) { return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv; } void outside_lattice(Lattice *lt) { BPoint *bp, *bp1, *bp2; int u, v, w; float fac1, du=0.0, dv=0.0, dw=0.0; bp= lt->def; if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1); if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1); if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1); for(w=0; wpntsw; w++) { for(v=0; vpntsv; v++) { for(u=0; upntsu; u++, bp++) { if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1); else { bp->hide= 1; bp->f1 &= ~SELECT; /* u extrema */ bp1= latt_bp(lt, 0, v, w); bp2= latt_bp(lt, lt->pntsu-1, v, w); fac1= du*u; bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; /* v extrema */ bp1= latt_bp(lt, u, 0, w); bp2= latt_bp(lt, u, lt->pntsv-1, w); fac1= dv*v; bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; /* w extrema */ bp1= latt_bp(lt, u, v, 0); bp2= latt_bp(lt, u, v, lt->pntsw-1); fac1= dw*w; bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; VecMulf(bp->vec, 0.3333333f); } } } } }