New! Pose-constraint Ipos now are integrated in NLA. ALso cleaned up the
authorTon Roosendaal <ton@blender.org>
Sat, 9 Jul 2005 19:37:38 +0000 (19:37 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 9 Jul 2005 19:37:38 +0000 (19:37 +0000)
weird disabled code that was hanging out there for ages.

Also cleaned up NLA blending itself, it was copying far too much data
around. Should be three times faster or so... need good test!

And restored Action Baking.

source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/object.c
source/blender/include/nla.h
source/blender/src/editaction.c
source/blender/src/editarmature.c

index 911df2a5998e81a83ccbc8e12c5fffdfa8296ded..f19a0d3971bcba3a71cb14e6b86ba03493e99d71 100644 (file)
@@ -251,10 +251,16 @@ void free_pose_channels(bPose *pose)
 
 static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan)
 {
+       bConstraint *pcon, *con;
+       
        VECCOPY(pchan->loc, chan->loc);
        VECCOPY(pchan->size, chan->size);
        QUATCOPY(pchan->quat, chan->quat);
        pchan->flag= chan->flag;
+       
+       con= chan->constraints.first;
+       for(pcon= pchan->constraints.first; pcon; pcon= pcon->next)
+               pcon->enforce= con->enforce;
 }
 
 /* checks for IK constraint, can do more constraints flags later */
@@ -305,6 +311,7 @@ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode)
 {
        bPoseChannel *dchan;
        const bPoseChannel *schan;
+       bConstraint *dcon, *scon;
        float   dquat[4], squat[4];
        float dstweight;
        int i;
@@ -346,6 +353,9 @@ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode)
                        }
                        dchan->flag |= schan->flag;
                }
+               for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) {
+                       dcon->enforce= dcon->enforce*dstweight + scon->enforce*srcweight;
+               }
        }
 }
 
@@ -423,67 +433,6 @@ void extract_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)
-{
-       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;
-       }
-       
-       /* 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)
-{
-       bConstraint *dcon, *scon;
-
-       if (!src || !dst)
-               return;
-
-       for (dcon = dst->chanbase.first; dcon; dcon=dcon->next){
-               for (scon=src->chanbase.first; scon; scon=scon->next){
-                       if (!strcmp(scon->name, dcon->name))
-                               break;
-               }
-               if (scon){
-                       dcon->enforce = scon->enforce;
-               }
-       }
-}
-#endif
-
 /* Pose should exist, can have any number of channels too (used for constraint) */
 void extract_pose_from_action(bPose *pose, bAction *act, float ctime) 
 {
@@ -508,9 +457,10 @@ void extract_pose_from_action(bPose *pose, bAction *act, float ctime)
                                
                                /* Evaluates and sets the internal ipo value */
                                calc_ipo(ipo, ctime);
-
                                /* This call also sets the pchan flags */
                                execute_ipo((ID*)act, achan->ipo);
+                               
+                               do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
                        }
                }
        }
@@ -532,221 +482,137 @@ static void rest_pose(bPose *pose, int clearflag)
                        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)
+void do_all_actions(Object *ob)
 {
-       Base *base;
-       bPose *apose=NULL;
        bPose *tpose=NULL;
-       Object *ob;
        bActionStrip *strip;
        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;
-
-       while(base) {
-               
-               if(only_this) ob= only_this;
-               else ob = base->object;
 
-               /* Retrieve data from the NLA */
-               if(ob->type==OB_ARMATURE && ob->pose) {
-                       bArmature *arm= ob->data;
-
-                       if(arm->flag & ARM_NO_ACTION) {  // no action set while transform
-                               ;
-                       }
-                       else {
-                               doit=0;
-
-                               /* Clear pose */
-                               if (apose){
-                                       free_pose_channels(apose);
-                                       MEM_freeN(apose);
-                               }
-                               /* Clear pose */
-                               if (tpose){
-                                       free_pose_channels(tpose);
-                                       MEM_freeN(tpose);
-                               }
+       /* Retrieve data from the NLA */
+       if(ob->type==OB_ARMATURE && ob->pose && ob->nlastrips.first) {
+               bArmature *arm= ob->data;
 
-                               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;
+               if(arm->flag & ARM_NO_ACTION) {  // no action set while transform
+                       ;
+               }
+               else {
+                       doit=0;
+
+                       copy_pose(&tpose, ob->pose, 1);
+                       rest_pose(ob->pose, 1);
+                       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));
+                                                                               doit=1;
                                                                        }
                                                                }
                                                        }
+                                               }
 
