diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
19 files changed, 2389 insertions, 3274 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 4b1f47707af..911df2a5998 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -23,9 +23,7 @@ * 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. + * Contributor(s): Full recode, Ton Roosendaal, Crete 2005 * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -39,50 +37,141 @@ #include <stdlib.h> /* for NULL */ #include "MEM_guardedalloc.h" -#include "BLI_arithb.h" -#include "BLI_blenlib.h" -#include "BKE_action.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_utildefines.h" - -#include "DNA_object_types.h" -#include "DNA_ipo_types.h" -#include "DNA_curve_types.h" -#include "DNA_scene_types.h" #include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" #include "DNA_nla_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "BKE_action.h" +#include "BKE_anim.h" +#include "BKE_armature.h" #include "BKE_blender.h" +#include "BKE_constraint.h" +#include "BKE_global.h" #include "BKE_ipo.h" -#include "BKE_object.h" #include "BKE_library.h" -#include "BKE_anim.h" -#include "BKE_armature.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" #include "nla.h" -#include "BKE_constraint.h" -#include "DNA_constraint_types.h" +/* *********************** NOTE ON POSE AND ACTION ********************** -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif + - Pose is the local (object level) component of armature. The current + object pose is saved in files, and (will be) is presorted for dependency + - Actions have fewer (or other) channels, and write data to a Pose + - Currently ob->pose data is controlled in where_is_pose only. The (recalc) + event system takes care of calling that + - The NLA system (here too) uses Poses as interpolation format for Actions + - Therefore we assume poses to be static, and duplicates of poses have channels in + same order, for quick interpolation reasons + + ****************************** (ton) ************************************ */ + +/* ***************** Library data level operations on action ************** */ + +void make_local_action(bAction *act) +{ + Object *ob; + bAction *actn; + int local=0, lib=0; + + if(act->id.lib==0) return; + if(act->id.us==1) { + act->id.lib= 0; + act->id.flag= LIB_LOCAL; + new_id(0, (ID *)act, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->action==act) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + act->id.lib= 0; + act->id.flag= LIB_LOCAL; + new_id(0, (ID *)act, 0); + } + else if(local && lib) { + actn= copy_action(act); + actn->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->action==act) { + + if(ob->id.lib==0) { + ob->action = actn; + ob->activecon = NULL; + actn->id.us++; + act->id.us--; + } + } + ob= ob->id.next; + } + } +} -/* Local function prototypes */ -static void do_pose_constraint_channels(bPose *pose, bAction *act, - float ctime); +void free_action(bAction *act) +{ + bActionChannel *chan; + + /* Free channels */ + for (chan=act->chanbase.first; chan; chan=chan->next){ + if (chan->ipo) + chan->ipo->id.us--; + free_constraint_channels(&chan->constraintChannels); + } + + if (act->chanbase.first) + BLI_freelistN (&act->chanbase); +} + +bAction* copy_action(bAction *src) +{ + bAction *dst = NULL; + bActionChannel *dchan, *schan; + + if(!src) return NULL; + + dst= copy_libblock(src); + duplicatelist(&(dst->chanbase), &(src->chanbase)); + + for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){ + dchan->ipo = copy_ipo(dchan->ipo); + copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels); + } + dst->id.flag |= LIB_FAKEUSER; + dst->id.us++; + return dst; +} + -static void rest_pose(bPose *pose, int clearflag); -/* Implementation */ +/* ************************ Pose channels *************** */ bPoseChannel *get_pose_channel(const bPose *pose, const char *name) { bPoseChannel *chan; + if(pose==NULL) return NULL; + for (chan=pose->chanbase.first; chan; chan=chan->next){ if (!strcmp (chan->name, name)) return chan; @@ -91,70 +180,132 @@ bPoseChannel *get_pose_channel(const bPose *pose, const char *name) return NULL; } -static void rest_pose(bPose *pose, int clearflag) +/* Use with care, not on Armature poses but for temporal ones */ +/* (currently used for action constraints and in rebuild_pose) */ +bPoseChannel *verify_pose_channel(bPose* pose, const char* name) { bPoseChannel *chan; - int i; + + if (!pose){ + return NULL; + } + + /* See if this channel exists */ + for (chan=pose->chanbase.first; chan; chan=chan->next){ + if (!strcmp (name, chan->name)) + return chan; + } + + /* If not, create it and add it */ + chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); + + strcpy (chan->name, name); + /* init vars to prevent mat errors */ + chan->quat[0] = 1.0F; + chan->size[0] = chan->size[1] = chan->size[2] = 1.0F; + Mat3One(chan->ik_mat); + + BLI_addtail (&pose->chanbase, chan); + + return chan; +} - if (!pose) + +/* dst should be freed already, makes entire duplicate */ +void copy_pose(bPose **dst, bPose *src, int copycon) +{ + bPose *outPose; + bPoseChannel *pchan; + ListBase listb; + + if (!src){ + *dst=NULL; return; + } + + outPose= MEM_callocN(sizeof(bPose), "pose"); + + duplicatelist (&outPose->chanbase, &src->chanbase); + + if (copycon) { + for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { + copy_constraints(&listb, &pchan->constraints); // copy_constraints NULLs listb + pchan->constraints= listb; + } + } + + *dst=outPose; +} - for (chan=pose->chanbase.first; chan; chan=chan->next){ - for (i=0; i<3; i++){ - chan->loc[i]=0.0; - chan->quat[i+1]=0.0; - chan->size[i]=1.0; +void free_pose_channels(bPose *pose) +{ + bPoseChannel *chan; + + if (pose->chanbase.first){ + for (chan = pose->chanbase.first; chan; chan=chan->next){ + free_constraints(&chan->constraints); } - chan->quat[0]=1.0; - if (clearflag) - chan->flag =0; + BLI_freelistN (&pose->chanbase); } } -#ifdef __NLA_BLENDCON -static void blend_constraints(ListBase *dst, const ListBase *src, - float srcweight, short mode) +static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) { - bConstraint *dcon; - const bConstraint *scon; - float dstweight = 0; + VECCOPY(pchan->loc, chan->loc); + VECCOPY(pchan->size, chan->size); + QUATCOPY(pchan->quat, chan->quat); + pchan->flag= chan->flag; +} - switch (mode){ - case POSE_BLEND: - dstweight = 1.0F - srcweight; - break; - case POSE_ADD: - dstweight = 1.0F; - break; +/* checks for IK constraint, can do more constraints flags later */ +/* pose should be entirely OK */ +void update_pose_constraint_flags(bPose *pose) +{ + bPoseChannel *pchan; + bConstraint *con; + + /* clear */ + for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) { + pchan->constflag= 0; } - - /* Blend constraints */ - for (dcon=dst->first; dcon; dcon=dcon->next){ - for (scon = src->first; scon; scon=scon->next){ - if (!strcmp(scon->name, dcon->name)) - break; + /* detect */ + for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) { + for(con= pchan->constraints.first; con; con= con->next) { + if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + pchan->constflag |= PCHAN_HAS_IK; + } + else pchan->constflag |= PCHAN_HAS_CONST; } - - if (scon){ - dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight); - if (mode == POSE_BLEND) - dcon->enforce/=2.0; - - if (dcon->enforce>1.0) - dcon->enforce=1.0; - if (dcon->enforce<0.0) - dcon->enforce=0.0; + } +} - } + +/* ************************ END Pose channels *************** */ + +bActionChannel *get_named_actionchannel(bAction *act, const char *name) +{ + bActionChannel *chan; + + if (!act) + return NULL; + + for (chan = act->chanbase.first; chan; chan=chan->next){ + if (!strcmp (chan->name, name)) + return chan; } + + return NULL; } -#endif +/* ************************ Blending with NLA *************** */ + + +/* Only allowed for Poses with identical channels */ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode) { bPoseChannel *dchan; const bPoseChannel *schan; - float dquat[4], squat[4]; //, mat[3][3]; + float dquat[4], squat[4]; float dstweight; int i; @@ -169,67 +320,35 @@ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode) dstweight = 1.0F; } - for (dchan = dst->chanbase.first; dchan; dchan=dchan->next){ - schan = get_pose_channel(src, dchan->name); - if (schan){ - if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)){ - - /* Convert both quats to matrices and then back again. - * This prevents interpolation problems - * This sucks because it is slow and stupid - */ - - //QuatToMat3(dchan->quat, mat); - //Mat3ToQuat(mat, dquat); - //QuatToMat3(schan->quat, mat); - //Mat3ToQuat(mat, squat); + schan= src->chanbase.first; + for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){ + if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) { + + /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ + + /* Do the transformation blend */ + if (schan->flag & POSE_ROT) { + QUATCOPY(dquat, dchan->quat); + QUATCOPY(squat, schan->quat); + if(mode==POSE_BLEND) + QuatInterpol(dchan->quat, dquat, squat, srcweight); + else + QuatAdd(dchan->quat, dquat, squat, srcweight); - /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ - /* Do the transformation blend */ - if (schan->flag & POSE_ROT) { - QUATCOPY(dquat, dchan->quat); - QUATCOPY(squat, schan->quat); - if(mode==POSE_BLEND) - QuatInterpol(dchan->quat, dquat, squat, srcweight); - else - QuatAdd(dchan->quat, dquat, squat, srcweight); - NormalQuat (dchan->quat); - } + NormalQuat (dchan->quat); + } - for (i=0; i<3; i++){ - if (schan->flag & POSE_LOC) - dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); - if (schan->flag & POSE_SIZE) - dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - //if (schan->flag & POSE_ROT) - // dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight); - } - - /* Do one more iteration for the quaternions only and normalize the quaternion if needed */ - //if (schan->flag & POSE_ROT) - // dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight); - //if (mode==POSE_BLEND) - // NormalQuat (dchan->quat); - - dchan->flag |= schan->flag; + for (i=0; i<3; i++){ + if (schan->flag & POSE_LOC) + dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); + if (schan->flag & POSE_SIZE) + dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); } + dchan->flag |= schan->flag; } } } -void clear_pose_constraint_status(Object *ob) -{ - bPoseChannel *chan; - - if (!ob) - return; - if (!ob->pose) - return; - - for (chan = ob->pose->chanbase.first; chan; chan=chan->next){ - chan->flag &= ~PCHAN_DONE; - } -} float calc_action_start(const bAction *act) { @@ -291,59 +410,60 @@ float calc_action_end(const bAction *act) return size; } -bPoseChannel *verify_pose_channel(bPose* pose, const char* name) +/* Copy the data from the action-pose (src) into the pose */ +/* both args are assumed to be valid */ +/* exported to game engine */ +void extract_pose_from_pose(bPose *pose, const bPose *src) { - bPoseChannel *chan; - - if (!pose){ - return NULL; - } + const bPoseChannel *schan; + bPoseChannel *pchan= pose->chanbase.first; - /* See if this channel exists */ - for (chan=pose->chanbase.first; chan; chan=chan->next){ - if (!strcmp (name, chan->name)) - return chan; + for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) { + copy_pose_channel_data(pchan, schan); } - - /* If not, create it and add it */ - chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); - - strcpy (chan->name, name); - chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F; - chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F; - chan->quat[0] = 1.0F; - chan->size[0] = chan->size[1] = chan->size[2] = 1.0F; - - chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC; - - BLI_addtail (&pose->chanbase, chan); - - return chan; } -void get_pose_from_pose(bPose **pose, const bPose *src) +/* seems to be disabled... (ton) */ +#ifdef __NLA_BLENDCON +static void blend_constraints(ListBase *dst, const ListBase *src, + float srcweight, short mode) { - const bPoseChannel *pchan; - bPoseChannel *newchan; - - if (!src) - return; - if (!pose) - return; - - /* If there is no pose, create one */ - if (!*pose){ - *pose=MEM_callocN (sizeof(bPose), "pose"); + bConstraint *dcon; + const bConstraint *scon; + float dstweight = 0; + + switch (mode){ + case POSE_BLEND: + dstweight = 1.0F - srcweight; + break; + case POSE_ADD: + dstweight = 1.0F; + break; } - - /* Copy the data from the action into the pose */ - for (pchan=src->chanbase.first; pchan; pchan=pchan->next){ - newchan = copy_pose_channel(pchan); - verify_pose_channel(*pose, pchan->name); - set_pose_channel(*pose, newchan); + + /* Blend constraints */ + for (dcon=dst->first; dcon; dcon=dcon->next){ + for (scon = src->first; scon; scon=scon->next){ + if (!strcmp(scon->name, dcon->name)) + break; + } + + if (scon){ + dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight); + if (mode == POSE_BLEND) + dcon->enforce/=2.0; + + if (dcon->enforce>1.0) + dcon->enforce=1.0; + if (dcon->enforce<0.0) + dcon->enforce=0.0; + + } } } +#endif +/* seems to be disabled... (ton) */ #ifdef __NLA_BLENDCON static void get_constraint_influence_from_pose(bPose *dst, bPose *src) { @@ -364,72 +484,76 @@ static void get_constraint_influence_from_pose(bPose *dst, bPose *src) } #endif -/* If the pose does not exist, a new one is created */ - -void get_pose_from_action(bPose **pose, bAction *act, float ctime) +/* Pose should exist, can have any number of channels too (used for constraint) */ +void extract_pose_from_action(bPose *pose, bAction *act, float ctime) { bActionChannel *achan; bPoseChannel *pchan; Ipo *ipo; - IpoCurve *curve; - if (!act) return; if (!pose) return; - /* If there is no pose, create one */ - if (!*pose){ - *pose=MEM_callocN (sizeof(bPose), "pose"); - } - /* Copy the data from the action into the pose */ for (achan=act->chanbase.first; achan; achan=achan->next){ - act->achan= achan; + act->achan= achan; // for ipos ipo = achan->ipo; - if (ipo){ - pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel"); - strcpy (pchan->name, achan->name); - - act->pchan=pchan; - /* Evaluates and sets the internal ipo value */ - calc_ipo(ipo, ctime); - - /* Set the pchan flags */ - for (curve = achan->ipo->curve.first; curve; curve=curve->next){ - /* Skip empty curves */ - if (!curve->totvert) - continue; - - switch (curve->adrcode){ - case AC_QUAT_X: - case AC_QUAT_Y: - case AC_QUAT_Z: - case AC_QUAT_W: - pchan->flag |= POSE_ROT; - break; - case AC_LOC_X: - case AC_LOC_Y: - case AC_LOC_Z: - pchan->flag |= POSE_LOC; - break; - case AC_SIZE_X: - case AC_SIZE_Y: - case AC_SIZE_Z: - pchan->flag |= POSE_SIZE; - break; - } + if (ipo) { + pchan= get_pose_channel(pose, achan->name); + if(pchan) { + act->pchan= pchan; // for ipos + + /* Evaluates and sets the internal ipo value */ + calc_ipo(ipo, ctime); + + /* This call also sets the pchan flags */ + execute_ipo((ID*)act, achan->ipo); } + } + } +} - execute_ipo((ID*)act, achan->ipo); - - set_pose_channel(*pose, pchan); +/* for do_all_actions, clears the pose */ +static void rest_pose(bPose *pose, int clearflag) +{ + bPoseChannel *chan; + int i; + + if (!pose) + return; + + for (chan=pose->chanbase.first; chan; chan=chan->next){ + for (i=0; i<3; i++){ + chan->loc[i]=0.0; + chan->quat[i+1]=0.0; + chan->size[i]=1.0; } + chan->quat[0]=1.0; + if (clearflag) + chan->flag =0; + } +} + +/* do constraint channels = execute the ipos */ +static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime) +{ + bPoseChannel *pchan; + bActionChannel *achan; + + if (!pose || !act) + return; + + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ + achan=get_named_actionchannel(act, pchan->name); + if (achan) + do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime); } } + void do_all_actions(Object *only_this) { Base *base; @@ -440,9 +564,11 @@ void do_all_actions(Object *only_this) int doit; float striptime, frametime, length, actlength; float blendfac, stripframe; - int set; + //printf("do all actions disabled\n"); + //return; + /* NEW: current scene ob ipo's */ base= G.scene->base.first; set= 0; @@ -453,150 +579,154 @@ void do_all_actions(Object *only_this) else ob = base->object; /* Retrieve data from the NLA */ - if(ob->type==OB_ARMATURE){ + if(ob->type==OB_ARMATURE && ob->pose) { + bArmature *arm= ob->data; - doit=0; - - /* Clear pose */ - if (apose){ - clear_pose(apose); - MEM_freeN(apose); - } - /* Clear pose */ - if (tpose){ - clear_pose(tpose); - MEM_freeN(tpose); + if(arm->flag & ARM_NO_ACTION) { // no action set while transform + ; } + else { + doit=0; - copy_pose(&apose, ob->pose, 1); - copy_pose(&tpose, ob->pose, 1); - rest_pose(apose, 1); - - if (ob->nlastrips.first){ - rest_pose(ob->pose, 0); - } + /* Clear pose */ + if (apose){ + free_pose_channels(apose); + MEM_freeN(apose); + } + /* Clear pose */ + if (tpose){ + free_pose_channels(tpose); + MEM_freeN(tpose); + } - for (strip=ob->nlastrips.first; strip; strip=strip->next){ - doit = 0; - if (strip->act){ - - /* Determine if the current frame is within the strip's range */ - length = strip->end-strip->start; - actlength = strip->actend-strip->actstart; - striptime = (G.scene->r.cfra-(strip->start)) / length; - stripframe = (G.scene->r.cfra-(strip->start)) ; - - - if (striptime>=0.0){ - - rest_pose(tpose, 1); - - /* Handle path */ - if (strip->flag & ACTSTRIP_USESTRIDE){ - if (ob->parent && ob->parent->type==OB_CURVE){ - Curve *cu = ob->parent->data; - float ctime, pdist; - - if (cu->flag & CU_PATH){ - /* Ensure we have a valid path */ - if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent); - - /* Find the position on the path */ - ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0); - - if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { - ctime /= cu->pathlen; - CLAMP(ctime, 0.0, 1.0); + copy_pose(&apose, ob->pose, 1); + copy_pose(&tpose, ob->pose, 1); + rest_pose(apose, 1); + + if (ob->nlastrips.first){ + rest_pose(ob->pose, 0); + } + + for (strip=ob->nlastrips.first; strip; strip=strip->next){ + doit = 0; + if (strip->act){ + + /* Determine if the current frame is within the strip's range */ + length = strip->end-strip->start; + actlength = strip->actend-strip->actstart; + striptime = (G.scene->r.cfra-(strip->start)) / length; + stripframe = (G.scene->r.cfra-(strip->start)) ; + + + if (striptime>=0.0){ + + rest_pose(tpose, 1); + + /* Handle path */ + if (strip->flag & ACTSTRIP_USESTRIDE){ + if (ob->parent && ob->parent->type==OB_CURVE){ + Curve *cu = ob->parent->data; + float ctime, pdist; + + if (cu->flag & CU_PATH){ + /* Ensure we have a valid path */ + if(cu->path==NULL || cu->path->data==NULL) printf("action path error\n"); + else { + + /* Find the position on the path */ + ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0); + + if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { + ctime /= cu->pathlen; + CLAMP(ctime, 0.0, 1.0); + } + pdist = ctime*cu->path->totdist; + + if (strip->stridelen) + striptime = pdist / strip->stridelen; + else + striptime = 0; + + striptime = (float)fmod (striptime, 1.0); + + frametime = (striptime * actlength) + strip->actstart; + extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); + #ifdef __NLA_BLENDCON + do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); + #endif + doit=1; + } } - pdist = ctime*cu->path->totdist; - - if (strip->stridelen) - striptime = pdist / strip->stridelen; - else - striptime = 0; - - striptime = (float)fmod (striptime, 1.0); - - frametime = (striptime * actlength) + strip->actstart; - get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); -#ifdef __NLA_BLENDCON - do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); -#endif - doit=1; } } - } - /* Handle repeat */ - - else if (striptime < 1.0){ - /* Mod to repeat */ - striptime*=strip->repeat; - striptime = (float)fmod (striptime, 1.0); - - frametime = (striptime * actlength) + strip->actstart; - get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); -#ifdef __NLA_BLENDCON - do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); -#endif - doit=1; - } - /* Handle extend */ - else{ - if (strip->flag & ACTSTRIP_HOLDLASTFRAME){ - striptime = 1.0; + /* Handle repeat */ + + else if (striptime < 1.0){ + /* Mod to repeat */ + striptime*=strip->repeat; + striptime = (float)fmod (striptime, 1.0); + frametime = (striptime * actlength) + strip->actstart; - get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); -#ifdef __NLA_BLENDCON + extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); + #ifdef __NLA_BLENDCON do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); -#endif + #endif doit=1; } - } + /* Handle extend */ + else{ + if (strip->flag & ACTSTRIP_HOLDLASTFRAME){ + striptime = 1.0; + frametime = (striptime * actlength) + strip->actstart; + extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); + #ifdef __NLA_BLENDCON + do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); + #endif + doit=1; + } + } - /* Handle blendin & blendout */ - if (doit){ - /* Handle blendin */ + /* Handle blendin & blendout */ + if (doit){ + /* Handle blendin */ - if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){ - blendfac = stripframe/strip->blendin; - } - else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){ - blendfac = (length-stripframe)/(strip->blendout); + if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){ + blendfac = stripframe/strip->blendin; + } + else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){ + blendfac = (length-stripframe)/(strip->blendout); + } + else + blendfac = 1; + + /* Blend this pose with the accumulated pose */ + blend_poses (apose, tpose, blendfac, strip->mode); + #ifdef __NLA_BLENDCON + blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode); + #endif } - else - blendfac = 1; - - /* Blend this pose with the accumulated pose */ - blend_poses (apose, tpose, blendfac, strip->mode); -#ifdef __NLA_BLENDCON - blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode); -#endif + } + if (apose){ + extract_pose_from_pose(ob->pose, apose); + #ifdef __NLA_BLENDCON + get_constraint_influence_from_pose(ob->pose, apose); + #endif } - } - if (apose){ - get_pose_from_pose(&ob->pose, apose); -#ifdef __NLA_BLENDCON - get_constraint_influence_from_pose(ob->pose, apose); -#endif } + } + + /* Do local action (always overrides the nla actions) */ + /* At the moment, only constraint ipos on the local action have any effect */ + if(ob->action) { + extract_pose_from_action (ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0)); + do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0)); + doit = 1; + } } - - /* Do local action (always overrides the nla actions) */ - /* At the moment, only constraint ipos on the local action have any effect */ - if(ob->action) { - get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0)); - do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0)); - doit = 1; - } - - if (doit) - apply_pose_armature(get_armature(ob), ob->pose, 1); - - } - + } if(only_this) break; base= base->next; @@ -608,222 +738,15 @@ void do_all_actions(Object *only_this) } if (apose){ - clear_pose(apose); + free_pose_channels(apose); MEM_freeN(apose); apose = NULL; } if (tpose){ - clear_pose(tpose); + free_pose_channels(tpose); MEM_freeN(tpose); apose = NULL; } } -static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime) -{ - bPoseChannel *pchan; - bActionChannel *achan; - - if (!pose || !act) - return; - - for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ - achan=get_named_actionchannel(act, pchan->name); - if (achan) - do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime); - } -} - -bActionChannel *get_named_actionchannel(bAction *act, const char *name) -{ - bActionChannel *chan; - - if (!act) - return NULL; - - for (chan = act->chanbase.first; chan; chan=chan->next){ - if (!strcmp (chan->name, name)) - return chan; - } - - return NULL; -} - -void clear_pose(bPose *pose) -{ - bPoseChannel *chan; - - if (pose->chanbase.first){ - for (chan = pose->chanbase.first; chan; chan=chan->next){ - free_constraints(&chan->constraints); - } - BLI_freelistN (&pose->chanbase); - } -} - -void make_local_action(bAction *act) -{ - Object *ob; - bAction *actn; - int local=0, lib=0; - - if(act->id.lib==0) return; - if(act->id.us==1) { - act->id.lib= 0; - act->id.flag= LIB_LOCAL; - new_id(0, (ID *)act, 0); - return; - } - - ob= G.main->object.first; - while(ob) { - if(ob->action==act) { - if(ob->id.lib) lib= 1; - else local= 1; - } - ob= ob->id.next; - } - - if(local && lib==0) { - act->id.lib= 0; - act->id.flag= LIB_LOCAL; - new_id(0, (ID *)act, 0); - } - else if(local && lib) { - actn= copy_action(act); - actn->id.us= 0; - - ob= G.main->object.first; - while(ob) { - if(ob->action==act) { - - if(ob->id.lib==0) { - ob->action = actn; - ob->activecon = NULL; - actn->id.us++; - act->id.us--; - } - } - ob= ob->id.next; - } - } -} - - -void free_action(bAction *act) -{ - bActionChannel *chan; - - /* Free channels */ - for (chan=act->chanbase.first; chan; chan=chan->next){ - if (chan->ipo) - chan->ipo->id.us--; - free_constraint_channels(&chan->constraintChannels); - } - - if (act->chanbase.first) - BLI_freelistN (&act->chanbase); -} - -bAction* copy_action(bAction *src) -{ - bAction *dst = NULL; - bActionChannel *dchan, *schan; - - if(!src) return NULL; - - dst= copy_libblock(src); - duplicatelist(&(dst->chanbase), &(src->chanbase)); - - for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){ - dchan->ipo = copy_ipo(dchan->ipo); - copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels); - } - dst->id.flag |= LIB_FAKEUSER; - dst->id.us++; - return dst; -} - -bPoseChannel *copy_pose_channel(const bPoseChannel* src) -{ - bPoseChannel *dst; - - if (!src) - return NULL; - - dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel"); - memcpy (dst, src, sizeof(bPoseChannel)); - dst->prev=dst->next=NULL; - - return dst; -} - -void copy_pose(bPose **dst, bPose *src, int copycon) -{ - bPose *outPose; - bPose * inPose; - bPoseChannel *newChan; - bPoseChannel *curChan; - - inPose = src; - - if (!inPose){ - *dst=NULL; - return; - } - - outPose=MEM_callocN(sizeof(bPose), "pose"); - - for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){ - newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel"); - - strcpy (newChan->name, curChan->name); - newChan->flag=curChan->flag; - - memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc)); - memcpy (newChan->size, curChan->size, sizeof (curChan->size)); - memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat)); - Mat4CpyMat4 (newChan->obmat, (void *)curChan->obmat); - - BLI_addtail (&outPose->chanbase, newChan); - if (copycon){ - copy_constraints(&newChan->constraints, &curChan->constraints); - } - } - - *dst=outPose; -} - -bPoseChannel *set_pose_channel(bPose *pose, bPoseChannel *chan) -{ - /* chan is no longer valid for the calling function. - and should not be used by that function after calling - this one - */ - bPoseChannel *curChan; - - /* Determine if an equivalent channel exists already */ - for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){ - if (!strcmp (curChan->name, chan->name)){ - if (chan->flag & POSE_ROT) - memcpy (curChan->quat, chan->quat, sizeof(chan->quat)); - if (chan->flag & POSE_SIZE) - memcpy (curChan->size, chan->size, sizeof(chan->size)); - if (chan->flag & POSE_LOC) - memcpy (curChan->loc, chan->loc, sizeof(chan->loc)); - if (chan->flag & PCHAN_DONE) - Mat4CpyMat4 (curChan->obmat, chan->obmat); - - curChan->flag |= chan->flag; - MEM_freeN (chan); - return curChan; - } - } - - MEM_freeN (chan); - return NULL; - /* If an equivalent channel doesn't exist, then don't bother setting it. */ -} - - diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index f92294df3d1..9ff8abf0f2a 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -89,7 +89,7 @@ void calc_curvepath(Object *ob) /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ - if(ob==0 || ob->type != OB_CURVE) return; + if(ob==NULL || ob->type != OB_CURVE) return; cu= ob->data; if(ob==G.obedit) nu= editNurb.first; else nu= cu->nurb.first; @@ -98,10 +98,6 @@ void calc_curvepath(Object *ob) cu->path= NULL; bl= cu->bev.first; - if(bl==NULL) { - makeDispList(ob); - bl= cu->bev.first; - } if(bl==NULL) return; cu->path=path= MEM_callocN(sizeof(Path), "path"); @@ -213,11 +209,10 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK float data[4]; int cycl=0, s0, s1, s2, s3; - if(ob==0 || ob->type != OB_CURVE) return 0; + if(ob==NULL || ob->type != OB_CURVE) return 0; cu= ob->data; - if(cu->path==0 || cu->path->data==0) { - calc_curvepath(ob); - if(cu->path==0 || cu->path->data==0) return 0; + if(cu->path==NULL || cu->path->data==NULL) { + printf("no path!\n"); } path= cu->path; fp= path->data; @@ -242,7 +237,8 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK p2= fp + 4*s2; p3= fp + 4*s3; - if(cu->flag & CU_FOLLOW) { + /* note, commented out for follow constraint */ + //if(cu->flag & CU_FOLLOW) { set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE); @@ -254,7 +250,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK dir[0]= -dir[0]; dir[1]= -dir[1]; dir[2]= -dir[2]; - } + //} nu= cu->nurb.first; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 1f96b48df9b..61122610e50 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -6,10 +6,7 @@ * 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. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,9 +20,7 @@ * 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. + * Contributor(s): Full recode, Ton Roosendaal, Crete 2005 * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -50,6 +45,7 @@ #include "DNA_view3d_types.h" #include "DNA_constraint_types.h" +#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_main.h" @@ -71,77 +67,192 @@ #include <config.h> #endif -/* Function prototypes */ - -static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit); -static Bone *get_named_bone_bonechildren (Bone *bone, const char *name); -static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index); -/*void make_bone_parent_matrix (Bone* bone);*/ -static void copy_bonechildren (Bone* newBone, Bone* oldBone); -static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]); -static int verify_boneptr_children (Bone *cBone, Bone *tBone); -static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime); -static Bone *get_last_ik_bone (Bone *bone); -static void precalc_bonelist_posemats(ListBase *bonelist, float parlen); - -/* Globals */ +/* ugly Globals */ static float g_premat[4][4]; static float g_postmat[4][4]; static MDeformVert *g_dverts; static ListBase *g_defbase; -static bArmature *g_defarm; +static Object *g_deform; -/* Functions */ +/* **************** Generic Functions, data level *************** */ + +bArmature *get_armature(Object *ob) +{ + if(ob==NULL) return NULL; + if(ob->type==OB_ARMATURE) return ob->data; + else return NULL; +} -float get_bone_length (Bone *bone) +bArmature *add_armature() { - float result[3]; + bArmature *arm; + + arm= alloc_libblock (&G.main->armature, ID_AR, "Armature"); + return arm; +} - VecSubf (result, bone->tail, bone->head); - return (float)sqrt(result[0]*result[0] + result[1]*result[1] + result[2]*result[2]); +void free_boneChildren(Bone *bone) +{ + Bone *child; + + if (bone) { + + child=bone->childbase.first; + if (child){ + while (child){ + free_boneChildren (child); + child=child->next; + } + BLI_freelistN (&bone->childbase); + } + } } -void apply_bonemat(Bone *bone) +void free_bones (bArmature *arm) { - float mat[3][3], imat[3][3], tmat[3][3]; + Bone *bone; + /* Free children (if any) */ + bone= arm->bonebase.first; + if (bone) { + while (bone){ + free_boneChildren (bone); + bone=bone->next; + } + } + - if(!bone) + BLI_freelistN(&arm->bonebase); +} + +void free_armature(bArmature *arm) +{ + if (arm) { + /* unlink_armature(arm);*/ + free_bones(arm); + } +} + +void make_local_armature(bArmature *arm) +{ + int local=0, lib=0; + Object *ob; + bArmature *newArm; + + if (arm->id.lib==0) return; + if (arm->id.us==1) { + arm->id.lib= 0; + arm->id.flag= LIB_LOCAL; + new_id(0, (ID*)arm, 0); + return; + } + + if(local && lib==0) { + arm->id.lib= 0; + arm->id.flag= LIB_LOCAL; + new_id(0, (ID *)arm, 0); + } + else if(local && lib) { + newArm= copy_armature(arm); + newArm->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==arm) { + + if(ob->id.lib==0) { + ob->data= newArm; + newArm->id.us++; + arm->id.us--; + } + } + ob= ob->id.next; + } + } +} - Mat3CpyMat4(mat, bone->obmat); +static void copy_bonechildren (Bone* newBone, Bone* oldBone) +{ + Bone *curBone, *newChildBone; - VECCOPY(bone->loc, bone->obmat[3]); + /* Copy this bone's list*/ + duplicatelist (&newBone->childbase, &oldBone->childbase); + + /* For each child in the list, update it's children*/ + newChildBone=newBone->childbase.first; + for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){ + newChildBone->parent=newBone; + copy_bonechildren(newChildBone,curBone); + newChildBone=newChildBone->next; + } +} + +bArmature *copy_armature(bArmature *arm) +{ + bArmature *newArm; + Bone *oldBone, *newBone; + + newArm= copy_libblock (arm); + duplicatelist(&newArm->bonebase, &arm->bonebase); + + /* Duplicate the childrens' lists*/ + newBone=newArm->bonebase.first; + for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){ + newBone->parent=NULL; + copy_bonechildren (newBone, oldBone); + newBone=newBone->next; + }; - Mat3ToQuat(mat, bone->quat); - QuatToMat3(bone->quat, tmat); + return newArm; +} - Mat3Inv(imat, tmat); +static Bone *get_named_bone_bonechildren (Bone *bone, const char *name) +{ + Bone *curBone, *rbone; - Mat3MulMat3(tmat, imat, mat); + if (!strcmp (bone->name, name)) + return bone; - bone->size[0]= tmat[0][0]; - bone->size[1]= tmat[1][1]; - bone->size[2]= tmat[2][2]; + for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ + rbone=get_named_bone_bonechildren (curBone, name); + if (rbone) + return rbone; + } + + return NULL; +} + +Bone *get_named_bone (bArmature *arm, const char *name) +/* + Walk the list until the bone is found + */ +{ + Bone *bone=NULL, *curBone; + + if (!arm) return NULL; + + for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ + bone = get_named_bone_bonechildren (curBone, name); + if (bone) + return bone; + } + + return bone; } +/* ****************** Game Blender functions, called by engine ************** */ + void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]) { float obinv[4][4]; -#if 0 - Mat4Invert(obinv, obmat); - Mat4CpyMat4(premat, obmat); - Mat4MulMat4(postmat, parmat, obinv); - Mat4Invert (postmat, premat); -#else Mat4Invert(obinv, obmat); Mat4CpyMat4(premat, obmat); Mat4MulMat4(postmat, parmat, obinv); Mat4Invert (premat, postmat); -#endif } void GB_init_armature_deform(ListBase *defbase, float premat[][4], float postmat[][4]) @@ -176,7 +287,7 @@ void GB_calc_armature_deform (float *co, MDeformVert *dvert) for (i=0; i<dvert->totweight; i++){ bone = dvert->dw[i].data; - if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib); +// if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib); } if (contrib){ @@ -189,207 +300,13 @@ void GB_calc_armature_deform (float *co, MDeformVert *dvert) Mat4MulVecfl(g_postmat, co); } -static Bone *get_last_ik_bone (Bone *bone) -{ - Bone *curBone; - - for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ - if (curBone->flag & BONE_IK_TOPARENT){ - return get_last_ik_bone (curBone); - } - } - - return bone; -} - -#if 0 -static Bone *get_first_ik_bone (Bone *bone) -{ - Bone *curBone; - - for (curBone = bone; curBone; curBone=curBone->parent){ - if (!bone->parent) - return curBone; - if (!bone->flag & BONE_IK_TOPARENT) - return curBone; - } - - return bone; -/* for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ - if (curBone->flag & BONE_IK_TOPARENT){ - return get_last_ik_bone (curBone); - } - } -*/ - return bone; - -} -#endif - -void where_is_bone(Object *ob, Bone *bone) -{ - where_is_bone_time (ob, bone, G.scene->r.cfra); -} - -void where_is_bone_time (Object *ob, Bone *bone, float ctime) -{ - where_is_bone1_time (ob, get_last_ik_bone(bone), ctime); -} - -void rebuild_bone_parent_matrix (Bone *bone) -{ - if (!bone) - return; - - if (bone->parent) - rebuild_bone_parent_matrix(bone->parent); - - /* Get the parent inverse */ - if (bone->parent) - Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat); - else - Mat4One (bone->parmat); - -} -void where_is_bone1_time (Object *ob, Bone *bone, float ctime) -/* Assumes the pose has already been retrieved from the action */ -/* Also assumes where_is_object has been called for owner */ -{ - bPose *pose; - bPoseChannel *chan; - bArmature *arm; - float imat[4][4]; - float totmat[4][4]; - Object conOb; - - pose = ob->pose; - if (!pose) - return; - - arm = get_armature(ob); - - /* Ensure there is a channel for this bone*/ - chan = verify_pose_channel (pose, bone->name); - if (!chan) return; - -#if 1 - /* If 1 attempt to use pose caching features */ - /* Bail out if we've been recalced recently */ - if (chan->flag & PCHAN_DONE){ - Mat4CpyMat4 (bone->obmat, chan->obmat); - if (bone->parent){ - if ((bone->flag & BONE_IK_TOPARENT)) - where_is_bone1_time (ob, bone->parent, ctime); - else - where_is_bone_time (ob, bone->parent, ctime); - } - return; - } - else - chan->flag |= PCHAN_DONE; -#endif - -#if 1 - /* Ensure parents have been evaluated */ - if (bone->parent){ - if ((bone->flag & BONE_IK_TOPARENT)) - where_is_bone1_time (ob, bone->parent, ctime); - else - where_is_bone_time (ob, bone->parent, ctime); - } - -#endif - - if (arm){ - if ((arm->flag & ARM_RESTPOS) || ((G.obedit && (ob->data == G.obedit->data)))){ - Mat4One (bone->obmat); - Mat4One (chan->obmat); - return; - } - } - - /* If the bone has been flagged as 'no calc', let's not - * bother calculating it. - */ - if (bone->flag & BONE_NOCALC) { - return; - } - - if (bone->flag & BONE_IK_TOPARENT){ - bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F; - } - bone_to_mat4(bone, bone->obmat); - - /* Do constraints */ - // clear_workob(); - - memset(&conOb, 0, sizeof(Object)); - conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0; - - /* Collect the constraints from the pose */ - conOb.constraints.first = chan->constraints.first; - conOb.constraints.last = chan->constraints.last; - - /* Totmat takes bone's obmat to worldspace */ - - { - float parmat[4][4]; - float temp[4][4]; - - Mat4CpyMat4 (temp, bone->obmat); - Mat4One (bone->obmat); - get_objectspace_bone_matrix(bone, parmat, 1, 1); - Mat4CpyMat4 (bone->obmat, temp); - Mat4MulMat4 (totmat, parmat, ob->obmat); - } - - /* Build a workob to pass the bone to the constraint solver */ - conOb.data = ob->data; - conOb.type = ob->type; - conOb.parent = ob; - conOb.trackflag = ob->trackflag; - conOb.upflag = ob->upflag; - - VECCOPY(conOb.size, bone->size); - - Mat4MulMat4 (conOb.obmat, bone->obmat, totmat); - - /* Solve */ - solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime); - - { - float parmat[4][4]; - float temp[4][4]; - - Mat4CpyMat4 (temp, bone->obmat); - Mat4One (bone->obmat); - get_objectspace_bone_matrix(bone, parmat, 1, 1); - Mat4CpyMat4 (bone->obmat, temp); - Mat4MulMat4 (totmat, parmat, ob->obmat); - } - - VECCOPY(bone->size, conOb.size); - - /* Take out of worldspace */ - Mat4Invert (imat, totmat); - Mat4MulMat4 (bone->obmat, conOb.obmat, imat); - Mat4CpyMat4 (chan->obmat, bone->obmat); - -} - - -bArmature *get_armature(Object *ob) -{ - if(ob==NULL) return NULL; - if(ob->type==OB_ARMATURE) return ob->data; - else return NULL; -} +/* ****************** END Game Blender functions, called by engine ************** */ +/* ************ Armature Deform ******************* */ void init_armature_deform(Object *parent, Object *ob) { bArmature *arm; bDeformGroup *dg; - Bone *curBone; MDeformVert *dvert; int totverts; float obinv[4][4]; @@ -399,18 +316,8 @@ void init_armature_deform(Object *parent, Object *ob) if (!arm) return; - if (ob) - where_is_object (ob); - -#if 1 - apply_pose_armature (arm, parent->pose, 1); /* Hopefully doit parameter can be set to 0 in future */ - where_is_armature (parent); -#else - apply_pose_armature (arm, parent->pose, 0); -#endif - g_defbase = &ob->defbase; - g_defarm = arm; + g_deform = parent; Mat4Invert(obinv, ob->obmat); Mat4CpyMat4(g_premat, ob->obmat); @@ -428,17 +335,12 @@ void init_armature_deform(Object *parent, Object *ob) totverts=0; } - /* Precalc bone defmats */ - precalc_armature_posemats (arm); - - for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ - precalc_bone_defmat(curBone); - } + /* bone defmats are already in the channels, chan_mat */ - /* Validate bone data in bDeformGroups */ + /* Validate channel data in bDeformGroups */ for (dg=g_defbase->first; dg; dg=dg->next) - dg->data = (void*)get_named_bone(arm, dg->name); + dg->data = (void*)get_pose_channel(parent->pose, dg->name); if (g_dverts){ for (j=0; j<totverts; j++){ @@ -456,114 +358,6 @@ void init_armature_deform(Object *parent, Object *ob) } } -void get_bone_root_pos (Bone* bone, float vec[3], int posed) -{ - Bone *curBone; - float mat[4][4]; - - get_objectspace_bone_matrix(bone, mat, 1, posed); - VECCOPY (vec, mat[3]); - return; - - rebuild_bone_parent_matrix(bone); - if (posed){ - - get_objectspace_bone_matrix(bone, mat, 1, posed); - VECCOPY (vec, mat[3]); - } - else { - vec[0]=vec[1]=vec[2]=0.0F; - for (curBone=bone; curBone; curBone=curBone->parent){ - if (curBone==bone) - VecAddf (vec, vec, curBone->head); - else - VecAddf (vec, vec, curBone->tail); - } - } -} - -void get_bone_tip_pos (Bone* bone, float vec[3], int posed) -{ - Bone *curBone; - float mat[4][4], tmat[4][4], rmat[4][4], bmat[4][4], fmat[4][4]; - - get_objectspace_bone_matrix(bone, mat, 0, posed); - VECCOPY (vec, mat[3]); - return; - - rebuild_bone_parent_matrix(bone); - if (posed){ - - Mat4One (mat); - - for (curBone = bone; curBone; curBone=curBone->parent){ - Mat4One (bmat); - /* [BMAT] This bone's offset */ - VECCOPY (bmat[3], curBone->head); - if (curBone==bone){ - Mat4One (tmat); - VecSubf (tmat[3], curBone->tail, curBone->head); - Mat4MulMat4 (bmat, tmat, curBone->obmat); - VecAddf (bmat[3], bmat[3], curBone->head); - } - else - VecAddf (bmat[3], bmat[3], curBone->obmat[3]); // Test - - /* [RMAT] Parent's bone length = parent rotmat * bone length */ - if (curBone->parent){ - Mat4One (tmat); - VecSubf (tmat[3], curBone->parent->tail, curBone->parent->head); - Mat4MulMat4 (rmat, tmat, curBone->parent->obmat); - VecSubf (rmat[3], rmat[3], curBone->parent->obmat[3]); - } - else - Mat4One (rmat); - - Mat4MulSerie (fmat, rmat, bmat, mat, 0, 0, 0, 0, 0); - Mat4CpyMat4 (mat, fmat); - } - - VECCOPY (vec, mat[3]); - } - else{ - vec[0]=vec[1]=vec[2]=0.0F; - for (curBone=bone; curBone; curBone=curBone->parent){ - VecAddf (vec, vec, curBone->tail); - } - } -} - -int verify_boneptr (bArmature *arm, Bone *bone) -{ - /* Ensures that a given bone exists in an armature */ - Bone *curBone; - - if (!arm) - return 0; - - for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ - if (verify_boneptr_children (curBone, bone)) - return 1; - } - - return 0; -} - -static int verify_boneptr_children (Bone *cBone, Bone *tBone) -{ - Bone *curBone; - - if (cBone == tBone) - return 1; - - for (curBone=cBone->childbase.first; curBone; curBone=curBone->next){ - if (verify_boneptr_children (curBone, tBone)) - return 1; - } - return 0; -} - - float dist_to_bone (float vec[3], float b1[3], float b2[3]) { /* float dist=0; */ @@ -592,137 +386,41 @@ float dist_to_bone (float vec[3], float b1[3], float b2[3]) else { return (hsqr - (a*a)); } - - } -static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]) +static float calc_armature_deform_bone(Bone *bone, bPoseChannel *pchan, float *vec, float *co) { - Bone *curBone; - float root[3]; - float tip[3]; float dist, fac, ifac; float cop[3]; - float bdsqr; - - - get_bone_root_pos (bone, root, 0); - get_bone_tip_pos (bone, tip, 0); + float bdsqr, contrib=0.0; bdsqr = bone->dist*bone->dist; VECCOPY (cop, co); - dist = dist_to_bone(cop, root, tip); + dist = dist_to_bone(cop, bone->arm_head, bone->arm_tail); if ((dist) <= bdsqr){ fac = (dist)/bdsqr; ifac = 1.0F-fac; ifac*=bone->weight; - - if (!vec) - (*contrib) +=ifac; - else{ - ifac*=(1.0F/(*contrib)); + contrib= ifac; + if(contrib>0.0) { VECCOPY (cop, co); - Mat4MulVecfl(bone->defmat, cop); + Mat4MulVecfl(pchan->chan_mat, cop); VecSubf (cop, cop, co); // Make this a delta from the base position cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac; VecAddf (vec, vec, cop); - - } - } - -// calc_bone_deform (bone, bone->weight, vec, co, contrib, obmat); - for (curBone = bone->childbase.first; curBone; curBone=curBone->next) - calc_armature_deform_bonechildren (curBone, vec, co, contrib, obmat); -} - -void precalc_bone_irestmat (Bone *bone) -{ - float restmat[4][4]; - - get_objectspace_bone_matrix(bone, restmat, 1, 0); - Mat4Invert (bone->irestmat, restmat); -} - -static void precalc_bonelist_posemats(ListBase *bonelist, float parlen) -{ - Bone *curBone; - float length; - float T_parlen[4][4]; - float T_root[4][4]; - float M_obmat[4][4]; - float R_bmat[4][4]; - float M_accumulatedMatrix[4][4]; - float delta[3]; - - for (curBone = bonelist->first; curBone; curBone=curBone->next){ - - /* Get the length translation (length along y axis) */ - length = get_bone_length(curBone); - - /* Get the bone's root offset (in the parent's coordinate system) */ - Mat4One (T_root); - VECCOPY (T_root[3], curBone->head); - - /* Compose the restmat */ - VecSubf(delta, curBone->tail, curBone->head); - make_boneMatrixvr(R_bmat, delta, curBone->roll); - - /* Retrieve the obmat (user transformation) */ - Mat4CpyMat4 (M_obmat, curBone->obmat); - - /* Compose the accumulated matrix (i.e. parent matrix * parent translation ) */ - if (curBone->parent){ - Mat4One (T_parlen); - T_parlen[3][1] = parlen; - Mat4MulMat4 (M_accumulatedMatrix, T_parlen, curBone->parent->posemat); } - else - Mat4One (M_accumulatedMatrix); - - /* Compose the matrix for this bone */ - Mat4MulSerie (curBone->posemat, M_accumulatedMatrix, T_root, R_bmat, M_obmat, NULL, NULL, NULL, NULL); - - precalc_bonelist_posemats(&curBone->childbase, length); } -} - -void precalc_armature_posemats (bArmature *arm) -{ - precalc_bonelist_posemats(&arm->bonebase, 0.0); -} - -void precalc_bone_defmat (Bone *bone) -{ - Bone *curBone; -#if 0 - float restmat[4][4]; - float posemat[4][4]; - float imat[4][4]; - /* Store restmat and restmat inverse - Calculate once when leaving editmode */ - /* Store all bones' posemats - Do when applied */ - - /* EXPENSIVE! Don't do this! */ - get_objectspace_bone_matrix(bone, restmat, 1, 0); - get_objectspace_bone_matrix(bone, posemat, 1, 1); - Mat4Invert (imat, restmat); - Mat4MulMat4 (bone->defmat, imat, posemat); - /* /EXPENSIVE */ -#else - Mat4MulMat4 (bone->defmat, bone->irestmat, bone->posemat); -#endif - for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ - precalc_bone_defmat(curBone); - } + return contrib; } -void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *contrib) +void calc_bone_deform (bPoseChannel *pchan, float weight, float *vec, float *co, float *contrib) { float cop[3]; @@ -731,7 +429,7 @@ void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *c VECCOPY (cop, co); - Mat4MulVecfl(bone->defmat, cop); + Mat4MulVecfl(pchan->chan_mat, cop); vec[0]+=(cop[0]-co[0])*weight; vec[1]+=(cop[1]-co[1])*weight; @@ -742,540 +440,638 @@ void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *c void calc_armature_deform (Object *ob, float *co, int index) { - bArmature *arm; - Bone *bone; - Bone *curBone; + bPoseChannel *pchan; + MDeformVert *dvert = g_dverts+index; float vec[3]; - float contrib=0; + float contrib=0.0; int i; - MDeformVert *dvert = g_dverts+index; - arm=g_defarm; vec[0]=vec[1]=vec[2]=0; /* Apply the object's matrix */ Mat4MulVecfl(g_premat, co); + /* using deform vertex groups */ if (g_dverts){ + for (i=0; i<dvert->totweight; i++){ - bone = dvert->dw[i].data; - if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib); + pchan = (bPoseChannel *)dvert->dw[i].data; + if (pchan) calc_bone_deform (pchan, dvert->dw[i].weight, vec, co, &contrib); } + } + else { /* or use bone distances */ + Bone *bone; - if (contrib){ - vec[0]/=contrib; - vec[1]/=contrib; - vec[2]/=contrib; + for(pchan= g_deform->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + if(bone) { + contrib+= calc_armature_deform_bone(bone, pchan, vec, co); + } } - VecAddf (co, vec, co); - Mat4MulVecfl(g_postmat, co); - return; - } - - // Count the number of interested bones - for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) - calc_armature_deform_bonechildren (curBone, NULL, co, &contrib, ob->obmat); - - // Do the deformation - for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) - calc_armature_deform_bonechildren (curBone, vec, co, &contrib, ob->obmat); + } + if (contrib>0.0){ + vec[0]/=contrib; + vec[1]/=contrib; + vec[2]/=contrib; + } VecAddf (co, vec, co); Mat4MulVecfl(g_postmat, co); } -void apply_pose_armature (bArmature* arm, bPose* pose, int doit) -{ - Bone *curBone; - for (curBone = arm->bonebase.first; curBone; curBone=curBone->next){ - apply_pose_bonechildren (curBone, pose, doit); - } -} +/* ************ END Armature Deform ******************* */ -void where_is_armature (Object *ob) +void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed) { - where_is_object (ob); - where_is_armature_time(ob, (float)G.scene->r.cfra); + Mat4CpyMat4(M_accumulatedMatrix, bone->arm_mat); } -void where_is_armature_time (Object *ob, float ctime) +#if 0 +/* IK in the sense of; connected directly */ +static Bone *get_last_ik_bone (Bone *bone) { - bArmature *arm; - - arm = get_armature(ob); - if (!arm) - return; + Bone *curBone; + + for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ + if (curBone->flag & BONE_IK_TOPARENT){ + return get_last_ik_bone (curBone); + } + } + + return bone; +} - where_is_bonelist_time (ob, &arm->bonebase, ctime); +#endif -} +/* **************** The new & simple (but OK!) armature evaluation ********* */ -static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime) -{ - Bone *curBone; +/* ****************** And how it works! **************************************** - for (curBone=base->first; curBone; curBone=curBone->next){ - if (!curBone->childbase.first) - where_is_bone1_time (ob, curBone, ctime); + This is the bone transformation trick; they're hierarchical so each bone(b) + is in the coord system of bone(b-1): - where_is_bonelist_time(ob, &curBone->childbase, ctime); - } -} -static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit) -{ - Bone *curBone; - bPoseChannel *chan; + arm_mat(b)= arm_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) + + -> yoffs is just the y axis translation in parent's coord system + -> d_root is the translation of the bone root, also in parent's coord system - if (!pose){ - - bone->dsize[0]=bone->dsize[1]=bone->dsize[2]=1.0F; - bone->size[0]=bone->size[1]=bone->size[2]=1.0F; + pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) - bone->dquat[0]=bone->dquat[1]=bone->dquat[2]=bone->dquat[3]=0; - bone->quat[0]=bone->quat[1]=bone->quat[2]=bone->quat[3]=0.0F; - - bone->dloc[0]=bone->dloc[1]=bone->dloc[2]=0.0F; - bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F; - } + we then - in init deform - store the deform in chan_mat, such that: - // Ensure there is a channel for this bone - chan = verify_pose_channel (pose, bone->name); + pose_mat(b)= arm_mat(b) * chan_mat(b) + + *************************************************************************** */ - /* Only do this crazy stuff if the no calc flag - * is cleared for this bone. - */ - if (chan && (~bone->flag & BONE_NOCALC)) { - if (chan->flag & POSE_LOC) - memcpy (bone->loc, chan->loc, sizeof (bone->loc)); - if (chan->flag & POSE_SIZE) - memcpy (bone->size, chan->size, sizeof (bone->size)); - if (chan->flag & POSE_ROT) - memcpy (bone->quat, chan->quat, sizeof (bone->quat)); - - if (doit){ - bone_to_mat4(bone, bone->obmat); - } - else{ - Mat4CpyMat4 (bone->obmat, chan->obmat); - } - } - - for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ - apply_pose_bonechildren (curBone, pose, doit); - } -} -void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll) /* Calculates the rest matrix of a bone based On its vector and a roll around that vector */ +void vec_roll_to_mat3(float *vec, float roll, float mat[][3]) { - float nor[3],axis[3],target[3]={0,1,0}; + float nor[3], axis[3], target[3]={0,1,0}; float theta; - float rMatrix[3][3], bMatrix[3][3], fMatrix[3][3]; - - VECCOPY (nor,delta); + float rMatrix[3][3], bMatrix[3][3]; + + VECCOPY (nor, vec); Normalise (nor); - + /* Find Axis & Amount for bone matrix*/ Crossf (axis,target,nor); - + if (Inpf(axis,axis) > 0.0000000000001) { /* if nor is *not* a multiple of target ... */ Normalise (axis); theta=(float) acos (Inpf (target,nor)); - + /* Make Bone matrix*/ VecRotToMat3(axis, theta, bMatrix); } else { /* if nor is a multiple of target ... */ float updown; - + /* point same direction, or opposite? */ updown = ( Inpf (target,nor) > 0 ) ? 1.0 : -1.0; - + /* I think this should work ... */ bMatrix[0][0]=updown; bMatrix[0][1]=0.0; bMatrix[0][2]=0.0; bMatrix[1][0]=0.0; bMatrix[1][1]=updown; bMatrix[1][2]=0.0; bMatrix[2][0]=0.0; bMatrix[2][1]=0.0; bMatrix[2][2]=1.0; } - + /* Make Roll matrix*/ VecRotToMat3(nor, roll, rMatrix); /* Combine and output result*/ - Mat3MulMat3 (fMatrix,rMatrix,bMatrix); - Mat4CpyMat3 (outmatrix,fMatrix); + Mat3MulMat3 (mat, rMatrix, bMatrix); } -void make_boneMatrix (float outmatrix[][4], Bone *bone) -/* Calculates the rest matrix of a bone based - On its vector and a roll around that vector */ + +/* recursive part, calculates restposition of entire tree of children */ +/* used by exiting editmode too */ +void where_is_armature_bone(Bone *bone, Bone *prevbone) { - float delta[3]; - float parmat[4][4], imat[4][4], obmat[4][4]; + float vec[3]; + + /* Bone Space */ + VecSubf (vec, bone->tail, bone->head); + vec_roll_to_mat3(vec, bone->roll, bone->bone_mat); - if (bone->parent){ - VecSubf (delta, bone->parent->tail, bone->parent->head); - make_boneMatrixvr(parmat, delta, bone->parent->roll); + bone->length= VecLenf(bone->head, bone->tail); + + if(prevbone) { + float offs_bone[4][4]; // yoffs(b-1) + root(b) + bonemat(b) + + /* bone transform itself */ + Mat4CpyMat3(offs_bone, bone->bone_mat); + + /* The bone's root offset (is in the parent's coordinate system) */ + VECCOPY(offs_bone[3], bone->head); + + /* Get the length translation of parent (length along y axis) */ + offs_bone[3][1]+= prevbone->length; + + /* Compose the matrix for this bone */ + Mat4MulMat4(bone->arm_mat, offs_bone, prevbone->arm_mat); } - else{ - Mat4One (parmat); + else { + Mat4CpyMat3(bone->arm_mat, bone->bone_mat); + VECCOPY(bone->arm_mat[3], bone->head); } - - Mat4Invert (imat, parmat); - VecSubf (delta, bone->tail, bone->head); - make_boneMatrixvr(obmat, delta, bone->roll); - - Mat4MulMat4(outmatrix, obmat, imat); - + /* head */ + VECCOPY(bone->arm_head, bone->arm_mat[3]); + /* tail is in current local coord system */ + VECCOPY(vec, bone->arm_mat[1]); + VecMulf(vec, bone->length); + VecAddf(bone->arm_tail, bone->arm_head, vec); + + /* and the kiddies */ + prevbone= bone; + for(bone= bone->childbase.first; bone; bone= bone->next) { + where_is_armature_bone(bone, prevbone); + } } - -bArmature *add_armature() +/* updates vectors and matrices on rest-position level, only needed + after editing armature itself, now only on reading file */ +void where_is_armature (bArmature *arm) { - bArmature *arm; - - arm= alloc_libblock (&G.main->armature, ID_AR, "Armature"); - - if(arm) { - + Bone *bone; + /* hierarchical from root to children */ + for(bone= arm->bonebase.first; bone; bone= bone->next) { + where_is_armature_bone(bone, NULL); } - return arm; } +static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int depth, int counter) +{ + bPoseChannel *pchan = verify_pose_channel (pose, bone->name); // verify checks and/or adds -void free_boneChildren(Bone *bone) -{ - Bone *child; - - if (bone) { - - child=bone->childbase.first; - if (child){ - while (child){ - free_boneChildren (child); - child=child->next; - } - BLI_freelistN (&bone->childbase); - } + pchan->bone= bone; + pchan->parent= parchan; + pchan->depth= depth; + counter++; + + for(bone= bone->childbase.first; bone; bone= bone->next) { + counter= rebuild_pose_bone(pose, bone, pchan, depth+1, counter); } + + return counter; } -void free_bones (bArmature *arm) +/* only after leave editmode, but also for validating older files */ +/* NOTE: pose->flag is set for it */ +void armature_rebuild_pose(Object *ob, bArmature *arm) { Bone *bone; - /* Free children (if any) */ - bone= arm->bonebase.first; - if (bone) { - while (bone){ - free_boneChildren (bone); - bone=bone->next; + bPose *pose; + bPoseChannel *pchan, *next; + int counter=0; + + /* only done here */ + if(ob->pose==NULL) ob->pose= MEM_callocN(sizeof(bPose), "new pose"); + pose= ob->pose; + + /* first step, check if all channels are there, also sets depth */ + for(bone= arm->bonebase.first; bone; bone= bone->next) { + counter= rebuild_pose_bone(pose, bone, NULL, 0, counter); + } + /* sort channels on dependency order, so we can walk the channel list */ + + /* and a check for garbage */ + for(pchan= pose->chanbase.first; pchan; pchan= next) { + next= pchan->next; + if(pchan->bone==NULL) { + BLI_freelinkN(&pose->chanbase, pchan); // constraints? } } + //printf("rebuild pose, %d bones\n", counter); + if(counter<2) return; + update_pose_constraint_flags(ob->pose); // for IK detection for example - BLI_freelistN(&arm->bonebase); + /* the sorting */ + DAG_pose_sort(ob); + + ob->pose->flag &= ~POSE_RECALC; } -void free_armature(bArmature *arm) -{ - if (arm) { -/* unlink_armature(arm);*/ - free_bones(arm); - } -} -void make_local_armature(bArmature *arm) -{ - int local=0, lib=0; - Object *ob; - bArmature *newArm; +/* ********************** THE IK SOLVER ******************* */ - if (arm->id.lib==0) - return; - if (arm->id.us==1) { - arm->id.lib= 0; - arm->id.flag= LIB_LOCAL; - new_id(0, (ID*)arm, 0); - return; - } - if(local && lib==0) { - arm->id.lib= 0; - arm->id.flag= LIB_LOCAL; - new_id(0, (ID *)arm, 0); +/* allocates PoseChain, and links that to root bone/channel */ +/* note; if we got this working, it can become static too? */ +static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip) +{ + bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256]; + PoseChain *chain; + bConstraint *con; + bKinematicConstraint *data; + int a, segcount= 0; + + /* find IK constraint, and validate it */ + for(con= pchan_tip->constraints.first; con; con= con->next) { + if(con->type==CONSTRAINT_TYPE_KINEMATIC) break; } - else if(local && lib) { - newArm= copy_armature(arm); - newArm->id.us= 0; - - ob= G.main->object.first; - while(ob) { - if(ob->data==arm) { - - if(ob->id.lib==0) { - ob->data= newArm; - newArm->id.us++; - arm->id.us--; - } - } - ob= ob->id.next; + if(con==NULL) return; + if(con->flag & CONSTRAINT_DISABLE) return; // not sure... + + data=(bKinematicConstraint*)con->data; + if(data->tar==NULL) return; + + /* Find the chain's root & count the segments needed */ + for (curchan = pchan_tip; curchan; curchan=curchan->parent){ + pchan_root = curchan; + /* tip is not in the chain */ + if (curchan!=pchan_tip){ + chanlist[segcount]=curchan; + segcount++; } + if(segcount>255) break; // also weak + + if (!(curchan->bone->flag & BONE_IK_TOPARENT)) + break; + } + if (!segcount) return; + + /* setup the chain data */ + chain = MEM_callocN(sizeof(PoseChain), "posechain"); + chain->totchannel= segcount; + chain->solver = IK_CreateChain(); + chain->con= con; + + chain->iterations = data->iterations; + chain->tolerance = data->tolerance; + + chain->pchanchain= MEM_callocN(segcount*sizeof(void *), "channel chain"); + for(a=0; a<segcount; a++) { + chain->pchanchain[a]= chanlist[segcount-a-1]; } + + /* AND! link the chain to the root */ + BLI_addtail(&pchan_root->chain, chain); } -static void copy_bonechildren (Bone* newBone, Bone* oldBone) +/* called from within the core where_is_pose loop, all animsystems and constraints +were executed & assigned. Now as last we do an IK pass */ +static void execute_posechain(Object *ob, PoseChain *chain) { - Bone *curBone, *newChildBone; - - /* Copy this bone's list*/ - duplicatelist (&newBone->childbase, &oldBone->childbase); - - /* For each child in the list, update it's children*/ - newChildBone=newBone->childbase.first; - for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){ - newChildBone->parent=newBone; - copy_bonechildren(newChildBone,curBone); - newChildBone=newChildBone->next; + IK_Segment_Extern *segs; + bPoseChannel *pchan; + float R_parmat[3][3]; + float iR_parmat[3][3]; + float R_bonemat[3][3]; + float rootmat[4][4], imat[4][4]; + float size[3]; + int curseg; + + /* first set the goal inverse transform, assuming the root of chain was done ok! */ + pchan= chain->pchanchain[0]; + Mat4One(rootmat); + VECCOPY(rootmat[3], pchan->pose_head); + + Mat4MulMat4 (imat, rootmat, ob->obmat); + Mat4Invert (chain->goalinv, imat); + + /* and set and transform goal */ + get_constraint_target_matrix(chain->con, TARGET_BONE, NULL, rootmat, size, 1.0); // 1.0=ctime + VECCOPY (chain->goal, rootmat[3]); + Mat4MulVecfl (chain->goalinv, chain->goal); + + /* Now we construct the IK segments */ + segs = MEM_callocN (sizeof(IK_Segment_Extern)*chain->totchannel, "iksegments"); + + for (curseg=0; curseg<chain->totchannel; curseg++){ + + pchan= chain->pchanchain[curseg]; + + /* Get the matrix that transforms from prevbone into this bone */ + Mat3CpyMat4(R_bonemat, pchan->pose_mat); + + if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT)) { + Mat3CpyMat4(R_parmat, pchan->parent->pose_mat); + } + else + Mat3One (R_parmat); + + Mat3Inv(iR_parmat, R_parmat); + + /* Mult and Copy the matrix into the basis and transpose (IK lib likes it) */ + Mat3MulMat3((void *)segs[curseg].basis, iR_parmat, R_bonemat); + Mat3Transp((void *)segs[curseg].basis); + + /* Fill out the IK segment */ + segs[curseg].length = pchan->bone->length; } + + /* Solve the chain */ + + IK_LoadChain(chain->solver, segs, chain->totchannel); + + IK_SolveChain(chain->solver, chain->goal, chain->tolerance, + chain->iterations, 0.1f, chain->solver->segments); + + + /* not yet free! */ } -bArmature *copy_armature(bArmature *arm) -{ - bArmature *newArm; - Bone *oldBone, *newBone; - newArm= copy_libblock (arm); - duplicatelist(&newArm->bonebase, &arm->bonebase); +/* ********************** THE POSE SOLVER ******************* */ - /* Duplicate the childrens' lists*/ - newBone=newArm->bonebase.first; - for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){ - newBone->parent=NULL; - copy_bonechildren (newBone, oldBone); - newBone=newBone->next; - }; - return newArm; -} - - -void bone_to_mat3(Bone *bone, float mat[][3]) /* no parent */ +/* loc/rot/size to mat4 */ +static void chan_calc_mat(bPoseChannel *chan) { float smat[3][3]; float rmat[3][3]; -/* float q1[4], vec[3];*/ - - /* size */ -/* if(bone->ipo) { - vec[0]= bone->size[0]+bone->dsize[0]; - vec[1]= bone->size[1]+bone->dsize[1]; - vec[2]= bone->size[2]+bone->dsize[2]; - SizeToMat3(vec, smat); - } - else -*/ { - SizeToMat3(bone->size, smat); - } - - /* rot */ - /*if(bone->flag & BONE_QUATROT) { - if(bone->ipo) { - QuatMul(q1, bone->quat, bone->dquat); - QuatToMat3(q1, rmat); - } - else - */ { - NormalQuat(bone->quat); - QuatToMat3(bone->quat, rmat); - } -/* } -*/ - Mat3MulMat3(mat, rmat, smat); -} - -void bone_to_mat4(Bone *bone, float mat[][4]) -{ float tmat[3][3]; - bone_to_mat3(bone, tmat); + SizeToMat3(chan->size, smat); + + NormalQuat(chan->quat); + QuatToMat3(chan->quat, rmat); - Mat4CpyMat3(mat, tmat); + Mat3MulMat3(tmat, rmat, smat); - VECCOPY(mat[3], bone->loc); -// VecAddf(mat[3], mat[3], bone->loc); -/* if(bone->ipo) { - mat[3][0]+= bone->dloc[0]; - mat[3][1]+= bone->dloc[1]; - mat[3][2]+= bone->dloc[2]; + Mat4CpyMat3(chan->chan_mat, tmat); + + /* prevent action channels breaking chains */ + if (!(chan->bone->flag & BONE_IK_TOPARENT)) { + VECCOPY(chan->chan_mat[3], chan->loc); } -*/ + } -Bone *get_indexed_bone (bArmature *arm, int index) -/* - Walk the list until the index is reached -*/ +/* transform from bone(b) to bone(b+1), store in chan_mat */ +static void make_dmats(bPoseChannel *pchan) { - Bone *bone=NULL, *curBone; - int ref=index; - - if (!arm) - return NULL; - - for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ - bone = get_indexed_bone_bonechildren (curBone, &ref); - if (bone) - return bone; + if (pchan->parent) { + float iR_parmat[4][4]; + Mat4Invert(iR_parmat, pchan->parent->pose_mat); + Mat4MulMat4(pchan->chan_mat, pchan->pose_mat, iR_parmat); // delta mat } - - return bone; + else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat); } -Bone *get_named_bone (bArmature *arm, const char *name) -/* - Walk the list until the bone is found -*/ +/* applies IK matrix to pchan, IK is done separated */ +/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */ +/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */ +static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = to detect if this is first bone { - Bone *bone=NULL, *curBone; - - if (!arm) return NULL; + float vec[3], ikmat[4][4]; + + Mat4CpyMat3(ikmat, ik_mat); + + if (pchan->parent) + Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL); + else + Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat); - for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ - bone = get_named_bone_bonechildren (curBone, name); - if (bone) - return bone; - } + /* calculate head */ + VECCOPY(pchan->pose_head, pchan->pose_mat[3]); + /* calculate tail */ + VECCOPY(vec, pchan->pose_mat[1]); + VecMulf(vec, pchan->bone->length); + VecAddf(pchan->pose_tail, pchan->pose_head, vec); - return bone; + pchan->flag |= POSE_DONE; } -static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index) +/* The main armature solver, does all constraints excluding IK */ +/* pchan is validated, as having bone and parent pointer */ +static void where_is_pose_bone(Object *ob, bPoseChannel *pchan) { - Bone *curBone, *rbone; - - if (!*index) - return bone; - - (*index)--; - - for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ - rbone=get_indexed_bone_bonechildren (curBone, index); - if (rbone) - return rbone; + Bone *bone, *parbone; + bPoseChannel *parchan; + float vec[3], ctime= 1.0; // ctime todo + + /* set up variables for quicker access below */ + bone= pchan->bone; + parbone= bone->parent; + parchan= pchan->parent; + + /* this gives a chan_mat with actions (ipos) results */ + chan_calc_mat(pchan); + + /* construct the posemat based on PoseChannels, that we do before applying constraints */ + /* pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */ + + if(parchan) { + float offs_bone[4][4]; // yoffs(b-1) + root(b) + bonemat(b) + + /* bone transform itself */ + Mat4CpyMat3(offs_bone, bone->bone_mat); + + /* The bone's root offset (is in the parent's coordinate system) */ + VECCOPY(offs_bone[3], bone->head); + + /* Get the length translation of parent (length along y axis) */ + offs_bone[3][1]+= parbone->length; + + /* Compose the matrix for this bone */ + Mat4MulSerie(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL); } - - return NULL; + else + Mat4MulMat4(pchan->pose_mat, pchan->chan_mat, bone->arm_mat); + + + /* Do constraints */ + if(pchan->constraints.first) { + static Object conOb; + static int initialized= 0; + + /* Build a workob to pass the bone to the constraint solver */ + if(initialized==0) { + memset(&conOb, 0, sizeof(Object)); + initialized= 1; + } + conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0; + conOb.data = ob->data; + conOb.type = ob->type; + conOb.parent = ob; // ik solver retrieves the armature that way !?!?!?! + conOb.pose= ob->pose; // needed for retrieving pchan + conOb.trackflag = ob->trackflag; + conOb.upflag = ob->upflag; + + /* Collect the constraints from the pose (listbase copy) */ + conOb.constraints = pchan->constraints; + + /* conOb.obmat takes bone to worldspace */ + Mat4MulMat4 (conOb.obmat, pchan->pose_mat, ob->obmat); + + //VECCOPY(conOb.size, pchan->size); // stretchto constraint + + /* Solve */ + solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime); // ctime doesnt alter objects + + //VECCOPY(bone->size, conOb.size); // stretchto constraint + + /* Take out of worldspace */ + Mat4MulMat4 (pchan->pose_mat, conOb.obmat, ob->imat); + } + + /* calculate head */ + VECCOPY(pchan->pose_head, pchan->pose_mat[3]); + /* calculate tail */ + VECCOPY(vec, pchan->pose_mat[1]); + VecMulf(vec, bone->length); + VecAddf(pchan->pose_tail, pchan->pose_head, vec); + } -static Bone *get_named_bone_bonechildren (Bone *bone, const char *name) +/* This only reads anim data from channels, and writes to channels */ +/* This is the only function adding poses */ +void where_is_pose (Object *ob) { - Bone *curBone, *rbone; - - if (!strcmp (bone->name, name)) - return bone; + bArmature *arm; + Bone *bone; + bPoseChannel *pchan, *next; + float imat[4][4]; +// float ctime= (float)G.scene->r.cfra; /* time only applies constraint location on curve path (now) */ - for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ - rbone=get_named_bone_bonechildren (curBone, name); - if (rbone) - return rbone; + arm = get_armature(ob); + + if(arm==NULL) return; + if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) + armature_rebuild_pose(ob, arm); + +// printf("re-evaluate pose %s\n", ob->id.name); + + /* In restposition we read the data from the bones */ + if(arm->flag & ARM_RESTPOS) { + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + if(bone) { + Mat4CpyMat4(pchan->pose_mat, bone->arm_mat); + VECCOPY(pchan->pose_head, bone->arm_head); + VECCOPY(pchan->pose_tail, pchan->pose_head); + } + } } - - return NULL; -} - -void make_displists_by_armature (Object *ob) -{ - Base *base; - - if (ob){ - if (ob->type != OB_ARMATURE) return; - for (base= G.scene->base.first; base; base= base->next){ - if ((ob==base->object->parent) && (base->lay & G.scene->lay)) - if ((base->object->partype==PARSKEL) || (base->object->type==OB_MBALL)) - makeDispList(base->object); + else { + Mat4Invert(ob->imat, ob->obmat); // imat is needed + +//#if 0 + /* 1. construct the PoseChains, clear flags */ + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + pchan->flag &= ~POSE_DONE; + if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints + initialize_posechain(ob, pchan); // will attach it to root! + } + + /* 2. the main loop, channels are already hierarchical sorted from root to children */ + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if(!(pchan->flag & POSE_DONE)) { + /* 3. if we find an IK root, we handle it separated */ + if(pchan->chain.first) { + while(pchan->chain.first) { + PoseChain *chain= pchan->chain.first; + int a; + + /* 4. walk over the chain for regular solving */ + for(a=0; a<chain->totchannel; a++) { + if(!(chain->pchanchain[a]->flag & POSE_DONE)) // successive chains can set the flag + where_is_pose_bone(ob, chain->pchanchain[a]); + } + /* 5. execute the IK solver */ + execute_posechain(ob, chain); // calculates 3x3 difference matrices + /* 6. apply the differences to the channels, we calculate the original differences first */ + for(a=0; a<chain->totchannel; a++) + make_dmats(chain->pchanchain[a]); + for(a=0; a<chain->totchannel; a++) + where_is_ik_bone(chain->pchanchain[a], (void *)chain->solver->segments[a].basis_change); + // (sets POSE_DONE) + + /* 6. and free */ + BLI_remlink(&pchan->chain, chain); + free_posechain(chain); + } + } + else where_is_pose_bone(ob, pchan); + } } +//#endif } -/* -(ton) changed this; now a free displist is sufficient, drawobject.c will make disp -(ton) changed it back... doesnt work yet, do it after release -*/ - -} - -void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed) -/* Gets matrix that transforms the bone to object space */ -/* This function is also used to compute the orientation of the bone for display */ -{ - Bone *curBone; - - Bone *bonelist[256]; - int bonecount=0, i; - Mat4One (M_accumulatedMatrix); - - /* Build a list of bones from tip to root */ - for (curBone=bone; curBone; curBone=curBone->parent){ - bonelist[bonecount] = curBone; - bonecount++; +#if 0 + doconstraints= 1; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + where_is_pose_bone(ob, pchan); } + doconstraints= 0; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + where_is_pose_bone(ob, pchan); + pchan->flag &= ~POSE_IK_MAT; + } +#endif + + /* calculating deform matrices */ + for(pchan= ob->pose->chanbase.first; pchan; pchan= next) { + next= pchan->next; + + if(pchan->bone) { + Mat4Invert(imat, pchan->bone->arm_mat); + Mat4MulMat4(pchan->chan_mat, imat, pchan->pose_mat); + } + } +} - /* Count through the inverted list (i.e. iterate from root to tip)*/ - for (i=0; i<bonecount; i++){ - float T_root[4][4]; - float T_len[4][4]; - float R_bmat[4][4]; - float M_obmat[4][4]; - float M_boneMatrix[4][4]; - float delta[3]; - - curBone = bonelist[bonecount-i-1]; - - /* Get the length translation (length along y axis) */ - Mat4One (T_len); - T_len[3][1] = get_bone_length(curBone); - - if ((curBone == bone) && (root)) - Mat4One (T_len); - - /* Get the bone's root offset (in the parent's coordinate system) */ - Mat4One (T_root); - VECCOPY (T_root[3], curBone->head); - - /* Compose the restmat */ - VecSubf(delta, curBone->tail, curBone->head); - make_boneMatrixvr(R_bmat, delta, curBone->roll); +/* *************** helper for selection code ****************** */ - /* Retrieve the obmat (user transformation) */ - if (posed) - Mat4CpyMat4 (M_obmat, curBone->obmat); - else - Mat4One (M_obmat); - /* Compose the matrix for this bone */ -#if 0 - Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, M_obmat, R_bmat, T_len, NULL, NULL, NULL); -#else - Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, R_bmat, M_obmat, T_len, NULL, NULL, NULL); -#endif - Mat4CpyMat4 (M_accumulatedMatrix, M_boneMatrix); +Bone *get_indexed_bone (Object *ob, int index) +/* + Now using pose channel +*/ +{ + bPoseChannel *pchan; + int a= 0; + + if(ob->pose==NULL) return NULL; + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, a++) { + if(a==index) return pchan->bone; } + return NULL; +} -} +/* *********************** Inverse Kinematics ************* */ +#if 0 void solve_posechain (PoseChain *chain) { float goal[3]; int i; Bone *curBone; - float M_obmat[4][4]; - float M_basischange[4][4]; +// float M_obmat[4][4]; +// float M_basischange[4][4]; bPoseChannel *chan; if (!chain->solver) return; @@ -1290,7 +1086,6 @@ void solve_posechain (PoseChain *chain) VECCOPY (goal, chain->goal); Mat4MulVecfl (chain->goalinv, goal); - /* Solve the chain */ IK_SolveChain(chain->solver, @@ -1302,30 +1097,41 @@ void solve_posechain (PoseChain *chain) /* Copy the results back into the bones */ for (i = chain->solver->num_segments-1, curBone=chain->target->parent; i>=0; i--, curBone=curBone->parent){ - +// for (i = 0; i<chain->solver->num_segments; i++) { + //curBone= bonelist[i]; + /* Retrieve the delta rotation from the solver */ - Mat4One(M_basischange); - Mat4CpyMat3(M_basischange, (void *)chain->solver->segments[i].basis_change); //basis_change = array[9] - - +// Mat4One(M_basischange); +// Mat4CpyMat3(M_basischange, (void *)chain->solver->segments[i].basis_change); //basis_change = array[9] +// printmatrix3(curBone->name, (void *)chain->solver->segments[i].basis_change); /** * Multiply the bone's usertransform by the * basis change to get the new usertransform */ - Mat4CpyMat4 (M_obmat, curBone->obmat); - Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat); - + //Mat4CpyMat4 (M_obmat, curBone->obmat); + //Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat); + /* store in channel itself */ + + chan= get_pose_channel(chain->pose, curBone->name); + Mat3CpyMat3 (chan->ik_mat, (void *)chain->solver->segments[i].basis_change); + chan->flag |= POSE_IK_MAT; + /* Store the solve results on the childrens' channels */ - for (chan = chain->pose->chanbase.first; chan; chan=chan->next){ - if (!strcmp (chan->name, curBone->name)){ - Mat4CpyMat4 (chan->obmat, curBone->obmat); - break; - } - } - + //for (chan = chain->pose->chanbase.first; chan; chan=chan->next){ + // if (!strcmp (chan->name, curBone->name)){ + // Mat4CpyMat4 (chan->obmat, curBone->obmat); + // break; + // } + //} } + /* WARNING! REMOVE LATER !!! */ + /* flag chain target to recalculate too */ + chan= get_pose_channel(chain->pose, chain->target->name); + Mat3One(chan->ik_mat); + chan->flag |= POSE_IK_MAT; } +#endif void free_posechain (PoseChain *chain) { @@ -1334,9 +1140,13 @@ void free_posechain (PoseChain *chain) chain->solver->segments = NULL; IK_FreeChain(chain->solver); } - MEM_freeN (chain); + if(chain->pchanchain) MEM_freeN(chain->pchanchain); + MEM_freeN(chain); } +#if 0 +/* actually; bones to IK_solver data */ +/* Object is its own Armature object */ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone) { IK_Segment_Extern *segs; @@ -1344,15 +1154,16 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone) Bone *curBone, *rootBone; int segcount, curseg, icurseg; float imat[4][4]; + bPoseChannel *pchan; Bone *bonelist[256]; float rootmat[4][4]; - float bonespace[4][4]; +// float bonespace[4][4]; /** * Some interesting variables in this function: * * Bone->obmat Bone's user transformation; - * It is initialized in where_is_bone1_time + * It is initialized in where_is_b one1_time * * rootmat Bone's coordinate system, computed by * get_objectspace_bone_matrix. Takes all @@ -1395,27 +1206,29 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone) /* Allocate some IK segments */ segs = MEM_callocN (sizeof(IK_Segment_Extern)*segcount, "iksegments"); - + //printf("segcount %d\n", segcount); /** * Remove the offset from the first bone in the chain and take the target to chainspace */ - - get_objectspace_bone_matrix(rootBone, bonespace, 1, 1); - Mat4One (rootmat); - VECCOPY (rootmat[3], bonespace[3]); + //get_objectspace_bone_matrix(rootBone, bonespace, 1, 1); + //Mat4One (rootmat); + //VECCOPY (rootmat[3], bonespace[3]); + pchan= get_pose_channel(ob->pose, rootBone->name); + Mat4One(rootmat); + VECCOPY(rootmat[3], pchan->pose_head); /* Take the target to bonespace */ + /* (ton) I think it's the matrix to take a world coordinate into "chainspace" */ Mat4MulMat4 (imat, rootmat, ob->obmat); Mat4Invert (chain->goalinv, imat); - /** * Build matrices from the root to the tip * We count backwards through the bone list (which is sorted tip to root) * and forwards through the ik_segment list */ - + /* that we're going to recode! (ton) */ for (curseg = segcount-1; curseg>=0; curseg--){ float M_basismat[4][4]; float R_parmat[4][4]; @@ -1428,11 +1241,16 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone) /* Get the basis matrix */ Mat4One (R_parmat); - get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1); + //get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1); + //R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F; + pchan= get_pose_channel(ob->pose, curBone->name); + Mat4CpyMat4(R_bonemat, pchan->pose_mat); R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F; - if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)){ - get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1); + if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)) { + //get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1); + Mat4CpyMat4(R_parmat, pchan->parent->pose_mat); + R_parmat[3][0]=R_parmat[3][1]=R_parmat[3][2]=0.0F; } @@ -1444,25 +1262,13 @@ PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone) Mat3Transp((void *)segs[icurseg].basis); /* Fill out the IK segment */ - segs[icurseg].length = get_bone_length(curBone); + segs[icurseg].length = VecLenf(curBone->head, curBone->tail); - }; + } IK_LoadChain(chain->solver, segs, segcount); + return chain; } - - -void precalc_bonelist_irestmats (ListBase* bonelist) -{ - Bone *curbone; - - if (!bonelist) - return; - - for (curbone = bonelist->first; curbone; curbone=curbone->next){ - precalc_bone_irestmat(curbone); - precalc_bonelist_irestmats(&curbone->childbase); - } -} +#endif diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2b7a5b446e5..b0f84d8d844 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -392,15 +392,6 @@ static void setup_app_data(BlendFileData *bfd, char *filename) } } - /* few DispLists, but do text_to_curve */ - // this should be removed!!! But first a better displist system (ton) - for (ob= G.main->object.first; ob; ob= ob->id.next) { - if(ob->type==OB_FONT) { - Curve *cu= ob->data; - if(cu->nurb.first==0) text_to_curve(ob, 0); - } - } - if (!G.background) { setscreen(G.curscreen); } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index dff98c87a6f..f373c7f9062 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -73,9 +73,178 @@ void Mat4BlendMat4(float [][4], float [][4], float [][4], float ); /* Local function prototypes */ -/* Functions */ +/* ********************* Data level ****************** */ -char constraint_has_target (bConstraint *con) { +void free_constraint_data (bConstraint *con) +{ + if (con->data){ + switch (con->type){ + default: + break; + }; + + MEM_freeN (con->data); + } +} + +void free_constraints (ListBase *conlist) +{ + bConstraint *con; + + /* Do any specific freeing */ + for (con=conlist->first; con; con=con->next) + { + free_constraint_data (con); + }; + + /* Free the whole list */ + BLI_freelistN(conlist); +} + +void free_constraint_channels (ListBase *chanbase) +{ + bConstraintChannel *chan; + + for (chan=chanbase->first; chan; chan=chan->next) + { + if (chan->ipo){ + chan->ipo->id.us--; + } + } + + BLI_freelistN(chanbase); +} + +void relink_constraints (struct ListBase *list) +{ + bConstraint *con; + + for (con = list->first; con; con=con->next){ + switch (con->type){ + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_NULL: + { + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_LOCKTRACK: + { + bLockTrackConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_ACTION: + { + bActionConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_FOLLOWPATH: + { + bFollowPathConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_STRETCHTO: + { + bStretchToConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + + } + } +} + +void *copy_constraint_channels (ListBase *dst, ListBase *src) +{ + bConstraintChannel *dchan, *schan; + bConstraintChannel *newact=NULL; + + dst->first=dst->last=NULL; + duplicatelist(dst, src); + + for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){ + dchan->ipo = copy_ipo(schan->ipo); + } + + return newact; +} + +bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact) +{ + bConstraintChannel *dchan, *schan; + bConstraintChannel *newact=NULL; + + dst->first=dst->last=NULL; + duplicatelist(dst, src); + + for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){ + id_us_plus((ID *)dchan->ipo); + if (schan==oldact) + newact=dchan; + } + + return newact; +} + +void copy_constraints (ListBase *dst, ListBase *src) +{ + bConstraint *con; + + dst->first= dst->last= NULL; + + duplicatelist (dst, src); + + for (con = dst->first; con; con=con->next) { + con->data = MEM_dupallocN (con->data); + /* removed a whole lot of useless code here (ton) */ + } +} + + +/* **************** Editor Functions **************** */ + +char constraint_has_target (bConstraint *con) +{ switch (con->type){ case CONSTRAINT_TYPE_TRACKTO: { @@ -137,7 +306,7 @@ char constraint_has_target (bConstraint *con) { return 0; } -Object *get_constraint_target(bConstraint *con) +Object *get_constraint_target(bConstraint *con, char **subtarget) { /* * If the target for this constraint is target, return a pointer @@ -147,48 +316,56 @@ Object *get_constraint_target(bConstraint *con) case CONSTRAINT_TYPE_ACTION: { bActionConstraint *data = con->data; + *subtarget= data->subtarget; return data->tar; } break; case CONSTRAINT_TYPE_LOCLIKE: { bLocateLikeConstraint *data = con->data; + *subtarget= data->subtarget; return data->tar; } break; case CONSTRAINT_TYPE_ROTLIKE: { bRotateLikeConstraint *data = con->data; + *subtarget= data->subtarget; return data->tar; } break; case CONSTRAINT_TYPE_KINEMATIC: { bKinematicConstraint *data = con->data; + *subtarget= data->subtarget; return data->tar; } break; case CONSTRAINT_TYPE_TRACKTO: { bTrackToConstraint *data = con->data; + *subtarget= data->subtarget; return data->tar; } break; case CONSTRAINT_TYPE_LOCKTRACK: { bLockTrackConstraint *data = con->data; + *subtarget= data->subtarget; return data->tar; } break; case CONSTRAINT_TYPE_FOLLOWPATH: { bFollowPathConstraint *data = con->data; + *subtarget= NULL; return data->tar; } break; case CONSTRAINT_TYPE_STRETCHTO: { bStretchToConstraint *data = con->data; + *subtarget= data->subtarget; return (data->tar); } break; @@ -197,7 +374,65 @@ Object *get_constraint_target(bConstraint *con) return NULL; } -void unique_constraint_name (bConstraint *con, ListBase *list){ +void set_constraint_target(bConstraint *con, Object *ob) +{ + /* + * Set the target for this constraint + */ + switch (con->type) { + case CONSTRAINT_TYPE_ACTION: + { + bActionConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_LOCKTRACK: + { + bLockTrackConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_FOLLOWPATH: + { + bFollowPathConstraint *data = con->data; + data->tar= ob; + } + break; + case CONSTRAINT_TYPE_STRETCHTO: + { + bStretchToConstraint *data = con->data; + data->tar= ob; + } + break; + } +} + +void unique_constraint_name (bConstraint *con, ListBase *list) +{ char tempname[64]; int number; char *dot; @@ -241,9 +476,9 @@ void unique_constraint_name (bConstraint *con, ListBase *list){ } } -void *new_constraint_data (short type) +void *new_constraint_data (short type) { - void *result; + void *result; switch (type){ case CONSTRAINT_TYPE_KINEMATIC: @@ -252,7 +487,7 @@ void *new_constraint_data (short type) data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint"); data->tolerance = (float)0.001; - data->iterations = 500; + data->iterations = 50; result = data; } @@ -344,23 +579,27 @@ void *new_constraint_data (short type) return result; } -bConstraintChannel *find_constraint_channel (ListBase *list, const char *name){ +bConstraintChannel *find_constraint_channel (ListBase *list, const char *name) +{ bConstraintChannel *chan; - for (chan = list->first; chan; chan=chan->next){ - if (!strcmp(name, chan->name)){ + for (chan = list->first; chan; chan=chan->next) { + if (!strcmp(name, chan->name)) { return chan; } } return NULL; } +/* ***************** Evaluating ********************* */ + +/* does ipos only */ void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime) { bConstraint *con; bConstraintChannel *chan; - IpoCurve *icu; - + IpoCurve *icu=NULL; + for (con=conbase->first; con; con=con->next){ chan = find_constraint_channel(chanbase, con->name); if (chan && chan->ipo){ @@ -421,94 +660,33 @@ void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweig static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime) { - /* Update the location of the target object */ - //where_is_object_time (ob, ctime); - /* Case OBJECT */ - if (!strlen(substring)){ + if (!strlen(substring)) { Mat4CpyMat4 (mat, ob->obmat); - VECCOPY (size, ob->size); - return; + VECCOPY (size, ob->size); // whats this for, hack! (ton) } - /* Case BONE */ else { - bArmature *arm; - Bone *bone; - float bmat[4][4]; + bPoseChannel *pchan; float bsize[3]={1, 1, 1}; - arm = get_armature(ob); - - /** - * Locate the bone (if there is one) - * Ensures that the bone's transformation is fully constrained - * (Cyclical relationships are disallowed elsewhere) - */ - bone = get_named_bone(arm, substring); - if (bone){ - where_is_bone_time(ob, bone, ctime); - get_objectspace_bone_matrix(bone, bmat, 1, 1); - VECCOPY(bsize, bone->size); + pchan = get_pose_channel(ob->pose, substring); + if (pchan){ + /** + * Multiply the objectspace bonematrix by the skeletons's global + * transform to obtain the worldspace transformation of the target + */ + Mat4MulMat4 (mat, pchan->pose_mat, ob->obmat); } else - Mat4One (bmat); - - /** - * Multiply the objectspace bonematrix by the skeletons's global - * transform to obtain the worldspace transformation of the target - */ - VECCOPY(size, bsize); - Mat4MulMat4 (mat, bmat, ob->obmat); - - return; - } -} - -void clear_object_constraint_status (Object *ob) -{ - bConstraint *con; + Mat4CpyMat4 (mat, ob->obmat); - if (!ob) return; - - /* Clear the object's constraints */ - for (con = ob->constraints.first; con; con=con->next){ - con->flag &= ~CONSTRAINT_DONE; - } - - /* Clear the object's subdata constraints */ - switch (ob->type){ - case OB_ARMATURE: - { - clear_pose_constraint_status (ob); - } - break; - default: - break; - } -} - -void clear_all_constraints(void) -{ - Base *base; - - /* Clear the constraint "done" flags -- this must be done - * before displists are calculated for objects that are - * deformed by armatures */ - for (base = G.scene->base.first; base; base=base->next){ - clear_object_constraint_status(base->object); - } -} - -void rebuild_all_armature_displists(void) { - Base *base; - - for (base = G.scene->base.first; base; base=base->next){ - clear_object_constraint_status(base->object); - make_displists_by_armature(base->object); + VECCOPY(size, bsize); // whats this for, hack! (ton) } } +/* called during solve_constraints */ +/* also for make_parent, to find correct inverse of "follow path" */ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime) { short valid=0; @@ -531,13 +709,11 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own float s,t; Bone *curBone; Bone tbone; - int i; +// int i; curBone = (Bone*)ownerdata; if (data->tar){ - /* Update the location of the target object */ - where_is_object_time (data->tar, ctime); constraint_target_to_mat4(data->tar, data->subtarget, tempmat, size, ctime); valid=1; } @@ -582,26 +758,26 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own pose = MEM_callocN(sizeof(bPose), "pose"); verify_pose_channel(pose, curBone->name); - get_pose_from_action (&pose, data->act, t); + extract_pose_from_action (pose, data->act, t); /* Find the appropriate channel */ pchan = get_pose_channel(pose, curBone->name); if (pchan){ memset(&tbone, 0x00, sizeof(Bone)); - VECCOPY (tbone.loc, pchan->loc); - VECCOPY (tbone.size, pchan->size); - for (i=0; i<4; i++) - tbone.quat[i]=pchan->quat[i]; - - bone_to_mat4(&tbone, mat); +// VECCOPY (tbone.loc, pchan->loc); +// VECCOPY (tbone.size, pchan->size); +// for (i=0; i<4; i++) +// tbone.quat[i]=pchan->quat[i]; +// +// bone_to_mat4(&tbone, mat); } else{ Mat4One(mat); } /* Clean up */ - clear_pose(pose); + free_pose_channels(pose); MEM_freeN(pose); } @@ -612,8 +788,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data; if (data->tar){ - /* Update the location of the target object */ - where_is_object_time (data->tar, ctime); constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); valid=1; } @@ -627,8 +801,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own data = (bRotateLikeConstraint*)con->data; if (data->tar){ - /* Update the location of the target object */ - where_is_object_time (data->tar, ctime); constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); valid=1; } @@ -642,9 +814,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own data = (bTrackToConstraint*)con->data; if (data->tar){ - // Refresh the object if it isn't a constraint loop - if (!(con->flag & CONSTRAINT_NOREFRESH)) - where_is_object_time (data->tar, ctime); constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); valid=1; } @@ -654,12 +823,10 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own break; case CONSTRAINT_TYPE_KINEMATIC: { - bTrackToConstraint *data; - data = (bTrackToConstraint*)con->data; + bKinematicConstraint *data; + data = (bKinematicConstraint*)con->data; if (data->tar){ - /* Update the location of the target object */ - where_is_object_time (data->tar, ctime); constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); valid=1; } @@ -673,10 +840,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own data = (bLockTrackConstraint*)con->data; if (data->tar){ - // Refresh the object if it isn't a constraint loop - if (!(con->flag & CONSTRAINT_NOREFRESH)) - where_is_object_time (data->tar, ctime); - constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); valid=1; } @@ -690,33 +853,17 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own data = (bFollowPathConstraint*)con->data; if (data->tar){ - short OldFlag; Curve *cu; float q[4], vec[4], dir[3], *quat, x1, totmat[4][4]; float curvetime; - where_is_object_time (data->tar, ctime); - Mat4One (totmat); Mat4One (mat); cu= data->tar->data; - OldFlag = cu->flag; - - if(data->followflag) { - if(!(cu->flag & CU_FOLLOW)) cu->flag += CU_FOLLOW; - } - else { - if(cu->flag & CU_FOLLOW) cu->flag -= CU_FOLLOW; - } - - if(!(cu->flag & CU_PATH)) cu->flag += CU_PATH; - - if(cu->path==NULL) - calc_curvepath(data->tar); - else if (cu->path->data==NULL) - calc_curvepath(data->tar); + /* note; when creating constraints that follow path, the curve gets the CU_PATH set now, + currently for paths to work it needs to go through the bevlist/displist system (ton) */ if(cu->path && cu->path->data) { curvetime= bsystem_time(data->tar, data->tar->parent, (float)ctime, 0.0) - data->offset; @@ -746,7 +893,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL); } } - cu->flag = OldFlag; valid=1; } else @@ -759,7 +905,6 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own data = (bStretchToConstraint*)con->data; if (data->tar){ - where_is_object_time (data->tar, ctime); constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); valid = 1; } @@ -776,209 +921,10 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own return valid; } -void relink_constraints (struct ListBase *list) -{ - bConstraint *con; - - for (con = list->first; con; con=con->next){ - switch (con->type){ - case CONSTRAINT_TYPE_KINEMATIC: - { - bKinematicConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_NULL: - { - } - break; - case CONSTRAINT_TYPE_TRACKTO: - { - bTrackToConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_LOCKTRACK: - { - bLockTrackConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_ACTION: - { - bActionConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_LOCLIKE: - { - bLocateLikeConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_ROTLIKE: - { - bRotateLikeConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_FOLLOWPATH: - { - bFollowPathConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - case CONSTRAINT_TYPE_STRETCHTO: - { - bStretchToConstraint *data; - data = con->data; - - ID_NEW(data->tar); - } - break; - - } - } -} - -void *copy_constraint_channels (ListBase *dst, ListBase *src) -{ - bConstraintChannel *dchan, *schan; - bConstraintChannel *newact=NULL; - - dst->first=dst->last=NULL; - duplicatelist(dst, src); - - for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){ - dchan->ipo = copy_ipo(schan->ipo); - } - - return newact; -} - -bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact) -{ - bConstraintChannel *dchan, *schan; - bConstraintChannel *newact=NULL; - - dst->first=dst->last=NULL; - duplicatelist(dst, src); - - for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){ - id_us_plus((ID *)dchan->ipo); - if (schan==oldact) - newact=dchan; - } - - return newact; -} - -void copy_constraints (ListBase *dst, ListBase *src) -{ - bConstraint *con; - - dst->first=dst->last=NULL; - - duplicatelist (dst, src); - - /* Update specific data */ - if (!dst->first) - return; - - for (con = dst->first; con; con=con->next){ - switch (con->type){ - case CONSTRAINT_TYPE_ACTION: - { - bActionConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bActionConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_LOCLIKE: - { - bLocateLikeConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bLocateLikeConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_ROTLIKE: - { - bRotateLikeConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bRotateLikeConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_NULL: - { - con->data = NULL; - } - break; - case CONSTRAINT_TYPE_TRACKTO: - { - bTrackToConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bTrackToConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_LOCKTRACK: - { - bLockTrackConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bLockTrackConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_KINEMATIC: - { - bKinematicConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bKinematicConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_FOLLOWPATH: - { - bFollowPathConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bFollowPathConstraint*) con->data; - } - break; - case CONSTRAINT_TYPE_STRETCHTO: - { - bStretchToConstraint *data; - - con->data = MEM_dupallocN (con->data); - data = (bStretchToConstraint*) con->data; - } - break; - default: - con->data = MEM_dupallocN (con->data); - break; - } - } -} +/* only called during solve_constraints */ +/* bone constraints create a fake object to work on, then ob is a workob */ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4]) -/* ob is likely to be a workob */ { float M_oldmat[4][4]; float M_identity[4][4]; @@ -988,11 +934,6 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, Mat4One (M_identity); - /* We've already been calculated */ - if (constraint->flag & CONSTRAINT_DONE){ - return; - } - switch (constraint->type){ case CONSTRAINT_TYPE_ACTION: { @@ -1088,6 +1029,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, break; case CONSTRAINT_TYPE_KINEMATIC: { +#if 0 bKinematicConstraint *data; float imat[4][4]; float temp[4][4]; @@ -1111,15 +1053,19 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, chain->tolerance = data->tolerance; - { + if(0) { + bPoseChannel *pchan= get_pose_channel(armob->pose, curBone->name); float parmat[4][4]; /* Take the obmat to objectspace */ - Mat4CpyMat4 (temp, curBone->obmat); - Mat4One (curBone->obmat); - get_objectspace_bone_matrix(curBone, parmat, 1, 1); - Mat4CpyMat4 (curBone->obmat, temp); - Mat4MulMat4 (totmat, parmat, ob->parent->obmat); + +// Mat4CpyMat4 (temp, curBone->obmat); +// Mat4One (curBone->obmat); +// get_objectspace_bone_matrix(curBone, parmat, 1, 1); + Mat4CpyMat4(parmat, pchan->pose_mat); + +// Mat4CpyMat4 (curBone->obmat, temp); + Mat4MulMat4 (totmat, parmat, armob->obmat); Mat4Invert (imat, totmat); @@ -1131,26 +1077,31 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, /* Solve it */ if (chain->solver){ VECCOPY (chain->goal, targetmat[3]); - solve_posechain(chain); + solve_posechain(chain); // applies to bones/channels } free_posechain(chain); - { + if(0) { float parmat[4][4]; + bPoseChannel *pchan= get_pose_channel(armob->pose, curBone->name); /* Take the obmat to worldspace */ - Mat4CpyMat4 (temp, curBone->obmat); - Mat4One (curBone->obmat); - get_objectspace_bone_matrix(curBone, parmat, 1, 1); - Mat4CpyMat4 (curBone->obmat, temp); - Mat4MulMat4 (totmat, parmat, ob->parent->obmat); +// Mat4CpyMat4 (temp, curBone->obmat); +// Mat4One (curBone->obmat); + +// get_objectspace_bone_matrix(curBone, parmat, 1, 1); + Mat4CpyMat4(parmat, pchan->pose_mat); + +// Mat4CpyMat4 (curBone->obmat, temp); + Mat4MulMat4 (totmat, parmat, armob->obmat); Mat4CpyMat4 (temp, ob->obmat); Mat4MulMat4 (ob->obmat, temp, totmat); } } +#endif } break; case CONSTRAINT_TYPE_LOCKTRACK: @@ -1481,7 +1432,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, data=(bFollowPathConstraint*)constraint->data; if (data->tar) { - + // weird, this is needed? doesnt work for workob (ton) object_to_mat4(ob, obmat); Mat4MulSerie(ob->obmat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL); @@ -1617,45 +1568,4 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, printf ("Error: Unknown constraint type\n"); break; } - -} - -void free_constraint_data (bConstraint *con) -{ - if (con->data){ - switch (con->type){ - default: - break; - }; - - MEM_freeN (con->data); - } -} - -void free_constraints (ListBase *conlist) -{ - bConstraint *con; - - /* Do any specific freeing */ - for (con=conlist->first; con; con=con->next) - { - free_constraint_data (con); - }; - - /* Free the whole list */ - BLI_freelistN(conlist); -} - -void free_constraint_channels (ListBase *chanbase) -{ - bConstraintChannel *chan; - - for (chan=chanbase->first; chan; chan=chan->next) - { - if (chan->ipo){ - chan->ipo->id.us--; - } - } - - BLI_freelistN(chanbase); } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 226a1d602b7..7fe0ec626a4 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -54,6 +54,7 @@ #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_object.h" #include "BKE_softbody.h" @@ -237,6 +238,8 @@ int mesh_modifier(Object *ob, char mode) MVert *mv; int a, done=0; + do_mesh_key(me); + /* conditions if it's needed */ if(ob->hooks.first); else if(ob->effect.first); // weak... particles too @@ -322,6 +325,8 @@ int curve_modifier(Object *ob, char mode) BPoint *bp; int a, index, done= 0; + do_curve_key(cu); + /* conditions if it's needed */ if(ob->hooks.first); else if(ob->parent && ob->partype==PARSKEL); @@ -390,6 +395,8 @@ int lattice_modifier(Object *ob, char mode) BPoint *bp; int a, index, done= 0; + do_latt_key(lt); + /* conditions if it's needed */ if(ob->hooks.first); else if(ob->parent && ob->partype==PARSKEL); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 668b18c0913..9f0501d54fc 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -41,17 +41,25 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_curve_types.h" #include "DNA_ID.h" +#include "DNA_effect_types.h" +#include "DNA_lattice_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" #include "DNA_oops_types.h" #include "DNA_scene_types.h" -#include "DNA_action_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view2d_types.h" -#include "BKE_utildefines.h" +#include "BKE_action.h" #include "BKE_global.h" +#include "BKE_mball.h" +#include "BKE_utildefines.h" #include "MEM_guardedalloc.h" #include "blendef.h" @@ -272,18 +280,16 @@ int queue_count(struct DagNodeQueue *queue){ DagForest * dag_init() { DagForest *forest; - - forest = MEM_mallocN(sizeof(DagForest),"DAG root"); - forest->DagNode.first = NULL; - forest->DagNode.last = NULL; - forest->numNodes = 0; + /* use callocN to init all zero */ + forest = MEM_callocN(sizeof(DagForest),"DAG root"); return forest; } -struct DagForest *build_dag(struct Scene *sce, short mask) +struct DagForest *build_dag(struct Scene *sce, short mask) { Base *base; Object *ob; + bConstraint *con; DagNode * node; DagNode * node2; DagNode * node3; @@ -299,130 +305,126 @@ struct DagForest *build_dag(struct Scene *sce, short mask) sce->theDag = dag; } - // add base node for scene. scene is always the first node in DAG + /* add base node for scene. scene is always the first node in DAG */ scenenode = dag_add_node(dag, sce); - /* targets in object struct yet to be added. should even they ? - struct Ipo *ipo; - ListBase nlastrips; - ListBase hooks; - */ - - - base = sce->base.first; - while(base) { // add all objects in any case + for(base = sce->base.first; base; base= base->next) { int addtoroot = 1; ob= (Object *) base->object; node = dag_get_node(dag,ob); - if ((ob->data) && (mask&DAG_RL_DATA_MASK)) { + if ((ob->data) && (mask&DAG_RL_DATA)) { node2 = dag_get_node(dag,ob->data); dag_add_relation(dag,node,node2,DAG_RL_DATA); node2->first_ancestor = ob; node2->ancestor_count += 1; - if ((ob->type == OB_ARMATURE) && (mask&DAG_RL_DATA_CONSTRAINT_MASK)) { // add armature constraints to datas - if (ob->pose){ - bPoseChannel *pchan; - bConstraint *con; - Object * target; - - for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){ - for (con = pchan->constraints.first; con; con=con->next){ - if (constraint_has_target(con)) { - target = get_constraint_target(con); - if (strcmp(target->id.name, ob->id.name) != 0) { - //fprintf(stderr,"armature target :%s \n", target->id.name); - node3 = dag_get_node(dag,target); - dag_add_relation(dag,node3,node2,DAG_RL_CONSTRAINT); - } - } - } - } - } - } - if ((ob->hooks.first) && (mask&DAG_RL_HOOK)) { - ObHook *hook; + } + if (ob->type == OB_ARMATURE) { + if (ob->pose){ + bPoseChannel *pchan; + bConstraint *con; + Object * target; + char *subtarget; - for(hook= ob->hooks.first; hook; hook= hook->next) { - if(hook->parent) { - node3 = dag_get_node(dag,hook->parent); - dag_add_relation(dag,node3,node2,DAG_RL_HOOK); - } - } - } - } else { // add armature constraints to object itself - if ((ob->type == OB_ARMATURE) && (mask&DAG_RL_DATA_CONSTRAINT_MASK)) { - if (ob->pose){ - bPoseChannel *pchan; - bConstraint *con; - Object * target; - - for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){ - for (con = pchan->constraints.first; con; con=con->next){ - if (constraint_has_target(con)) { - target = get_constraint_target(con); - if (strcmp(target->id.name, ob->id.name) != 0) { - //fprintf(stderr,"armature target :%s \n", target->id.name); - node3 = dag_get_node(dag,target); - dag_add_relation(dag,node3,node,DAG_RL_CONSTRAINT); - } + for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){ + for (con = pchan->constraints.first; con; con=con->next){ + if (constraint_has_target(con)) { + target = get_constraint_target(con, &subtarget); + if (target!=ob) { + // fprintf(stderr,"armature %s target :%s \n", ob->id.name, target->id.name); + node3 = dag_get_node(dag, target); + + dag_add_relation(dag,node3,node,DAG_RL_OB_DATA); + } } } } } - if ((ob->hooks.first) && (mask&DAG_RL_HOOK)) { - ObHook *hook; - - for(hook= ob->hooks.first; hook; hook= hook->next) { - if(hook->parent) { - node3 = dag_get_node(dag,hook->parent); - dag_add_relation(dag,node3,node,DAG_RL_HOOK); - } + } + if (ob->hooks.first) { + ObHook *hook; + + for(hook= ob->hooks.first; hook; hook= hook->next) { + if(hook->parent) { + node3 = dag_get_node(dag,hook->parent); + dag_add_relation(dag,node3,node,DAG_RL_OB_DATA); } - } + } } - - if ((ob->parent) && (mask&DAG_RL_PARENT_MASK)){ + if (ob->parent) { node2 = dag_get_node(dag,ob->parent); - dag_add_relation(dag,node2,node,DAG_RL_PARENT); + + switch(ob->partype) { + case PARSKEL: + dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB); + break; + case PARVERT1: case PARVERT3: case PARBONE: + dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB); + break; + default: + if(ob->parent->type==OB_LATTICE) + dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB); + else if(ob->parent->type==OB_CURVE) { + Curve *cu= ob->parent->data; + if(cu->flag & CU_PATH) + dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB); + else + dag_add_relation(dag,node2,node,DAG_RL_OB_OB); + } + else + dag_add_relation(dag,node2,node,DAG_RL_OB_OB); + } addtoroot = 0; } - if ((ob->track) && (mask&DAG_RL_TRACK_MASK)){ + if (ob->track) { node2 = dag_get_node(dag,ob->track); - dag_add_relation(dag,node2,node,DAG_RL_TRACK); + dag_add_relation(dag,node2,node,DAG_RL_OB_OB); addtoroot = 0; - } - if ((ob->path) && (mask&DAG_RL_PATH_MASK)){ - node2 = dag_get_node(dag,ob->track); - dag_add_relation(dag,node2,node,DAG_RL_PATH); - addtoroot = 0; - + if (ob->type==OB_MBALL) { + Object *mom= find_basis_mball(ob); + if(mom!=ob) { + node2 = dag_get_node(dag, mom); + dag_add_relation(dag,node,node2,DAG_RL_DATA_DATA|DAG_RL_OB_DATA); // mom depends on children! + } } - - /* Count constraints */ - if (mask & DAG_RL_CONSTRAINT_MASK) { - bConstraint *con; - for (con = ob->constraints.first; con; con=con->next){ - if (constraint_has_target(con)) { - node2 = dag_get_node(dag,get_constraint_target(con)); - dag_add_relation(dag,node2,node,DAG_RL_CONSTRAINT); - addtoroot = 0; - - } + else if (ob->type==OB_CURVE) { + Curve *cu= ob->data; + if(cu->bevobj) { + node2 = dag_get_node(dag, cu->bevobj); + dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA); } - } + if(cu->taperobj) { + node2 = dag_get_node(dag, cu->taperobj); + dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA); + } + } + else if(ob->type==OB_FONT) { + Curve *cu= ob->data; + if(cu->textoncurve) { + node2 = dag_get_node(dag, cu->textoncurve); + dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA); + } + } + for (con = ob->constraints.first; con; con=con->next){ + if (constraint_has_target(con)) { + char *str; + node2 = dag_get_node(dag, get_constraint_target(con, &str)); + if(con->type==CONSTRAINT_TYPE_FOLLOWPATH) + dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB); + else + dag_add_relation(dag, node2, node, DAG_RL_OB_OB); + addtoroot = 0; + } + } if (addtoroot == 1 ) dag_add_relation(dag,scenenode,node,DAG_RL_SCENE); - - addtoroot = 1; - base= base->next; } // cycle detection and solving @@ -458,18 +460,20 @@ void free_forest(DagForest *Dag) DagNode * dag_find_node (DagForest *forest,void * fob) { - DagNode *node = forest->DagNode.first; - - while (node) { - if (node->ob == fob) - return node; - node = node->next; - } - return NULL; + DagNode *node = forest->DagNode.first; + + while (node) { + if (node->ob == fob) + return node; + node = node->next; + } + return NULL; } +static int ugly_hack_sorry= 1; // prevent type check + /* no checking of existance, use dag_find_node first or dag_get_node */ -DagNode * dag_add_node (DagForest *forest,void * fob) +DagNode * dag_add_node (DagForest *forest, void * fob) { DagNode *node; @@ -486,7 +490,7 @@ DagNode * dag_add_node (DagForest *forest,void * fob) node->first_ancestor = NULL; node->ancestor_count = 0; - node->type = GS(((ID *) fob)->name); + if(ugly_hack_sorry) node->type = GS(((ID *) fob)->name); // sorry, done for pose sorting if (forest->numNodes) { ((DagNode *) forest->DagNode.last)->next = node; forest->DagNode.last = node; @@ -540,7 +544,7 @@ DagNode * dag_get_sub_node (DagForest *forest,void * fob) return node; } -void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, dag_rel_type rel) +void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel) { DagAdjList *itA = fob1->child; @@ -846,6 +850,7 @@ DagNodeQueue * graph_dfs(void) return(retqueue); } +/* unused */ int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data) { DagNode *node; @@ -933,84 +938,6 @@ int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_a return(retval); } -// sort the base list on place -void topo_sort_baselist(struct Scene *sce){ - DagNode *node; - DagNodeQueue *nqueue; - DagAdjList *itA; - int time; - int skip = 0; - ListBase tempbase; - Base *base; - - tempbase.first= tempbase.last= 0; - - build_dag(sce,DAG_RL_ALL_BUT_DATA_MASK); - - nqueue = queue_create(DAGQUEUEALLOC); - - node = sce->theDag->DagNode.first; - while(node) { - node->color = DAG_WHITE; - node = node->next; - } - - time = 1; - - node = sce->theDag->DagNode.first; - - node->color = DAG_GRAY; - time++; - push_stack(nqueue,node); - - while(nqueue->count) { - - skip = 0; - node = get_top_node_queue(nqueue); - - itA = node->child; - while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { - itA->node->DFS_dvtm = time; - itA->node->color = DAG_GRAY; - - time++; - push_stack(nqueue,itA->node); - skip = 1; - break; - } - itA = itA->next; - } - - if (!skip) { - if (node) { - node = pop_queue(nqueue); - if (node->ob == sce) // we are done - break ; - node->color = DAG_BLACK; - - time++; - base = sce->base.first; - while (base->object != node->ob) - base = base->next; - BLI_remlink(&sce->base,base); - BLI_addhead(&tempbase,base); - } - } - } - - // temporal correction for circular dependancies - base = sce->base.first; - while (base) { - BLI_remlink(&sce->base,base); - BLI_addhead(&tempbase,base); - base = sce->base.first; - } - - sce->base = tempbase; - queue_delete(nqueue); -} - // used to get the obs owning a datablock struct DagNodeQueue *get_obparents(struct DagForest *dag, void *ob) @@ -1020,7 +947,10 @@ struct DagNodeQueue *get_obparents(struct DagForest *dag, void *ob) DagAdjList *itA; node = dag_find_node(dag,ob); - if (node->ancestor_count == 1) { // simple case + if(node==NULL) { + return NULL; + } + else if (node->ancestor_count == 1) { // simple case nqueue = queue_create(1); push_queue(nqueue,node); } else { // need to go over the whole dag for adj list @@ -1082,7 +1012,7 @@ struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) int skip = 0; nqueue = queue_create(DAGQUEUEALLOC); - retqueue = queue_create(MainDag->numNodes); + retqueue = queue_create(dag->numNodes); // was MainDag... why? (ton) node = dag->DagNode.first; while(node) { @@ -1092,45 +1022,47 @@ struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) time = 1; - node = dag_find_node(dag,ob); - - node->color = DAG_GRAY; - time++; - push_stack(nqueue,node); - - while(nqueue->count) { + node = dag_find_node(dag,ob); // could be done in loop above (ton) + if(node) { // can be null for newly added objects - skip = 0; - node = get_top_node_queue(nqueue); - - itA = node->child; - while(itA != NULL) { - if((itA->node->color == DAG_WHITE) ) { - itA->node->DFS_dvtm = time; - itA->node->color = DAG_GRAY; - - time++; - push_stack(nqueue,itA->node); - skip = 1; - break; - } - itA = itA->next; - } + node->color = DAG_GRAY; + time++; + push_stack(nqueue,node); - if (!skip) { - node = pop_queue(nqueue); - node->color = DAG_BLACK; + while(nqueue->count) { - time++; - push_stack(retqueue,node); + skip = 0; + node = get_top_node_queue(nqueue); + + itA = node->child; + while(itA != NULL) { + if((itA->node->color == DAG_WHITE) ) { + itA->node->DFS_dvtm = time; + itA->node->color = DAG_GRAY; + + time++; + push_stack(nqueue,itA->node); + skip = 1; + break; + } + itA = itA->next; + } + + if (!skip) { + node = pop_queue(nqueue); + node->color = DAG_BLACK; + + time++; + push_stack(retqueue,node); + } } } - queue_delete(nqueue); return(retqueue); } -dag_rel_type are_obs_related(struct DagForest *dag, void *ob1, void *ob2) { +/* unused */ +short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) { DagNode * node; DagAdjList *itA; @@ -1211,4 +1143,434 @@ void graph_print_adj_list(void) } } +/* ************************ API *********************** */ + +/* sort the base list on dependency order */ +void DAG_scene_sort(struct Scene *sce) +{ + DagNode *node; + DagNodeQueue *nqueue; + DagAdjList *itA; + int time; + int skip = 0; + ListBase tempbase; + Base *base; + + tempbase.first= tempbase.last= NULL; + + build_dag(sce, DAG_RL_ALL_BUT_DATA); + + nqueue = queue_create(DAGQUEUEALLOC); + + node = sce->theDag->DagNode.first; + while(node) { + node->color = DAG_WHITE; + node = node->next; + } + + time = 1; + + node = sce->theDag->DagNode.first; + + node->color = DAG_GRAY; + time++; + push_stack(nqueue,node); + + while(nqueue->count) { + + skip = 0; + node = get_top_node_queue(nqueue); + + itA = node->child; + while(itA != NULL) { + if((itA->node->color == DAG_WHITE) ) { + itA->node->DFS_dvtm = time; + itA->node->color = DAG_GRAY; + + time++; + push_stack(nqueue,itA->node); + skip = 1; + break; + } + itA = itA->next; + } + + if (!skip) { + if (node) { + node = pop_queue(nqueue); + if (node->ob == sce) // we are done + break ; + node->color = DAG_BLACK; + + time++; + base = sce->base.first; + while (base->object != node->ob) + base = base->next; + BLI_remlink(&sce->base,base); + BLI_addhead(&tempbase,base); + } + } + } + + // temporal correction for circular dependancies + base = sce->base.first; + while (base) { + BLI_remlink(&sce->base,base); + BLI_addhead(&tempbase,base); + //if(G.f & G_DEBUG) + printf("cyclic %s\n", base->object->id.name); + base = sce->base.first; + } + + sce->base = tempbase; + queue_delete(nqueue); + + if(G.f & G_DEBUG) { + printf("\nordered\n"); + for(base = sce->base.first; base; base= base->next) { + printf(" %s\n", base->object->id.name); + } + } +} + +/* node was checked to have lasttime != curtime and is if type ID_OB */ +static void flush_update_node(DagNode *node, unsigned int layer, int curtime) +{ + DagAdjList *itA; + Object *ob, *obc; + int oldflag, changed=0; + unsigned int all_layer; + + node->lasttime= curtime; + + ob= node->ob; + if(ob->recalc & OB_RECALC) { + all_layer= ob->lay; + /* got an object node that changes, now check relations */ + for(itA = node->child; itA; itA= itA->next) { + all_layer |= itA->lay; + /* the relationship is visible */ + if(itA->lay & layer) { + if(itA->node->type==ID_OB) { + obc= itA->node->ob; + oldflag= obc->recalc; + + /* got a ob->obc relation, now check if flag needs flush */ + if(ob->recalc & OB_RECALC_OB) { + if(itA->type & DAG_RL_OB_OB) { + //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name); + obc->recalc |= OB_RECALC_OB; + } + if(itA->type & DAG_RL_OB_DATA) { + //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name); + obc->recalc |= OB_RECALC_DATA; + } + } + if(ob->recalc & OB_RECALC_DATA) { + if(itA->type & DAG_RL_DATA_OB) { + //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name); + obc->recalc |= OB_RECALC_OB; + } + if(itA->type & DAG_RL_DATA_DATA) { + //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name); + obc->recalc |= OB_RECALC_DATA; + } + } + if(oldflag!=obc->recalc) changed= 1; + } + } + } + /* even nicer, we can clear recalc flags... but we don't for armatures, these can have poses that need pointer checks (read old file issue) */ + if(ob->type!=OB_ARMATURE) + if((all_layer & layer)==0) + ob->recalc &= ~OB_RECALC; + } + else{ + /* Object has not RECALC flag */ + /* check case where child changes and parent forcing obdata to change */ + /* could merge this in with loop above... (ton) */ + for(itA = node->child; itA; itA= itA->next) { + /* the relationship is visible */ + if(itA->lay & layer) { + if(itA->node->type==ID_OB) { + obc= itA->node->ob; + /* child moves */ + if((obc->recalc & OB_RECALC)==OB_RECALC_OB) { + /* parent has deforming info */ + if(itA->type & (DAG_RL_OB_DATA|DAG_RL_DATA_DATA)) { + // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name); + obc->recalc |= OB_RECALC_DATA; + } + } + } + } + } + } + /* we only go deeper if node not checked or something changed */ + for(itA = node->child; itA; itA= itA->next) { + if(changed || itA->node->lasttime!=curtime) + flush_update_node(itA->node, layer, curtime); + } +} + +/* node was checked to have lasttime != curtime , and is of type ID_OB */ +static unsigned int flush_layer_node(DagNode *node, int curtime) +{ + DagAdjList *itA; + + node->lasttime= curtime; + node->lay= ((Object *)node->ob)->lay; + + for(itA = node->child; itA; itA= itA->next) { + if(itA->node->type==ID_OB) { + if(itA->node->lasttime!=curtime) { + itA->lay= flush_layer_node(itA->node, curtime); // lay is only set once for each relation + //printf("layer %d for relation %s to %s\n", itA->lay, ((Object *)node->ob)->id.name, ((Object *)itA->node->ob)->id.name); + } + else itA->lay= itA->node->lay; + + node->lay |= itA->lay; + } + } + + return node->lay; +} + +/* flushes all recalc flags in objects down the dependency tree */ +void DAG_scene_flush_update(Scene *sce) +{ + DagNode *firstnode; + DagAdjList *itA; + int lasttime; + + firstnode= sce->theDag->DagNode.first; // always scene node + + /* first we flush the layer flags */ + sce->theDag->time++; // so we know which nodes were accessed + lasttime= sce->theDag->time; + for(itA = firstnode->child; itA; itA= itA->next) { + if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) + flush_layer_node(itA->node, lasttime); + } + + /* then we use the relationships + layer info to flush update events */ + sce->theDag->time++; // so we know which nodes were accessed + lasttime= sce->theDag->time; + for(itA = firstnode->child; itA; itA= itA->next) { + if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) + flush_update_node(itA->node, sce->lay, lasttime); + } +} + +/* flag all objects that need recalc, for changes in time for example */ +void DAG_scene_update_flags(Scene *sce, unsigned int lay) +{ + Base *base; + Object *ob; + + /* set ob flags where animated systems are */ + for(base= sce->base.first; base; base= base->next) { + + /* now if DagNode were part of base, the node->lay could be checked... */ + /* we do all now, since the scene_flush checks layers */ + //if((base->lay & lay)) { + ob= base->object; + + if(ob->ipo) ob->recalc |= OB_RECALC_OB; + else if(ob->constraints.first) ob->recalc |= OB_RECALC_OB; + else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; + else if(ob->parent) { + if(ob->parent->type==OB_CURVE) ob->recalc |= OB_RECALC_OB; + } + + if(ob->action) ob->recalc |= OB_RECALC_DATA; + else if(ob->nlastrips.first) ob->recalc |= OB_RECALC_DATA; + else if(ob->softflag & OB_SB_ENABLE) ob->recalc |= OB_RECALC_DATA; + else { + Mesh *me; + Curve *cu; + Lattice *lt; + + switch(ob->type) { + case OB_MESH: + me= ob->data; + if(me->key) ob->recalc |= OB_RECALC_DATA; + else if(ob->effect.first) { + Effect *eff= ob->effect.first; + if(eff->type==EFF_WAVE) ob->recalc |= OB_RECALC_DATA; + } + break; + case OB_CURVE: + case OB_SURF: + cu= ob->data; + if(cu->key) ob->recalc |= OB_RECALC_DATA; + break; + case OB_LATTICE: + lt= ob->data; + if(lt->key) ob->recalc |= OB_RECALC_DATA; + break; + } + } + //} + } + DAG_scene_flush_update(sce); +} + +/* flag this object and all its relations to recalc */ +/* if you need to do more objects, tag object yourself and + use DAG_scene_flush_update() in end */ +void DAG_object_flush_update(Scene *sce, Object *ob, short flag) +{ + Base *base; + + if(ob==NULL) return; + ob->recalc |= flag; + + /* all users of this ob->data should be checked */ + if(flag & OB_RECALC_DATA) { + ID *id= ob->data; + if(id && id->us>1) { + for (base= sce->base.first; base; base= base->next) { + if (ob->data==base->object->data) { + base->object->recalc |= OB_RECALC_DATA; + } + } + } + } + + DAG_scene_flush_update(sce); +} + +/* ******************* DAG FOR ARMATURE POSE ***************** */ + +/* we assume its an armature with pose */ +void DAG_pose_sort(Object *ob) +{ + bPose *pose= ob->pose; + bPoseChannel *pchan; + bConstraint *con; + DagNode *node; + DagNode *node2, *node3; + DagNode *rootnode; + DagForest *dag; + DagNodeQueue *nqueue; + DagAdjList *itA; + ListBase tempbase; + int skip = 0; + + dag = dag_init(); + ugly_hack_sorry= 0; // no ID structs + + rootnode = dag_add_node(dag, NULL); // node->ob becomes NULL + + /* we add the hierarchy and the constraints */ + for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) { + int addtoroot = 1; + + node = dag_get_node(dag, pchan); + + if(pchan->parent) { + node2 = dag_get_node(dag, pchan->parent); + dag_add_relation(dag, node2, node, 0); + addtoroot = 0; + } + for (con = pchan->constraints.first; con; con=con->next){ + if (constraint_has_target(con)) { + char *subtarget; + Object *target = get_constraint_target(con, &subtarget); + + if (target==ob && subtarget) { + bPoseChannel *target= get_pose_channel(ob->pose, subtarget); + if(target) { + node2= dag_get_node(dag, target); + dag_add_relation(dag, node2, node, 0); + + if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + bPoseChannel *par= pchan->parent; + + while(par) { + node3= dag_get_node(dag, par); + dag_add_relation(dag, node2, node3, 0); + + if(par->bone->flag & BONE_IK_TOPARENT) + par= par->parent; + else break; + } + } + } + } + } + } + if (addtoroot == 1 ) + dag_add_relation(dag, rootnode, node, 0); + } + + /* now we try to sort... */ + tempbase.first= tempbase.last= NULL; + + nqueue = queue_create(DAGQUEUEALLOC); + + /* tag nodes unchecked */ + for(node = dag->DagNode.first; node; node= node->next) + node->color = DAG_WHITE; + + node = dag->DagNode.first; + + node->color = DAG_GRAY; + push_stack(nqueue, node); + + while(nqueue->count) { + + skip = 0; + node = get_top_node_queue(nqueue); + + itA = node->child; + while(itA != NULL) { + if((itA->node->color == DAG_WHITE) ) { + itA->node->color = DAG_GRAY; + push_stack(nqueue,itA->node); + skip = 1; + break; + } + itA = itA->next; + } + + if (!skip) { + if (node) { + node = pop_queue(nqueue); + if (node->ob == NULL) // we are done + break ; + node->color = DAG_BLACK; + + /* put node in new list */ + BLI_remlink(&pose->chanbase, node->ob); + BLI_addhead(&tempbase, node->ob); + } + } + } + + // temporal correction for circular dependancies + while(pose->chanbase.first) { + pchan= pose->chanbase.first; + BLI_remlink(&pose->chanbase, pchan); + BLI_addhead(&tempbase, pchan); + + printf("cyclic %s\n", pchan->name); + } + + pose->chanbase = tempbase; + queue_delete(nqueue); + +// printf("\nordered\n"); +// for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) { +// printf(" %s\n", pchan->name); +// } + + free_forest( dag ); + MEM_freeN( dag ); + + ugly_hack_sorry= 1; +} + + diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 3e4c670dd04..b2876260c15 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -238,24 +238,6 @@ void freedisplist(ListBase *lb) } } -static void freedisplist_object(Object *ob) -{ - freedisplist(&ob->disp); - - if(ob->type==OB_MESH) { - Mesh *me= ob->data; - freedisplist(&me->disp); - if (me->derived) { - me->derived->release(me->derived); - me->derived = NULL; - } - } - else if(ob->type==OB_CURVE || ob->type==OB_SURF || ob->type==OB_FONT) { - Curve *cu= ob->data; - freedisplist(&cu->disp); - } -} - DispList *find_displist_create(ListBase *lb, int type) { DispList *dl; @@ -1661,12 +1643,12 @@ void makeDispList(Object *ob) if (ob!=G.obedit) mesh_modifier(ob, 'e'); } else if(ob->type==OB_MBALL) { - ob= find_basis_mball(ob); + if(ob==find_basis_mball(ob)) { + metaball_polygonize(ob); + tex_space_mball(ob); - metaball_polygonize(ob); - tex_space_mball(ob); - - object_deform(ob); + object_deform(ob); + } } else if(ob->type==OB_SURF) { @@ -1760,6 +1742,7 @@ void makeDispList(Object *ob) if(ob!=G.obedit) object_deform(ob); } else if ELEM(ob->type, OB_CURVE, OB_FONT) { + int obedit= (G.obedit && G.obedit->data==ob->data); draw= ob->dt; cu= ob->data; @@ -1767,21 +1750,23 @@ void makeDispList(Object *ob) if(dl_onlyzero && dispbase->first) return; freedisplist(dispbase); + BLI_freelistN(&(cu->bev)); + if(cu->path) free_path(cu->path); - cu->path= 0; + cu->path= NULL; - BLI_freelistN(&(cu->bev)); + if(ob->type==OB_FONT) text_to_curve(ob, 0); - if(ob!=G.obedit) curve_modifier(ob, 's'); + if(!obedit) curve_modifier(ob, 's'); - if(ob==G.obedit) { + if(obedit) { if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase); else curve_to_displist(&cu->nurb, dispbase); - if(cu->flag & CU_PATH) makeBevelList(ob); + makeBevelList(ob); // always needed, so calc_curvepath() can work } else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==NULL && cu->width==1.0) { curve_to_displist(&cu->nurb, dispbase); - if(cu->flag & CU_PATH) makeBevelList(ob); + makeBevelList(ob); // always needed, so calc_curvepath() can work } else { @@ -1893,10 +1878,12 @@ void makeDispList(Object *ob) freedisplist(&dlbev); } } + if(cu->flag & CU_PATH) calc_curvepath(ob); - if(ob!=G.obedit) curve_modifier(ob, 'e'); - if(ob!=G.obedit) object_deform(ob); - + if(!obedit) { + curve_modifier(ob, 'e'); + object_deform(ob); + } tex_space_curve(cu); } @@ -2203,142 +2190,6 @@ void imagestodisplist(void) allqueue(REDRAWVIEW3D, 0); } -/* on frame change */ -/* new method: only frees displists, and relies on - drawobject.c & convertscene.c to build it when needed -*/ -void test_all_displists(void) -{ - Base *base; - Object *ob; - unsigned int lay; - int makedisp, freedisp; - - /* background */ - lay= G.scene->lay; - - /* clear flags, we use them because parent->parents are evaluated too */ - base= G.scene->base.first; - while(base) { - if(base->lay & lay) { - base->object->flag &= ~(BA_DISP_UPDATE|BA_WHERE_UPDATE); - } - if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; - else base= base->next; - } - - base= G.scene->base.first; - while(base) { - if(base->lay & lay) { - ob= base->object; - makedisp= freedisp= 0; - - if(ob->type==OB_MBALL && (ob->ipo || ob->parent)) { - // find metaball object holding the displist - // WARNING: if more metaballs have IPO's the displist - // is recalculated to often... do we free the displist - // and rely on the drawobject.c to build it again when needed - - if(ob->disp.first == NULL) { - ob= find_basis_mball(ob); - } - makedisp= 1; - } - else if(ob->parent) { - - if (ob->parent->type == OB_LATTICE) - freedisp= 1; - else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL)) - makedisp= 1; - else if(ob->softflag & OB_SB_ENABLE) - makedisp= 1; - else if ((ob->parent->type==OB_CURVE) && (ob->partype == PARSKEL)) - freedisp= 1; - else if(ob->partype==PARVERT1 || ob->partype==PARVERT3) { - if(ob->parent->parent) - ob->parent->flag |= BA_DISP_UPDATE; - else if(ob->parent->effect.first) // stupid test for wave - ob->parent->flag |= BA_DISP_UPDATE; - } - } - - if(ob->hooks.first) { - ObHook *hook; - for(hook= ob->hooks.first; hook; hook= hook->next) { - if(hook->parent) - freedisp= 1; - break; - } - } - - if(ob->softflag & OB_SB_ENABLE) freedisplist_object(ob); - /* warn, ob pointer changed in case of OB_MALL */ - - if ELEM(ob->type, OB_CURVE, OB_SURF) { - if(ob!=G.obedit) { - Curve *cu= ob->data; - - if(cu->key ) makedisp= 1; - if(cu->bevobj) { - Curve *cu1= cu->bevobj->data; - if(cu1->key ) freedisp= 1; - } - if(cu->taperobj) { - Curve *cu1= cu->taperobj->data; - if(cu1->key ) freedisp= 1; - } - } - } - else if(ob->type==OB_FONT) { - Curve *cu= ob->data; - if(cu->textoncurve) { - if( ((Curve *)cu->textoncurve->data)->key ) { - text_to_curve(ob, 0); - freedisp= 1; - } - } - } - else if(ob->type==OB_MESH) { - if(ob->effect.first) { - Effect *eff= ob->effect.first; - while(eff) { - if(eff->type==EFF_WAVE) { - freedisp= 1; - break; - } - eff= eff->next; - } - } - if(ob!=G.obedit) { - if(( ((Mesh *)(ob->data))->key )) - freedisp= 1; - } - } - if(freedisp) ob->flag |= BA_WHERE_UPDATE; - if(makedisp) ob->flag |= BA_DISP_UPDATE; - } - if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; - else base= base->next; - } - - /* going over the flags to free or make displists */ - base= G.scene->base.first; - while(base) { - if(base->lay & lay) { - ob= base->object; - if(ob->flag & BA_DISP_UPDATE) { - where_is_object(ob); - makeDispList(ob); - } - else if(ob->flag & BA_WHERE_UPDATE) freedisplist_object(ob); - } - if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; - else base= base->next; - } - -} - - void boundbox_displist(Object *ob) { BoundBox *bb=0; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index dc2594079f2..aca3d38a98e 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -1314,7 +1314,7 @@ void build_particle_system(Object *ob) do_ob_key(par); if(par->type==OB_ARMATURE) { do_all_actions(par); // only does this object actions - clear_object_constraint_status(par); // mysterious call, otherwise do_actions doesnt work??? +// clear_object_constraint_status(par); // mysterious call, otherwise do_actions doesnt work??? } par= par->parent; } @@ -1394,7 +1394,7 @@ void build_particle_system(Object *ob) if(par->type==OB_ARMATURE) { do_all_actions(par); // only does this object actions - clear_object_constraint_status(par); // mysterious call, otherwise do_actions doesnt work??? +// clear_object_constraint_status(par); // mysterious call, otherwise do_actions doesnt work??? } par= par->parent; } diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index a371edcf954..b49143ff48f 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -1028,7 +1028,6 @@ static void read_videoscape_nurbs(char *str) } } fclose(fp); - makeDispList(ob); } static void read_videoscape(char *str) diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 5305dfb56ec..61869e47040 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -510,8 +510,6 @@ struct chartrans *text_to_curve(Object *ob, int mode) ct++; } - - cu->lines= 1; ct= chartransdata; for (i= 0; i<=slen; i++, mem++, ct++) { @@ -562,7 +560,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) oldflag= cucu->flag; cucu->flag |= (CU_PATH+CU_FOLLOW); - if(cucu->path==0) calc_curvepath(cu->textoncurve); + if(cucu->path==NULL) makeDispList(cu->textoncurve); if(cucu->path) { diff --git a/source/blender/blenkernel/intern/ika.c b/source/blender/blenkernel/intern/ika.c deleted file mode 100644 index 32903590043..00000000000 --- a/source/blender/blenkernel/intern/ika.c +++ /dev/null @@ -1,596 +0,0 @@ - -/* ika.c - * - * - * $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 <math.h> -#include <stdlib.h> - -#include "MEM_guardedalloc.h" - -/* types */ -#include "DNA_ika_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_view3d_types.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" -/* functions */ -#include "BKE_blender.h" -#include "BKE_library.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_object.h" -#include "BKE_ika.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -/* Let's go! */ -#define TOLER 0.000076 -#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) - - -void unlink_ika(Ika *ika) -{ - - -} - -/* do not free Ika itself */ -void free_ika(Ika *ika) -{ - - /* unimplemented!!! */ - unlink_ika(ika); - - BLI_freelistN(&ika->limbbase); - - if(ika->def) MEM_freeN(ika->def); -} - -Ika *add_ika() -{ - Ika *ika; - - ika= alloc_libblock(&G.main->ika, ID_IK, "Ika"); - ika->flag = IK_GRABEFF | IK_XYCONSTRAINT; - - ika->xyconstraint= 0.5f; - ika->mem= 0.3f; - ika->iter= 6; - - return ika; -} - -Ika *copy_ika(Ika *ika) -{ - Ika *ikan; - - ikan= copy_libblock(ika); - - duplicatelist(&ikan->limbbase, &ika->limbbase); - - ikan->def= MEM_dupallocN(ikan->def); - - return ikan; -} - -void make_local_ika(Ika *ika) -{ - Object *ob; - Ika *ikan; - int local=0, lib=0; - - /* - only lib users: dont do - * - only local users: set flag - * - mixed: copy - */ - - if(ika->id.lib==0) return; - if(ika->id.us==1) { - ika->id.lib= 0; - ika->id.flag= LIB_LOCAL; - new_id(0, (ID *)ika, 0); - return; - } - - ob= G.main->object.first; - while(ob) { - if(ob->data==ika) { - if(ob->id.lib) lib= 1; - else local= 1; - } - ob= ob->id.next; - } - - if(local && lib==0) { - ika->id.lib= 0; - ika->id.flag= LIB_LOCAL; - new_id(0, (ID *)ika, 0); - } - else if(local && lib) { - ikan= copy_ika(ika); - ikan->id.us= 0; - - ob= G.main->object.first; - while(ob) { - if(ob->data==ika) { - - if(ob->id.lib==0) { - ob->data= ikan; - ikan->id.us++; - ika->id.us--; - } - } - ob= ob->id.next; - } - } -} - -int count_limbs(Object *ob) -{ - int tot=0; - Ika *ika; - Limb *li; - - if(ob->type!=OB_IKA) return 0; - ika= ob->data; - - li= ika->limbbase.first; - while(li) { - tot++; - li= li->next; - } - return tot; -} - -/* ************************************************** */ - - -/* using eff[ ] and len and alpha */ -void calc_limb(Limb *li) -{ - Limb *prev= li; - float vec[2], alpha= 0.0; - - /* alpha from 'parents' */ - while( (prev=prev->prev) ) { - alpha+= prev->alpha; - } - - if(li->prev) { - vec[0]= -li->prev->eff[0]; - vec[1]= -li->prev->eff[1]; - } - else vec[0]= vec[1]= 0.0; - - vec[0]+= li->eff[0]; - vec[1]+= li->eff[1]; - - li->alpha= (float)atan2(vec[1], vec[0]) - alpha; - li->len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1]); - -} - -/* using len and alpha the endpoints are calculated */ -void calc_ika(Ika *ika, Limb *li) -{ - float alpha=0.0, co, si; - - if(li) { - Limb *prev= li; - while((prev=prev->prev)) { - alpha+= prev->alpha; - } - } - else li= ika->limbbase.first; - - while(li) { - if(li->alpha != li->alpha) li->alpha= 0.0f; /* NaN patch */ - - alpha+= li->alpha; - - co= (float)cos(alpha); - si= (float)sin(alpha); - - li->eff[0]= co*li->len; - li->eff[1]= si*li->len; - - if(li->prev) { - li->eff[0]+= li->prev->eff[0]; - li->eff[1]+= li->prev->eff[1]; - } - - if(li->next==0) { - ika->eff[0]= li->eff[0]; - ika->eff[1]= li->eff[1]; - } - - li= li->next; - } -} - -void init_defstate_ika(Object *ob) -{ - Ika *ika; - Limb *li; - - ika= ob->data; - ika->totx= 0.0; - ika->toty= 0.0; - li= ika->limbbase.first; - - calc_ika(ika, 0); /* correct endpoints */ - - while(li) { - li->alphao= li->alpha; - li->leno= li->len; - - li= li->next; - } - ika->eff[2]= 0.0; - VecMat4MulVecfl(ika->effg, ob->obmat, ika->eff); -} - -void itterate_limb(Ika *ika, Limb *li) -{ - float da, n1[2], n2[2], len1, len2; - - if(li->prev) { - n1[0]= ika->eff[0] - li->prev->eff[0]; - n1[1]= ika->eff[1] - li->prev->eff[1]; - n2[0]= ika->effn[0] - li->prev->eff[0]; - n2[1]= ika->effn[1] - li->prev->eff[1]; - } - else { - n1[0]= ika->eff[0]; - n1[1]= ika->eff[1]; - n2[0]= ika->effn[0]; - n2[1]= ika->effn[1]; - } - len1= (float)sqrt(n1[0]*n1[0] + n1[1]*n1[1]); - len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]); - - da= (1.0f-li->fac)*saacos( (n1[0]*n2[0]+n1[1]*n2[1])/(len1*len2) ); - - if(n1[0]*n2[1] < n1[1]*n2[0]) da= -da; - - li->alpha+= da; - -} - -void rotate_ika(Object *ob, Ika *ika) -{ - Limb *li; - float len2, da, n1[2], n2[2]; - - /* rotate back */ - euler_rot(ob->rot, -ika->toty, 'y'); - ika->toty= 0.0; - - where_is_object(ob); - - Mat4Invert(ob->imat, ob->obmat); - VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); - - li= ika->limbbase.last; - if(li==0) return; - - n1[0]= ika->eff[0]; - n2[0]= ika->effn[0]; - n2[1]= ika->effn[2]; - - len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]); - - if(len2>TOLER) { - da= (n2[0])/(len2); - if(n1[0]<0.0) da= -da; - - /* when the x component is almost zero, this can happen */ - if(da<=-1.0+TOLER || da>=1.0) ; - else { - - da= saacos( da ); - if(n1[0]*n2[1] > 0.0) da= -da; - - euler_rot(ob->rot, da, 'y'); - ika->toty= da; - } - } -} - -void rotate_ika_xy(Object *ob, Ika *ika) -{ - Limb *li; - float ang, da, n1[3], n2[3], axis[3], quat[4]; - - /* rotate back */ - euler_rot(ob->rot, -ika->toty, 'y'); - euler_rot(ob->rot, -ika->totx, 'x'); - - where_is_object(ob); - - Mat4Invert(ob->imat, ob->obmat); - VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); - - li= ika->limbbase.last; - if(li==0) return; - - /* ika->eff = old situation */ - /* ika->effn = desired situation */ - - *(n1)= *(ika->effn); - *(n1+1)= *(ika->effn+1); - *(n1+2)= 0.0; - - *(n2)= *(ika->effn); - *(n2+1)= *(ika->effn+1); - *(n2+2)= *(ika->effn+2); - - Normalise(n1); - Normalise(n2); - - ang= n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2]; - ang= saacos(ang); - - if(ang<-0.0000001 || ang>0.00000001) { - Crossf(axis, n1, n2); - Normalise(axis); - quat[0]= (float)cos(0.5*ang); - da= (float)sin(0.5*ang); - quat[1]= da*axis[0]; - quat[2]= da*axis[1]; - quat[3]= da*axis[2]; - - QuatToEul(quat, axis); - - ika->totx= axis[0]; - CLAMP(ika->totx, -ika->xyconstraint, ika->xyconstraint); - ika->toty= axis[1]; - CLAMP(ika->toty, -ika->xyconstraint, ika->xyconstraint); - } - - euler_rot(ob->rot, ika->totx, 'x'); - euler_rot(ob->rot, ika->toty, 'y'); -} - -void itterate_ika(Object *ob) -{ - Ika *ika; - Limb *li; - int it = 0; - - ika= ob->data; - if((ika->flag & IK_GRABEFF)==0) return; - - disable_where_script(1); - /* memory: handle large steps in time */ - it= abs(ika->lastfra - G.scene->r.cfra); - ika->lastfra= G.scene->r.cfra; - if(it>10) { - - /* one itteration extra */ - itterate_ika(ob); - } - else { - li= ika->limbbase.first; - while(li) { - li->alpha= (1.0f-ika->mem)*li->alpha + ika->mem*li->alphao; - li= li->next; - } - } - calc_ika(ika, 0); - - /* effector has parent? */ - if(ika->parent) { - - if(ika->partype==PAROBJECT) { - if(ika->parent->ctime != (float) G.scene->r.cfra) where_is_object(ika->parent); - *(ika->effg)= *(ika->parent->obmat[3]); - *(ika->effg+1)= *(ika->parent->obmat[3]+1); - *(ika->effg+2)= *(ika->parent->obmat[3]+2); - } - else { - what_does_parent1(ika->parent, ika->partype, ika->par1, 0, 0); - *(ika->effg)= *(workob.obmat[3]); - *(ika->effg+1)= *(workob.obmat[3]+1); - *(ika->effg+2)= *(workob.obmat[3]+2); - } - } - - - /* rotate y-as correctly */ - if(ika->flag & IK_XYCONSTRAINT) - rotate_ika_xy(ob, ika); - else - rotate_ika(ob, ika); - - it= ika->iter; - while(it--) { - - where_is_object(ob); - Mat4Invert(ob->imat, ob->obmat); - VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); - /* forward orfer: to do the first limbs as well */ - li= ika->limbbase.first; - while(li) { - - itterate_limb(ika, li); - - /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */ - calc_ika(ika, li); - - li= li->next; - } - - where_is_object(ob); - Mat4Invert(ob->imat, ob->obmat); - VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); - - /* backward */ - li= ika->limbbase.last; - while(li) { - - itterate_limb(ika, li); - - /* when you put calc_ika() outside this loop: long chains get instable */ - calc_ika(ika, li); - - li= li->prev; - } - } - - disable_where_script(0); -} - - -void do_all_ikas() -{ - Base *base = 0; - - base= G.scene->base.first; - while(base) { - - if(base->object->type==OB_IKA) itterate_ika(base->object); - - base= base->next; - } -} - -void do_all_visible_ikas() -{ - Base *base = 0; - - base= G.scene->base.first; - while(base) { - if(base->lay & G.scene->lay) { - if(base->object->type==OB_IKA) itterate_ika(base->object); - } - base= base->next; - } -} - -/* ******************** DEFORM ************************ */ - - -void init_skel_deform(Object *par, Object *ob) -{ - Deform *def; - Ika *ika; - int a; - - /* deform: - * - * ob_vec * ob_obmat * def_imat (weight fie) * def_obmat * ob_imat = ob_vec' - * - * <----- premat ----> <---- postmat ----> - */ - - if(par->type!=OB_IKA) return; - - Mat4Invert(ob->imat, ob->obmat); - - ika= par->data; - a= ika->totdef; - def= ika->def; - while(a--) { - - what_does_parent1(def->ob, def->partype, def->par1, def->par2, def->par3); - - Mat4MulMat4(def->premat, ob->obmat, def->imat); - Mat4MulMat4(def->postmat, workob.obmat, ob->imat); - - def++; - } -} - - -void calc_skel_deform(Ika *ika, float *co) -{ - Deform *def; - int a; - float totw=0.0, weight, fac, len, vec[3], totvec[3]; - - def= ika->def; - if(def==0) return; - a= ika->totdef; - totvec[0]=totvec[1]=totvec[2]= 0.0; - - while(a--) { - - VecMat4MulVecfl(vec, def->premat, co); - - len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); - - if(def->vec[0]==0.0f) len= 2.0f*len; - else len= len + (float)sqrt( (vec[0]+def->vec[0])*(vec[0]+def->vec[0]) + vec[1]*vec[1] + vec[2]*vec[2]); - - /* def->vec[0]= len limb */ - - weight= 1.0f/(0.001f+len); - weight*= weight; - weight*= weight; - weight*= def->fac; - - len -= def->vec[0]; - - if(def->dist != 0.0) { - if(len >= def->dist) { - weight= 0.0; - } - else { - fac= (def->dist - len)/def->dist; - weight*= fac; - } - } - if(weight > 0.0) { - Mat4MulVecfl(def->postmat, vec); - - VecMulf(vec, weight); - VecAddf(totvec, totvec, vec); - - totw+= weight; - } - def++; - } - - if(totw==0.0) return; - - co[0]= totvec[0]/totw; - co[1]= totvec[1]/totw; - co[2]= totvec[2]/totw; - -} diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 25c23b8480b..a03eb0e35c4 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -41,22 +41,21 @@ #include "MEM_guardedalloc.h" -#include "DNA_ika_types.h" -#include "DNA_sequence_types.h" +#include "DNA_action_types.h" +#include "DNA_curve_types.h" #include "DNA_camera_types.h" -#include "DNA_sound_types.h" #include "DNA_lamp_types.h" -#include "DNA_view3d_types.h" +#include "DNA_ipo_types.h" #include "DNA_key_types.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" #include "DNA_material_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" -#include "DNA_mesh_types.h" -#include "DNA_curve_types.h" -#include "DNA_ipo_types.h" -#include "DNA_action_types.h" +#include "DNA_sequence_types.h" +#include "DNA_scene_types.h" +#include "DNA_sound_types.h" +#include "DNA_texture_types.h" +#include "DNA_view3d_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -64,15 +63,16 @@ #include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" -#include "BKE_main.h" -#include "BKE_global.h" -#include "BKE_library.h" -#include "BKE_curve.h" -#include "BKE_object.h" +#include "BKE_action.h" #include "BKE_blender.h" -#include "BKE_ipo.h" +#include "BKE_curve.h" #include "BKE_constraint.h" +#include "BKE_global.h" +#include "BKE_ipo.h" +#include "BKE_library.h" +#include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_object.h" #define SMALL -1.0e-10 @@ -89,7 +89,7 @@ int ob_ar[OB_TOTIPO]= { OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z, OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z, OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z, - OB_LAY, OB_TIME, OB_EFF_X, OB_EFF_Y, OB_EFF_Z, OB_COL_A, + OB_LAY, OB_TIME, OB_COL_R, OB_COL_G, OB_COL_B, OB_COL_A, OB_PD_FSTR, OB_PD_FFALL, OB_PD_SDAMP, OB_PD_RDAMP, OB_PD_PERM }; @@ -1080,25 +1080,45 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) return NULL; switch (icu->adrcode){ case AC_QUAT_W: - poin= &(pchan->quat[0]); break; + poin= &(pchan->quat[0]); + pchan->flag |= POSE_ROT; + break; case AC_QUAT_X: - poin= &(pchan->quat[1]); break; + poin= &(pchan->quat[1]); + pchan->flag |= POSE_ROT; + break; case AC_QUAT_Y: - poin= &(pchan->quat[2]); break; + poin= &(pchan->quat[2]); + pchan->flag |= POSE_ROT; + break; case AC_QUAT_Z: - poin= &(pchan->quat[3]); break; + poin= &(pchan->quat[3]); + pchan->flag |= POSE_ROT; + break; case AC_LOC_X: - poin= &(pchan->loc[0]); break; + poin= &(pchan->loc[0]); + pchan->flag |= POSE_LOC; + break; case AC_LOC_Y: - poin= &(pchan->loc[1]); break; + poin= &(pchan->loc[1]); + pchan->flag |= POSE_LOC; + break; case AC_LOC_Z: - poin= &(pchan->loc[2]); break; + poin= &(pchan->loc[2]); + pchan->flag |= POSE_LOC; + break; case AC_SIZE_X: - poin= &(pchan->size[0]); break; + poin= &(pchan->size[0]); + pchan->flag |= POSE_SIZE; + break; case AC_SIZE_Y: - poin= &(pchan->size[1]); break; + poin= &(pchan->size[1]); + pchan->flag |= POSE_SIZE; + break; case AC_SIZE_Z: - poin= &(pchan->size[2]); break; + poin= &(pchan->size[2]); + pchan->flag |= POSE_SIZE; + break; }; } @@ -1800,9 +1820,8 @@ int has_ipo_code(Ipo *ipo, int code) return 0; } -void do_all_ipos() +void do_all_data_ipos() { - Base *base; Material *ma; Tex *tex; World *wo; @@ -1813,7 +1832,6 @@ void do_all_ipos() Sequence *seq; Editing *ed; float ctime; - int set; ctime= frame_to_float(G.scene->r.cfra); @@ -1825,27 +1843,6 @@ void do_all_ipos() ipo= ipo->id.next; } - /* NEW: current scene ob ipo's */ - base= G.scene->base.first; - set= 0; - while(base) { - - /* Do object ipos */ - do_constraint_channels(&base->object->constraints, &base->object->constraintChannels, ctime); - - if(base->object->ipo) { - /* do per object ipo the calc_ipo: because of possible timeoffs */ - do_ob_ipo(base->object); - if(base->object->type==OB_MBALL) where_is_object(base->object); - } - base= base->next; - - if(base==0 && set==0 && G.scene->set) { - set= 1; - base= G.scene->set->base.first; - } - } - tex= G.main->tex.first; while(tex) { if(tex->ipo) execute_ipo((ID *)tex, tex->ipo); @@ -1882,39 +1879,14 @@ void do_all_ipos() snd= snd->id.next; } - /*just in case of... WATCH IT: 2x */ - base= G.scene->base.first; - while(base) { - - /* only update layer when an ipo */ - if( has_ipo_code(base->object->ipo, OB_LAY) ) { - base->lay= base->object->lay; - } - - base= base->next; - } - - /* just in case...*/ - if(G.scene->set) { - base= G.scene->set->base.first; - while(base) { - - /* only update layer when an ipo */ - if( has_ipo_code(base->object->ipo, OB_LAY) ) { - base->lay= base->object->lay; - } - - base= base->next; - } - } - - /* intrr: process FAC Ipos used as volume envelopes */ + /* process FAC Ipos used as volume envelopes */ ed= G.scene->ed; if (ed) { seq= ed->seqbasep->first; while(seq) { - if ((seq->type == SEQ_SOUND) && (seq->ipo) - &&(seq->startdisp<=G.scene->r.cfra+2) && (seq->enddisp>G.scene->r.cfra)) do_seq_ipo(seq); + if ((seq->type == SEQ_SOUND) && (seq->ipo) && + (seq->startdisp<=G.scene->r.cfra+2) && (seq->enddisp>G.scene->r.cfra)) + do_seq_ipo(seq); seq= seq->next; } } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 3b54072bd12..966eadeb2d5 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -897,8 +897,6 @@ void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, flo } } - - void do_mesh_key(Mesh *me) { KeyBlock *k[4]; @@ -906,8 +904,9 @@ void do_mesh_key(Mesh *me) int a, flag = 0, step; if(me->totvert==0) return; - if(me->key==0) return; - if(me->key->block.first==0) return; + if(me->key==NULL) return; + if(me->key->flag & KEY_LOCKED) return; + if(me->key->block.first==NULL) return; if(me->key->slurph && me->key->type!=KEY_RELATIVE ) { delta= me->key->slurph; @@ -981,6 +980,7 @@ void do_cu_key(Curve *cu, KeyBlock **k, float *t) tot= count_curveverts(&cu->nurb); nu= cu->nurb.first; a= 0; + while(nu) { if(nu->bp) { @@ -1051,8 +1051,9 @@ void do_curve_key(Curve *cu) tot= count_curveverts(&cu->nurb); if(tot==0) return; - if(cu->key==0) return; - if(cu->key->block.first==0) return; + if(cu->key==NULL) return; + if(cu->key->flag & KEY_LOCKED) return; + if(cu->key->block.first==NULL) return; if(cu->key->slurph) { delta= cu->key->slurph; @@ -1117,9 +1118,10 @@ void do_latt_key(Lattice *lt) float delta, cfra, ctime, t[4]; int a, tot, flag; - if(lt->key==0) return; + if(lt->key==NULL) return; + if(lt->key->flag & KEY_LOCKED) return; if(lt->key->block.first==0) return; - + tot= lt->pntsu*lt->pntsv*lt->pntsw; if(lt->key->slurph) { @@ -1172,21 +1174,14 @@ void do_latt_key(Lattice *lt) } - -void do_all_keys() +/* going to be removed */ +void unlock_all_keys() { Key *key; - int idcode; key= G.main->key.first; while(key) { - if(key->from) { - idcode= GS(key->from->name); - - if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from); - else if(idcode==ID_CU) do_curve_key( (Curve *)key->from); - else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from); - } + key->flag &= ~KEY_LOCKED; key= key->id.next; } } diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 3da60f99826..db5dee45d5d 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -51,7 +51,6 @@ #include "DNA_lattice_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" -#include "DNA_ika_types.h" #include "BKE_anim.h" #include "BKE_armature.h" @@ -59,7 +58,6 @@ #include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_global.h" -#include "BKE_ika.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 27d87ce9117..63524c47592 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -56,7 +56,6 @@ #include "DNA_meta_types.h" #include "DNA_material_types.h" #include "DNA_texture_types.h" -#include "DNA_ika_types.h" #include "DNA_image_types.h" #include "DNA_wave_types.h" #include "DNA_lamp_types.h" @@ -91,7 +90,6 @@ #include "BKE_texture.h" #include "BKE_scene.h" #include "BKE_image.h" -#include "BKE_ika.h" #include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_world.h" @@ -149,8 +147,6 @@ ListBase *wich_libbase(Main *mainlib, short type) return &(mainlib->tex); case ID_IM: return &(mainlib->image); - case ID_IK: - return &(mainlib->ika); case ID_WV: return &(mainlib->wave); case ID_LT: @@ -209,26 +205,26 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[8]= &(main->mesh); lb[9]= &(main->curve); lb[10]= &(main->mball); - lb[11]= &(main->ika); - lb[12]= &(main->wave); - lb[13]= &(main->latt); - lb[14]= &(main->lamp); - lb[15]= &(main->camera); - - lb[16]= &(main->world); - lb[17]= &(main->screen); - lb[18]= &(main->object); - lb[19]= &(main->scene); - lb[20]= &(main->library); - lb[21]= &(main->text); - lb[22]= &(main->sound); - lb[23]= &(main->group); - - lb[24]= samples; - lb[25]= &(main->script); - lb[26]=0; - - return 26; + + lb[11]= &(main->wave); + lb[12]= &(main->latt); + lb[13]= &(main->lamp); + lb[14]= &(main->camera); + + lb[15]= &(main->world); + lb[16]= &(main->screen); + lb[17]= &(main->object); + lb[18]= &(main->scene); + lb[19]= &(main->library); + lb[20]= &(main->text); + lb[21]= &(main->sound); + lb[22]= &(main->group); + + lb[23]= samples; + lb[24]= &(main->script); + lb[25]= NULL; + + return 25; } /* *********** ALLOC AND FREE ***************** @@ -273,9 +269,6 @@ static ID *alloc_libblock_notest(short type) case ID_IM: id= MEM_callocN(sizeof(Image), "image"); break; - case ID_IK: - id= MEM_callocN(sizeof(Ika), "ika"); - break; case ID_WV: id= MEM_callocN(sizeof(Wave), "wave"); break; @@ -421,9 +414,6 @@ void free_libblock(ListBase *lb, void *idv) case ID_IM: free_image((Image *)id); break; - case ID_IK: - free_ika((Ika *)id); - break; case ID_WV: /* free_wave(id); */ break; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index bc3290aa0d4..3d7fba62b0b 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -737,7 +737,7 @@ void delete_material_index() if(ob->type==OB_MESH) { Mesh *me= get_mesh(ob); mesh_delete_material_index(me, actcol-1); - makeDispList(ob); + freedisplist(&ob->disp); } else if ELEM(ob->type, OB_CURVE, OB_SURF) { cu= ob->data; @@ -750,6 +750,6 @@ void delete_material_index() } nu= nu->next; } - makeDispList(ob); + freedisplist(&ob->disp); } } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index fdb08813765..68aa863d22c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -48,7 +48,6 @@ #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_group_types.h" -#include "DNA_ika_types.h" #include "DNA_ipo_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" @@ -81,24 +80,24 @@ #include "BKE_main.h" #include "BKE_global.h" -#include "BKE_object.h" +#include "BKE_anim.h" #include "BKE_blender.h" -#include "BKE_screen.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_group.h" #include "BKE_ipo.h" -#include "BKE_ika.h" +#include "BKE_key.h" +#include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_mesh.h" -#include "BKE_curve.h" #include "BKE_mball.h" -#include "BKE_effect.h" -#include "BKE_sca.h" -#include "BKE_displist.h" +#include "BKE_object.h" #include "BKE_property.h" -#include "BKE_anim.h" -#include "BKE_group.h" -#include "BKE_lattice.h" -#include "BKE_constraint.h" +#include "BKE_sca.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "BKE_softbody.h" #include "BPY_extern.h" @@ -201,7 +200,7 @@ void free_object(Object *ob) if(ob->defbase.first) BLI_freelistN(&ob->defbase); if(ob->pose) { - clear_pose(ob->pose); + free_pose_channels(ob->pose); MEM_freeN(ob->pose); } free_effects(&ob->effect); @@ -237,8 +236,10 @@ void unlink_object(Object *ob) Tex *tex; ObHook *hook; Group *group; + bConstraint *con; int a; - + char *str; + unlink_controllers(&ob->controllers); unlink_actuators(&ob->actuators); @@ -246,37 +247,48 @@ void unlink_object(Object *ob) obt= G.main->object.first; while(obt) { if(obt->id.lib==NULL) { + if(obt->parent==ob) { obt->parent= NULL; - if(ob->type==OB_LATTICE) freedisplist(&obt->disp); + obt->recalc |= OB_RECALC; } - if(obt->track==ob) obt->track= NULL; + + if(obt->track==ob) { + obt->track= NULL; + obt->recalc |= OB_RECALC_OB; + } + for(hook=obt->hooks.first; hook; hook= hook->next) { - if(hook->parent==ob) hook->parent= NULL; + if(hook->parent==ob) { + hook->parent= NULL; + obt->recalc |= OB_RECALC; + } } + if ELEM(obt->type, OB_CURVE, OB_FONT) { cu= obt->data; - if(cu->bevobj==ob) cu->bevobj= NULL; - if(cu->taperobj==ob) cu->taperobj= NULL; - if(cu->textoncurve==ob) cu->textoncurve= NULL; - } - if(obt->type==OB_IKA) { - Ika *ika= obt->data; - Deform *def= ika->def; - - if(ika->parent==ob) ika->parent= NULL; - a= ika->totdef; - while(a--) { - if(def->ob==ob) { - ika->totdef= 0; - MEM_freeN(ika->def); - ika->def= NULL; - break; - } - def++; + if(cu->bevobj==ob) { + cu->bevobj= NULL; + obt->recalc |= OB_RECALC; + } + if(cu->taperobj==ob) { + cu->taperobj= NULL; + obt->recalc |= OB_RECALC; + } + if(cu->textoncurve==ob) { + cu->textoncurve= NULL; + obt->recalc |= OB_RECALC; } } + sca_remove_ob_poin(obt, ob); + + for (con = obt->constraints.first; con; con=con->next) { + if(ob==get_constraint_target(con, &str)) { + set_constraint_target(con, NULL); + obt->recalc |= OB_RECALC_OB; + } + } } obt= obt->id.next; } @@ -625,7 +637,6 @@ static void *add_obdata_from_type(int type) case OB_MBALL: return add_mball(); case OB_CAMERA: return add_camera(); case OB_LAMP: G.totlamp++; return add_lamp(); - case OB_IKA: return add_ika(); case OB_LATTICE: return add_lattice(); case OB_WAVE: return add_wave(); case OB_ARMATURE: return add_armature(); @@ -646,7 +657,6 @@ static char *get_obdata_defname(int type) case OB_MBALL: return "Mball"; case OB_CAMERA: return "Camera"; case OB_LAMP: return "Lamp"; - case OB_IKA: return "Ika"; case OB_LATTICE: return "Lattice"; case OB_WAVE: return "Wave"; case OB_ARMATURE: return "Armature"; @@ -721,7 +731,8 @@ Object *add_object(int type) base= scene_add_base(G.scene, ob); scene_select_base(G.scene, base); - + ob->recalc |= OB_RECALC; + return ob; } @@ -1071,57 +1082,31 @@ void ob_parcurve(Object *ob, Object *par, float mat[][4]) void ob_parbone(Object *ob, Object *par, float mat[][4]) { - Bone *bone; + bPoseChannel *pchan; bArmature *arm; - - Mat4One(mat); + float vec[3]; + arm=get_armature(par); - if (!arm) + if (!arm) { + Mat4One(mat); return; - + } + /* Make sure the bone is still valid */ - bone = get_named_bone(arm, ob->parsubstr); - if (!bone){ + pchan= get_pose_channel(par->pose, ob->parsubstr); + if (!pchan){ printf ("Lost bone %s\n", ob->parsubstr); + Mat4One(mat); return; } - apply_pose_armature(arm, par->pose, 1); /* Hopefully can set doit parameter in the future */ - where_is_bone (par, bone); + /* get bone transform */ + Mat4CpyMat4(mat, pchan->pose_mat); - /* Translate by negative bone */ - get_objectspace_bone_matrix(bone, mat, 0, 1); - -} - -void ob_parlimb(Object *ob, Object *par, float mat[][4]) -{ - Ika *ika; - Limb *li; - float ang=0.0; - int cur=0; - - /* in local ob space */ - Mat4One(mat); - - ika= par->data; - li= ika->limbbase.first; - while(li) { - ang+= li->alpha; - if(cur==ob->par1 || li->next==0) break; - - cur++; - li= li->next; - } - - mat[0][0]= (float)cos(ang); - mat[1][0]= (float)-sin(ang); - mat[0][1]= (float)sin(ang); - mat[1][1]= (float)cos(ang); - - mat[3][0]= li->eff[0]; - mat[3][1]= li->eff[1]; - + /* but for backwards compatibility, the child has to move to the tail */ + VECCOPY(vec, mat[1]); + VecMulf(vec, pchan->bone->length); + VecAddf(mat[3], mat[3], vec); } void give_parvert(Object *par, int nr, float *vec) @@ -1141,7 +1126,7 @@ void give_parvert(Object *par, int nr, float *vec) vec[0]=vec[1]=vec[2]= 0.0; if(par->type==OB_MESH) { - if(par==G.obedit) { + if(G.obedit && (par->data==G.obedit->data)) { if(nr >= G.totvert) nr= 0; count= 0; @@ -1209,20 +1194,6 @@ void give_parvert(Object *par, int nr, float *vec) } } - else if(par->type==OB_IKA) { - Ika *ika= par->data; - Limb *li= ika->limbbase.first; - int cur= 1; - if(nr) { - while(li) { - if(cur==nr || li->next==0) break; - cur++; - li= li->next; - } - vec[0]= li->eff[0]; - vec[1]= li->eff[1]; - } - } else return; } @@ -1309,13 +1280,9 @@ void where_is_object_time(Object *ob, float ctime) calc_ipo(ob->ipo, stime); execute_ipo((ID *)ob, ob->ipo); - } - } - - - if(ob->type==OB_IKA) { - Ika *ika= ob->data; - if(ika->parent) where_is_object_time(ika->parent, ctime); + } + /* do constraint ipos ... what the heck is a channel for! */ + do_constraint_channels(&ob->constraints, &ob->constraintChannels, ctime); } if(ob->parent) { @@ -1323,6 +1290,7 @@ void where_is_object_time(Object *ob, float ctime) if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf; + /* hurms, code below conflicts with depgraph... (ton) */ pop= 0; if(no_parent_ipo==0 && ctime != par->ctime) { @@ -1410,11 +1378,6 @@ static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int si Mat4MulSerie(totmat, par->obmat, tmat, NULL, NULL, NULL, NULL, NULL, NULL); break; - case PARLIMB: - ob_parlimb(ob, par, tmat); - Mat4MulSerie(totmat, par->obmat, tmat, - NULL, NULL, NULL, NULL, NULL, NULL); - break; case PARVERT1: Mat4One(totmat); @@ -1569,24 +1532,29 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) float smat[3][3], rmat[3][3], mat[3][3]; float enf; - for (con = ob->constraints.first; con; con=con->next){ + for (con = ob->constraints.first; con; con=con->next) { + // inverse kinematics is solved seperate + if (con->type==CONSTRAINT_TYPE_KINEMATIC) continue; + /* Clear accumulators if necessary*/ - if (clear){ - clear=0; - a=0; - tot=0; + if (clear) { + clear= 0; + a= 0; + tot= 0; memset(aquat, 0, sizeof(float)*4); memset(aloc, 0, sizeof(float)*3); memset(asize, 0, sizeof(float)*3); } /* Check this constraint only if it has some enforcement */ - if (!(con->flag & CONSTRAINT_DISABLE)) - { - if (con->enforce==0) + if (!(con->flag & CONSTRAINT_DISABLE)) { + /* weird code was here (ton) + if (con->enforce==0.0) enf = 0.001f; enf = con->enforce; - + */ + enf = con->enforce; + /* Get the targetmat */ get_constraint_target_matrix(con, obtype, obdata, tmat, size, ctime); @@ -1598,10 +1566,10 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) Mat3CpyMat4(mat, focusmat); Mat3ToSize(mat, size); - a+=enf; + a+= enf; tot++; - for(i=0; i<3; i++){ + for(i=0; i<3; i++) { aquat[i+1]+=(quat[i+1]) * enf; aloc[i]+=(loc[i]) * enf; asize[i]+=(size[i]-1.0f) * enf; @@ -1612,16 +1580,15 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) /* If the next constraint is not the same type (or there isn't one), * then evaluate the accumulator & request a clear */ - if ((!con->next)||(con->next && con->next->type!=con->type)) - { - clear=1; + if ((!con->next)||(con->next && con->next->type!=con->type)) { + clear= 1; Mat4CpyMat4(oldmat, ob->obmat); /* If we have several inputs, do a blend of them */ - if (tot){ - if (tot>1){ - if (a){ - for (i=0; i<3; i++){ + if (tot) { + if (tot>1) { + if (a) { + for (i=0; i<3; i++) { asize[i]=1.0f + (asize[i]/(a)); aloc[i]=(aloc[i]/a); } @@ -1639,14 +1606,14 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) } /* If we only have one, blend with the current obmat */ - else{ + else { float solution[4][4]; float delta[4][4]; float imat[4][4]; float identity[4][4]; float worldmat[4][4]; - if (con->type!=CONSTRAINT_TYPE_KINEMATIC){ + if (con->type!=CONSTRAINT_TYPE_KINEMATIC) { /* If we're not an IK constraint, solve the constraint then blend it to the previous one */ evaluate_constraint(con, ob, obtype, obdata, lastmat); @@ -1665,7 +1632,7 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) } else{ /* Interpolate the target between the chain's unconstrained endpoint and the effector loc */ - if (obtype==TARGET_BONE){ + if (obtype==TARGET_BONE) { get_objectspace_bone_matrix(obdata, oldmat, 1, 1); Mat4MulMat4(worldmat, oldmat, ob->parent->obmat); @@ -1681,28 +1648,7 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) } } -void what_does_parent1(Object *par, int partype, int par1, int par2, int par3) -{ - - clear_workob(); - Mat4One(workob.parentinv); - workob.parent= par; - if(par) - workob.track= par->track; /* WATCH IT: THATS NOT NICE CODE */ - workob.partype= partype; - workob.par1= par1; - workob.par2= par2; - workob.par3= par3; - - if (par){ - workob.constraints.first = par->constraints.first; - workob.constraints.last = par->constraints.last; - } - - where_is_object(&workob); -} - - +/* for calculation of the inverse parent transform, only used for editor */ void what_does_parent(Object *ob) { @@ -1800,4 +1746,32 @@ void minmax_object(Object *ob, float *min, float *max) } } +/* the main object update call, for object matrix, constraints, keys and displist (modifiers) */ +/* requires flags to be set! */ +void object_handle_update(Object *ob) +{ + if(ob->recalc & OB_RECALC) { + + if(ob->recalc & OB_RECALC_OB) where_is_object(ob); + + if(ob->recalc & OB_RECALC_DATA) { + + /* includes all keys and modifiers */ + if(ob->type && ob->type<OB_LAMP) { +// printf("recalcdata %s\n", ob->id.name+2); + makeDispList(ob); + } + else if(ob->type==OB_ARMATURE) { + /* this actually only happens for reading old files... */ + if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) + armature_rebuild_pose(ob, ob->data); + do_all_actions(ob); + where_is_pose(ob); + } + } + + ob->recalc &= ~OB_RECALC; + } +} + diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5d73b24e8bb..255cdba9f6d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -46,46 +46,39 @@ #endif #include "MEM_guardedalloc.h" -#include "nla.h" /* for __NLA : IMPORTANT Do not delete me yet! */ -#ifdef __NLA /* for __NLA : IMPORTANT Do not delete me yet! */ -#include "DNA_armature_types.h" /* for __NLA : IMPORTANT Do not delete me yet! */ -#include "BKE_armature.h" /* for __NLA : IMPORTANT Do not delete me yet! */ -#include "BKE_action.h" /* for __NLA : IMPORTANT Do not delete me yet! */ -#endif /* for __NLA : IMPORTANT Do not delete me yet! */ - +#include "DNA_armature_types.h" #include "DNA_constraint_types.h" -#include "DNA_scene_types.h" -#include "DNA_object_types.h" -#include "DNA_scriptlink_types.h" -#include "DNA_meta_types.h" -#include "DNA_ika_types.h" +#include "DNA_curve_types.h" +#include "DNA_group_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" -#include "DNA_group_types.h" -#include "DNA_curve_types.h" +#include "DNA_meta_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_scriptlink_types.h" #include "DNA_userdef_types.h" -#include "BLI_blenlib.h" - -#include "BKE_bad_level_calls.h" -#include "BKE_utildefines.h" - -#include "BKE_global.h" -#include "BKE_main.h" +#include "BKE_action.h" #include "BKE_anim.h" +#include "BKE_armature.h" +#include "BKE_bad_level_calls.h" #include "BKE_constraint.h" - +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_ipo.h" +#include "BKE_key.h" #include "BKE_library.h" - +#include "BKE_main.h" +#include "BKE_object.h" #include "BKE_scene.h" #include "BKE_world.h" -#include "BKE_ipo.h" -#include "BKE_ika.h" -#include "BKE_key.h" +#include "BKE_utildefines.h" #include "BPY_extern.h" -#include "BKE_depsgraph.h" +#include "BLI_blenlib.h" + +#include "nla.h" #ifdef WIN32 #else @@ -222,95 +215,6 @@ int object_in_scene(Object *ob, Scene *sce) return 0; } -void sort_baselist(Scene *sce) -{ - topo_sort_baselist(sce); -} - -#if 0 -void old_sort_baselist(Scene *sce) -{ - /* in order of parent and track */ - ListBase tempbase, noparentbase, notyetbase; - Base *base, *test=NULL; - Object *par; - int doit, domore= 0, lastdomore=1; - - /* keep same order when nothing has changed! */ - - while(domore!=lastdomore) { - - lastdomore= domore; - domore= 0; - tempbase.first= tempbase.last= 0; - noparentbase.first= noparentbase.last= 0; - notyetbase.first= notyetbase.last= 0; - - while( (base= sce->base.first) ) { - BLI_remlink(&sce->base, base); - - par= 0; - if(base->object->type==OB_IKA) { - Ika *ika= base->object->data; - par= ika->parent; - } - - if(par || base->object->parent || base->object->track) { - - doit= 0; - if(base->object->parent) doit++; - if(base->object->track) doit++; - - /* Count constraints */ - { - bConstraint *con; - for (con = base->object->constraints.first; con; con=con->next){ - if (constraint_has_target(con)) - doit++; - } - } - - if(par) doit++; - - test= tempbase.first; - while(test) { - - if(test->object==base->object->parent) doit--; - if(test->object==base->object->track) doit--; - if(test->object==par) doit--; - - /* Decrement constraints */ - { - bConstraint *con; - for (con = base->object->constraints.first; con; con=con->next){ - if (test->object == get_constraint_target(con) && test->object!=base->object) - doit--; - } - } - - if(doit==0) break; - test= test->next; - } - - if(test) BLI_insertlink(&tempbase, test, base); - else { - BLI_addhead(&tempbase, base); - domore++; - } - - } - else BLI_addtail(&noparentbase, base); - - } - sce->base= noparentbase; - addlisttolist(&sce->base, &tempbase); - addlisttolist(&sce->base, ¬yetbase); - - } - -} -#endif - void set_scene_bg(Scene *sce) { Base *base; @@ -340,37 +244,34 @@ void set_scene_bg(Scene *sce) } /* sort baselist */ - sort_baselist(sce); + DAG_scene_sort(sce); /* copy layers and flags from bases to objects */ base= G.scene->base.first; while(base) { - - base->object->lay= base->lay; + ob= base->object; + ob->lay= base->lay; /* group patch... */ - base->flag &= ~OB_FROMGROUP; - flag= base->object->flag & OB_FROMGROUP; + base->flag &= ~(OB_FROMGROUP); + flag= ob->flag & (OB_FROMGROUP); base->flag |= flag; - base->object->flag= base->flag; + ob->flag= base->flag; + ob->recalc= OB_RECALC; - base->object->ctime= -1234567.0; /* force ipo to be calculated later */ + ob->ctime= -1234567.0; /* force ipo to be calculated later */ base= base->next; } - - do_all_ipos(); /* layers/materials */ - + // full update + scene_update_for_newframe(sce, sce->lay); + /* do we need FRAMECHANGED in set_scene? */ - if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED); +// if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED); - do_all_keys(); -#ifdef __NLA - do_all_actions(NULL); - rebuild_all_armature_displists(); -#endif - do_all_ikas(); +// do_all_keys(); +// do_all_actions(NULL); } @@ -518,3 +419,41 @@ void scene_select_base(Scene *sce, Base *selbase) sce->basact= selbase; } + +/* applies changes right away */ +void scene_update_for_newframe(Scene *sce, unsigned int lay) +{ + Base *base; + int setcount=0; + + /* object ipos are calculated in where_is_object */ + do_all_data_ipos(); + + if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED); + +// do_all_actions(NULL); + /* so nice, better do it twice */ +// do_all_actions(NULL); + + /* if keys were activated, disable the locks */ + unlock_all_keys(); + + /* for time being; sets otherwise can be cyclic */ + while(sce && setcount<2) { + if(sce->theDag==NULL) + DAG_scene_sort(sce); + + DAG_scene_update_flags(sce, lay); // only stuff that moves + + for(base= sce->base.first; base; base= base->next) { + object_handle_update(base->object); // bke_object.h + + /* only update layer when an ipo */ + if(base->object->ipo && has_ipo_code(base->object->ipo, OB_LAY) ) { + base->lay= base->object->lay; + } + } + sce= sce->set; + setcount++; + } +} |