2002-10-12 11:37:38 +00:00
|
|
|
/* deform.c June 2001
|
|
|
|
*
|
|
|
|
* support for deformation groups
|
|
|
|
*
|
|
|
|
* Reevan McKay
|
|
|
|
*
|
|
|
|
* $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 <string.h>
|
2004-11-06 21:59:35 +00:00
|
|
|
#include <math.h>
|
2004-09-14 19:03:11 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
2004-09-14 19:03:11 +00:00
|
|
|
|
|
|
|
#include "DNA_curve_types.h"
|
2004-09-19 17:44:20 +00:00
|
|
|
#include "DNA_effect_types.h"
|
2004-09-14 19:03:11 +00:00
|
|
|
#include "DNA_lattice_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_object_types.h"
|
2005-05-02 13:28:13 +00:00
|
|
|
#include "DNA_object_force.h"
|
2004-10-01 14:04:17 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2004-09-14 19:03:11 +00:00
|
|
|
|
|
|
|
#include "BKE_curve.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "BKE_deform.h"
|
2004-09-14 19:03:11 +00:00
|
|
|
#include "BKE_displist.h"
|
2004-09-19 17:44:20 +00:00
|
|
|
#include "BKE_effect.h"
|
2004-10-01 14:04:17 +00:00
|
|
|
#include "BKE_global.h"
|
2004-09-14 19:03:11 +00:00
|
|
|
#include "BKE_lattice.h"
|
2004-10-01 14:04:17 +00:00
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_softbody.h"
|
2004-09-14 19:03:11 +00:00
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_arithb.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2002-11-25 12:02:15 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
void copy_defgroups(ListBase *outbase, ListBase *inbase)
|
|
|
|
{
|
|
|
|
bDeformGroup *defgroup, *defgroupn;
|
|
|
|
|
|
|
|
outbase->first= outbase->last= 0;
|
|
|
|
|
|
|
|
for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
|
|
|
|
defgroupn= copy_defgroup(defgroup);
|
|
|
|
BLI_addtail(outbase, defgroupn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bDeformGroup* copy_defgroup (bDeformGroup *ingroup)
|
|
|
|
{
|
|
|
|
bDeformGroup *outgroup;
|
|
|
|
|
|
|
|
if (!ingroup)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
outgroup=MEM_callocN(sizeof(bDeformGroup), "deformGroup");
|
|
|
|
|
|
|
|
/* For now, just copy everything over. */
|
|
|
|
memcpy (outgroup, ingroup, sizeof(bDeformGroup));
|
|
|
|
|
|
|
|
outgroup->next=outgroup->prev=NULL;
|
|
|
|
|
|
|
|
return outgroup;
|
|
|
|
}
|
|
|
|
|
2005-01-12 23:57:33 +00:00
|
|
|
bDeformGroup *get_named_vertexgroup(Object *ob, char *name)
|
|
|
|
{
|
|
|
|
/* return a pointer to the deform group with this name
|
|
|
|
* or return NULL otherwise.
|
|
|
|
*/
|
|
|
|
bDeformGroup *curdef;
|
|
|
|
|
|
|
|
for (curdef = ob->defbase.first; curdef; curdef=curdef->next){
|
|
|
|
if (!strcmp(curdef->name, name)){
|
|
|
|
return curdef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_defgroup_num (Object *ob, bDeformGroup *dg)
|
|
|
|
{
|
|
|
|
/* Fetch the location of this deform group
|
|
|
|
* within the linked list of deform groups.
|
|
|
|
* (this number is stored in the deform
|
|
|
|
* weights of the deform verts to link them
|
|
|
|
* to this deform group) deform deform
|
|
|
|
* deform blah blah deform
|
|
|
|
*/
|
|
|
|
|
|
|
|
bDeformGroup *eg;
|
|
|
|
int def_nr;
|
|
|
|
|
|
|
|
eg = ob->defbase.first;
|
|
|
|
def_nr = 0;
|
|
|
|
|
|
|
|
/* loop through all deform groups
|
|
|
|
*/
|
|
|
|
while (eg != NULL){
|
|
|
|
|
|
|
|
/* if the current deform group is
|
|
|
|
* the one we are after, return
|
|
|
|
* def_nr
|
|
|
|
*/
|
|
|
|
if (eg == dg){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++def_nr;
|
|
|
|
eg = eg->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if there was no deform group found then
|
|
|
|
* return -1 (should set up a nice symbolic
|
|
|
|
* constant for this)
|
|
|
|
*/
|
|
|
|
if (eg == NULL) return -1;
|
|
|
|
|
|
|
|
return def_nr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-09-14 19:03:11 +00:00
|
|
|
/* *************** HOOK ****************** */
|
|
|
|
|
|
|
|
/* vec==NULL: init
|
2004-11-10 15:55:07 +00:00
|
|
|
vec is supposed to be local coord, deform happens in local space
|
2004-09-14 19:03:11 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
void hook_object_deform(Object *ob, int index, float *vec)
|
|
|
|
{
|
|
|
|
float totforce;
|
|
|
|
ObHook *hook;
|
|
|
|
float vect[3], vectot[3];
|
|
|
|
|
|
|
|
if(ob->hooks.first==NULL) return;
|
|
|
|
|
|
|
|
/* reinitialize if... */
|
|
|
|
if(vec==NULL) {
|
|
|
|
totforce= 0.0;
|
|
|
|
for(hook= ob->hooks.first; hook; hook= hook->next) {
|
|
|
|
if(hook->parent) {
|
|
|
|
hook->curindex= 0;
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
/* apparently this call goes from right to left... */
|
|
|
|
Mat4MulSerie(hook->mat, ob->imat, hook->parent->obmat, hook->parentinv, NULL,
|
|
|
|
NULL, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
totforce= 0.0;
|
|
|
|
vectot[0]= vectot[1]= vectot[2]= 0.0;
|
|
|
|
|
|
|
|
for(hook= ob->hooks.first; hook; hook= hook->next) {
|
|
|
|
if(hook->parent) {
|
|
|
|
|
|
|
|
/* is 'index' in hook array? */
|
|
|
|
while(hook->curindex < hook->totindex-1) {
|
|
|
|
if( hook->indexar[hook->curindex] < index ) hook->curindex++;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( hook->indexar[hook->curindex]==index ) {
|
2004-11-06 21:59:35 +00:00
|
|
|
float fac= hook->force, len;
|
2004-09-14 19:03:11 +00:00
|
|
|
|
|
|
|
VecMat4MulVecfl(vect, hook->mat, vec);
|
2004-11-06 21:59:35 +00:00
|
|
|
|
|
|
|
if(hook->falloff!=0.0) {
|
2004-11-10 15:55:07 +00:00
|
|
|
/* hook->cent is in local coords */
|
|
|
|
len= VecLenf(vec, hook->cent);
|
2004-11-06 21:59:35 +00:00
|
|
|
if(len > hook->falloff) fac= 0.0;
|
|
|
|
else if(len>0.0) fac*= sqrt(1.0 - len/hook->falloff);
|
|
|
|
}
|
|
|
|
if(fac!=0.0) {
|
|
|
|
totforce+= fac;
|
|
|
|
vectot[0]+= fac*vect[0];
|
|
|
|
vectot[1]+= fac*vect[1];
|
|
|
|
vectot[2]+= fac*vect[2];
|
|
|
|
}
|
2004-09-14 19:03:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if totforce < 1.0, we take old position also into account */
|
|
|
|
if(totforce<1.0) {
|
|
|
|
vectot[0]+= (1.0-totforce)*vec[0];
|
|
|
|
vectot[1]+= (1.0-totforce)*vec[1];
|
|
|
|
vectot[2]+= (1.0-totforce)*vec[2];
|
|
|
|
}
|
|
|
|
else VecMulf(vectot, 1.0/totforce);
|
|
|
|
|
|
|
|
VECCOPY(vec, vectot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* modifiers: hooks, deform, softbody
|
2004-09-28 16:18:22 +00:00
|
|
|
mode=='s' is start, 'e' is end , 'a' is apply
|
2004-09-14 19:03:11 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
int mesh_modifier(Object *ob, char mode)
|
|
|
|
{
|
|
|
|
static MVert *mvert=NULL;
|
|
|
|
Mesh *me= ob->data;
|
|
|
|
MVert *mv;
|
|
|
|
int a, done=0;
|
|
|
|
|
|
|
|
/* conditions if it's needed */
|
|
|
|
if(ob->hooks.first);
|
2004-09-19 17:44:20 +00:00
|
|
|
else if(ob->effect.first); // weak... particles too
|
2004-09-14 19:03:11 +00:00
|
|
|
else if(ob->parent && ob->parent->type==OB_LATTICE);
|
|
|
|
else if(ob->parent && ob->partype==PARSKEL);
|
2005-04-03 16:57:16 +00:00
|
|
|
else if(ob->softflag & OB_SB_ENABLE);
|
2004-09-14 19:03:11 +00:00
|
|
|
else return 0;
|
|
|
|
|
|
|
|
if(me->totvert==0) return 0;
|
|
|
|
|
|
|
|
if(mode=='s') { // "start"
|
|
|
|
/* copy */
|
|
|
|
mvert= MEM_dupallocN(me->mvert);
|
|
|
|
|
|
|
|
/* hooks */
|
|
|
|
if(ob->hooks.first) {
|
|
|
|
done= 1;
|
|
|
|
|
|
|
|
/* NULL signals initialize */
|
|
|
|
hook_object_deform(ob, 0, NULL);
|
|
|
|
|
|
|
|
for(a=0, mv= me->mvert; a<me->totvert; a++, mv++) {
|
|
|
|
hook_object_deform(ob, a, mv->co);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-19 17:44:20 +00:00
|
|
|
if(ob->effect.first) done |= object_wave(ob);
|
2005-01-12 22:28:13 +00:00
|
|
|
|
2005-04-02 13:57:23 +00:00
|
|
|
if((ob->softflag & OB_SB_ENABLE) && !(ob->softflag & OB_SB_POSTDEF)) {
|
2004-10-01 14:04:17 +00:00
|
|
|
done= 1;
|
2005-04-02 13:57:23 +00:00
|
|
|
sbObjectStep(ob, (float)G.scene->r.cfra);
|
2004-10-01 14:04:17 +00:00
|
|
|
}
|
2005-01-12 22:28:13 +00:00
|
|
|
|
2005-04-02 13:57:23 +00:00
|
|
|
/* object_deform: output for mesh is in mesh->mvert */
|
2004-09-14 19:03:11 +00:00
|
|
|
done |= object_deform(ob);
|
2005-01-12 22:28:13 +00:00
|
|
|
|
2005-04-02 13:57:23 +00:00
|
|
|
if((ob->softflag & OB_SB_ENABLE) && (ob->softflag & OB_SB_POSTDEF)) {
|
2005-01-12 22:28:13 +00:00
|
|
|
done= 1;
|
2005-04-02 13:57:23 +00:00
|
|
|
sbObjectStep(ob, (float)G.scene->r.cfra);
|
2005-01-12 22:28:13 +00:00
|
|
|
}
|
2004-09-14 19:03:11 +00:00
|
|
|
|
|
|
|
/* put deformed vertices in dl->verts, optional subsurf will replace that */
|
|
|
|
if(done) {
|
|
|
|
DispList *dl= find_displist_create(&ob->disp, DL_VERTS);
|
|
|
|
float *fp;
|
|
|
|
|
|
|
|
if(dl->verts) MEM_freeN(dl->verts);
|
2004-11-06 21:59:35 +00:00
|
|
|
if(dl->nors) MEM_freeN(dl->nors);
|
2004-09-14 19:03:11 +00:00
|
|
|
dl->nr= me->totvert;
|
|
|
|
if(dl->nr) {
|
|
|
|
|
|
|
|
/* make disp array */
|
|
|
|
dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
|
|
|
|
mv= me->mvert;
|
|
|
|
for(a=0; a<me->totvert; a++, mv++, fp+=3) {
|
|
|
|
VECCOPY(fp, mv->co);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-09-19 17:44:20 +00:00
|
|
|
|
2004-09-14 19:03:11 +00:00
|
|
|
}
|
2004-09-28 16:18:22 +00:00
|
|
|
else if(mode=='e') { // end
|
2004-09-14 19:03:11 +00:00
|
|
|
if(mvert) {
|
2004-09-28 16:18:22 +00:00
|
|
|
if(me->mvert) MEM_freeN(me->mvert);
|
2004-09-14 19:03:11 +00:00
|
|
|
me->mvert= mvert;
|
|
|
|
mvert= NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-09-28 16:18:22 +00:00
|
|
|
else if(mode=='a') { // apply
|
|
|
|
if(mvert) MEM_freeN(mvert);
|
|
|
|
mvert= NULL;
|
|
|
|
}
|
2004-09-14 19:03:11 +00:00
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
int curve_modifier(Object *ob, char mode)
|
|
|
|
{
|
|
|
|
static ListBase nurb={NULL, NULL};
|
|
|
|
Curve *cu= ob->data;
|
|
|
|
Nurb *nu, *newnu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
BPoint *bp;
|
|
|
|
int a, index, done= 0;
|
|
|
|
|
|
|
|
/* conditions if it's needed */
|
|
|
|
if(ob->hooks.first);
|
|
|
|
else if(ob->parent && ob->partype==PARSKEL);
|
|
|
|
else if(ob->parent && ob->parent->type==OB_LATTICE);
|
|
|
|
else return 0;
|
|
|
|
|
|
|
|
if(mode=='s') { // "start"
|
|
|
|
/* copy */
|
|
|
|
nurb.first= nurb.last= NULL;
|
|
|
|
nu= cu->nurb.first;
|
|
|
|
while(nu) {
|
|
|
|
newnu= duplicateNurb(nu);
|
|
|
|
BLI_addtail(&nurb, newnu);
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* hooks */
|
|
|
|
if(ob->hooks.first) {
|
|
|
|
done= 1;
|
|
|
|
|
|
|
|
/* NULL signals initialize */
|
|
|
|
hook_object_deform(ob, 0, NULL);
|
|
|
|
index= 0;
|
|
|
|
|
|
|
|
nu= cu->nurb.first;
|
|
|
|
while(nu) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
|
|
bezt= nu->bezt;
|
|
|
|
a= nu->pntsu;
|
|
|
|
while(a--) {
|
|
|
|
hook_object_deform(ob, index++, bezt->vec[0]);
|
|
|
|
hook_object_deform(ob, index++, bezt->vec[1]);
|
|
|
|
hook_object_deform(ob, index++, bezt->vec[2]);
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bp= nu->bp;
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while(a--) {
|
|
|
|
hook_object_deform(ob, index++, bp->vec);
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-09-28 16:18:22 +00:00
|
|
|
else if(mode=='e') {
|
2004-09-14 19:03:11 +00:00
|
|
|
/* paste */
|
|
|
|
freeNurblist(&cu->nurb);
|
|
|
|
cu->nurb= nurb;
|
|
|
|
}
|
2004-09-28 16:18:22 +00:00
|
|
|
else if(mode=='a') {
|
|
|
|
freeNurblist(&nurb);
|
|
|
|
}
|
2004-09-14 19:03:11 +00:00
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
int lattice_modifier(Object *ob, char mode)
|
|
|
|
{
|
|
|
|
static BPoint *bpoint;
|
|
|
|
Lattice *lt= ob->data;
|
|
|
|
BPoint *bp;
|
|
|
|
int a, index, done= 0;
|
|
|
|
|
|
|
|
/* conditions if it's needed */
|
|
|
|
if(ob->hooks.first);
|
|
|
|
else if(ob->parent && ob->partype==PARSKEL);
|
2005-04-02 19:52:32 +00:00
|
|
|
else if((ob->softflag & OB_SB_ENABLE));
|
2004-09-14 19:03:11 +00:00
|
|
|
else return 0;
|
|
|
|
|
|
|
|
if(mode=='s') { // "start"
|
|
|
|
/* copy */
|
|
|
|
bpoint= MEM_dupallocN(lt->def);
|
|
|
|
|
|
|
|
/* hooks */
|
|
|
|
if(ob->hooks.first) {
|
|
|
|
done= 1;
|
|
|
|
|
|
|
|
/* NULL signals initialize */
|
|
|
|
hook_object_deform(ob, 0, NULL);
|
|
|
|
index= 0;
|
|
|
|
bp= lt->def;
|
|
|
|
a= lt->pntsu*lt->pntsv*lt->pntsw;
|
|
|
|
while(a--) {
|
|
|
|
hook_object_deform(ob, index++, bp->vec);
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
2005-04-02 19:52:32 +00:00
|
|
|
|
|
|
|
if((ob->softflag & OB_SB_ENABLE)) {
|
|
|
|
sbObjectStep(ob, (float)G.scene->r.cfra);
|
|
|
|
}
|
|
|
|
|
2004-09-14 19:03:11 +00:00
|
|
|
}
|
|
|
|
else { // end
|
|
|
|
MEM_freeN(lt->def);
|
|
|
|
lt->def= bpoint;
|
|
|
|
bpoint= NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|