-                                                       /* Handle repeat */
-                       
-                                                       else if (striptime < 1.0){
-                                                               /* Mod to repeat */
-                                                               striptime*=strip->repeat;
-                                                               striptime = (float)fmod (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;
+                                                       extract_pose_from_action (tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
+                                                       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 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);
-                                                               }
-                                                               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 (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
+                                                               blendfac = stripframe/strip->blendin;
                                                        }
-                                               }                                       
-                                               if (apose){
-                                                       extract_pose_from_pose(ob->pose, apose);
-       #ifdef __NLA_BLENDCON
-                                                       get_constraint_influence_from_pose(ob->pose, apose);
-       #endif
+                                                       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 (ob->pose, tpose, blendfac, strip->mode);
                                                }
-                                       }
-                                       
+                                       }                                       
                                }
-
-                               /* 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;
-                               } 
-                               
                        }
-               }               
-               if(only_this) break;
-               
-               base= base->next;
-               if(base==0 && set==0 && G.scene->set) {
-                       set= 1;
-                       base= G.scene->set->base.first; 
+
+                       /* 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));
+                               doit = 1;
+                       } 
+                       
                }
-               
        }
-
-       if (apose){
-               free_pose_channels(apose);
-               MEM_freeN(apose);
-               apose = NULL;
-       }       
+       
        if (tpose){
                free_pose_channels(tpose);
                MEM_freeN(tpose);
-               apose = NULL;
        }
-
 }
 
index 6338cf45030c0d431d590370357ad64bdd827d72..28981801ebf1e2d6184e5ecc5a1b6d013c42443e 100644 (file)
@@ -936,13 +936,9 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan)
                /* 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*)pchan, ctime);   // ctime doesnt alter objects
                
-               //VECCOPY(bone->size, conOb.size);      // stretchto constraint
-               
                /* Take out of worldspace */
                Mat4MulMat4 (pchan->pose_mat, conOb.obmat, ob->imat);
        }
index 3ace9715c7f06144434599d5c1bc1a5848898477..ab7792aef2c6e834b371a2c0e6d32a0065225290 100644 (file)
@@ -600,7 +600,8 @@ void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
        bConstraintChannel *chan;
        IpoCurve *icu=NULL;
        
-       for (con=conbase->first; con; con=con->next){
+       for (con=conbase->first; con; con=con->next) {
+               con->enforce= 1.0;
                chan = find_constraint_channel(chanbase, con->name);
                if (chan && chan->ipo){
                        calc_ipo(chan->ipo, ctime);
index 5c0d61ae30ab1e65ff1c1c01134dd8ad9863a2ff..b750214ecd7e502604d8c7c4f5d8b5a99f45b235 100644 (file)
@@ -1559,13 +1559,8 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime)
                
                /* Check this constraint only if it has some enforcement */
                if (!(con->flag & CONSTRAINT_DISABLE)) {
-                       /* weird code was here (ton)
-                       if (con->enforce==0.0)
-                               enf = 0.001f;
-                               enf = con->enforce;
-                       */
-                       enf = con->enforce;
-                       
+                       enf = con->enforce;     // value from ipos (from action channels)
+
                        /* Get the targetmat */
                        get_constraint_target_matrix(con, obtype, obdata, tmat, size, ctime);
                        
index d5685f9550ec6150f821050b5247106706130a6e..f07121bd56b17dfe3833bedeafa8a4f39378e7a8 100644 (file)
@@ -41,9 +41,6 @@
  *     __CON_IPO
  *     Support for constraint ipo keys
  *
- *     __NLA_BAKE
- *     Allow users to bake constraints into keyframes
- *
  *     __NLA_ACTION_BY_MOTION_ACTUATOR
  *     New action actuator playback type
  *
@@ -55,7 +52,6 @@
 
 #define __NLA                  
 
-#define __NLA_BAKE                                                     //      Not for release: Not yet fully implemented
 #define __CON_IPO                                                      //      Not for Release: Not yet fully implemented
 //#define __NLA_ACTION_BY_MOTION_ACTUATOR      //      Not for release: Not yet fully implemented
 
index 8754549dd59f992cc69a565f9dbd6e2b4a635549..4e7fced2dbdabb992862a195f74a99319bc32465 100644 (file)
@@ -141,26 +141,24 @@ static void select_poseelement_by_name (char *name, int select)
                break;
        }
 }
-#ifdef __NLA_BAKE
+
 bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
 {
+       bArmature               *arm;
        bAction                 *result=NULL;
        bActionChannel *achan;
+       bAction                 *temp;
+       bPoseChannel    *pchan;
        float                   actlen;
+       int                             oldframe;
        int                             curframe;
        char                    newname[64];
-       bArmature               *arm;
-       Bone                    *bone;
-       float                   oldframe;
-       bAction                 *temp;
-       bPoseChannel *pchan;
 
        if (!act)
                return NULL;
 
        arm = get_armature(armob);
 
-       
        if (G.obedit){
                error ("Actions can't be baked in Edit Mode");
                return NULL;
@@ -194,38 +192,22 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
                /* Apply the object ipo */
                extract_pose_from_action(armob->pose, act, curframe);
 
-//             where_is_armature_time(armob, curframe);
+               where_is_pose(armob);
                
                /* For each channel: set quats and locs if channel is a bone */
                for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){
 
-                       bone = get_named_bone(arm, pchan->name);
-                       if (bone){
-                               float tmp_quat[4], tmp_loc[3], tmp_size[3];
-                               QUATCOPY(tmp_quat, pchan->quat);
-                               VECCOPY(tmp_loc, pchan->loc);
-                               VECCOPY(tmp_size, pchan->size);
-
-//                             Mat4ToQuat(pchan->obmat, pchan->quat);
-//                             Mat4ToSize(pchan->obmat, pchan->size);
-//                             VECCOPY(pchan->loc, pchan->obmat[3]);
-
-                               /* Apply to keys */
-                               set_action_key_time (result, pchan, AC_QUAT_X, 1, curframe);
-                               set_action_key_time (result, pchan, AC_QUAT_Y, 1, curframe);
-                               set_action_key_time (result, pchan, AC_QUAT_Z, 1, curframe);
-                               set_action_key_time (result, pchan, AC_QUAT_W, 1, curframe);
-                               set_action_key_time (result, pchan, AC_LOC_X, 1, curframe);
-                               set_action_key_time (result, pchan, AC_LOC_Y, 1, curframe);
-                               set_action_key_time (result, pchan, AC_LOC_Z, 1, curframe);
-                               set_action_key_time (result, pchan, AC_SIZE_X, 1, curframe);
-                               set_action_key_time (result, pchan, AC_SIZE_Y, 1, curframe);
-                               set_action_key_time (result, pchan, AC_SIZE_Z, 1, curframe);
-
-                               QUATCOPY(pchan->quat, tmp_quat);
-                               VECCOPY(pchan->loc, tmp_loc);
-                               VECCOPY(pchan->size, tmp_size);
-                       }
+                       /* Apply to keys */
+                       set_action_key_time (result, pchan, AC_QUAT_X, 1, curframe);
+                       set_action_key_time (result, pchan, AC_QUAT_Y, 1, curframe);
+                       set_action_key_time (result, pchan, AC_QUAT_Z, 1, curframe);
+                       set_action_key_time (result, pchan, AC_QUAT_W, 1, curframe);
+                       set_action_key_time (result, pchan, AC_LOC_X, 1, curframe);
+                       set_action_key_time (result, pchan, AC_LOC_Y, 1, curframe);
+                       set_action_key_time (result, pchan, AC_LOC_Z, 1, curframe);
+                       set_action_key_time (result, pchan, AC_SIZE_X, 1, curframe);
+                       set_action_key_time (result, pchan, AC_SIZE_Y, 1, curframe);
+                       set_action_key_time (result, pchan, AC_SIZE_Z, 1, curframe);
                }
        }
 
@@ -241,9 +223,16 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        notice ("Made a new action named \"%s\"", newname);
        G.scene->r.cfra = oldframe;
        armob->action = temp;
+               
+       /* restore */
+       extract_pose_from_action(armob->pose, act, G.scene->r.cfra);
+       where_is_pose(armob);
+       
+       allqueue(REDRAWACTION, 1);
+       
        return result;
 }
-#endif
+
 
 void select_actionchannel_by_name (bAction *act, char *name, int select)
 {
index 8e0067dcb84cdd63099248fffa4c90fad464cf24..528dbefe2fbee5b131da72de8931186c8a4582b2 100644 (file)
@@ -2071,7 +2071,7 @@ void clear_armature(Object *ob, char mode)
                        }
                }
        }
-       /* no DAG flush, this will execture the action again */
+       /* no DAG flush, this will execute the action again */
        where_is_pose (ob);
 }