Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

pose.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  POSE.C                                                                                                                                                              */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                    */
00005 /*  Description: Bone hierarchy implementation.                                                 .                               */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #pragma message ("could optimize a name binded setPose by caching the mapping from motionpath[i] to joint[j]")
00023 
00024 #include <assert.h>
00025 #include <string.h>
00026 
00027 #include "ram.h"
00028 #include "errorlog.h"
00029 #include "Pose.h"
00030 #include "StrBlock.h"
00031 
00032 #define GE_POSE_STARTING_JOINT_COUNT (1)
00033 
00034 
00035 /* this object maintains a hierarchy of joints.
00036    the hierarchy is stored as an array of joints, with each joint having an number
00037    that is it's parent's index in the array.  
00038    This code assumes:  
00039    **The parent's index is always smaller than the child**
00040 */
00041 
00042 typedef struct gePose_Joint
00043 {
00044         int                      ParentJoint;           // parent of path
00045         geXForm3d    *Transform;                // matrix for path      (pointer into TransformArray)
00046         geQuaternion Rotation;                  // quaternion representation for orientation of above Transform
00047 
00048         geVec3d          UnscaledAttachmentTranslation; 
00049                                         // point of Attachment to parent (in parent frame of ref) **Unscaled
00050         geQuaternion AttachmentRotation;// rotation of attachement to parent (in parent frame of ref)
00051         geXForm3d    AttachmentTransform;       //------------
00052 
00053         geVec3d          LocalTranslation;      // translation relative to attachment 
00054         geQuaternion LocalRotation;             // rotation relative to attachment 
00055 
00056         geBoolean    Touched;                   // if this joint has been touched and needs recomputation
00057         geBoolean    NoAttachmentRotation; // GE_TRUE if there is no attachment rotation.
00058         int                      Covered;                       // if joint has been 100% set (no blending)
00059 } gePose_Joint;                                         // structure to bind a name and a path for a joint
00060 
00061 typedef struct gePose
00062 {
00063         int                               JointCount;   // number of joints in the motion
00064         int32                     NameChecksum; // checksum based on joint names and list order
00065         geBoolean                 Touched;              // if any joint has been touched & needs recomputation  
00066         geStrBlock               *JointNames;
00067         geVec3d                   Scale;                // current scaling. Used for scaling motion samples
00068 
00069         geBoolean                 Slave;                        // if pose is 'slaved' to parent -vs- attached.
00070         int                               SlaveJointIndex;      // index of 'slaved' joint
00071         gePose                   *Parent;               
00072         gePose_Joint      RootJoint;            
00073         geXForm3d                 ParentsLastTransform; // Compared to parent's transform to see if it changed: recompute is needed
00074         geXForm3d                 RootTransform;
00075         geXFArray                *TransformArray;       
00076         gePose_Joint     *JointArray;
00077         int                               OnlyThisJoint;                // update only this joint (and it's parents) if this is >0
00078 } gePose;
00079 
00080 
00081 
00082 static void gePose_ReattachTransforms(gePose *P)
00083 {
00084         int XFormCount;
00085         int JointCount;
00086         geXForm3d *XForms;
00087         int i;
00088 
00089         assert( P != NULL );
00090 
00091         JointCount = P->JointCount;
00092         if (JointCount > 0)
00093                 {
00094                         assert( P->TransformArray != NULL );
00095 
00096                         XForms = geXFArray_GetElements(P->TransformArray,&XFormCount);
00097                         
00098                         assert( XForms != NULL );
00099                         assert( XFormCount == JointCount );
00100                         
00101                         for (i=0; i<JointCount; i++)
00102                                 {
00103                                         P->JointArray[i].Transform=&(XForms[i]);
00104                                 }
00105                 }
00106         P->RootJoint.Transform = &(P->RootTransform);
00107 }
00108         
00109 
00110 static const gePose_Joint *gePose_JointByIndex(const gePose *P, int Index)
00111 {
00112         assert( P != NULL );
00113         assert( (Index >=0)                 || (Index==(GE_POSE_ROOT_JOINT)));
00114         assert( (Index < P->JointCount)     || (Index==(GE_POSE_ROOT_JOINT)));
00115 
00116         if (Index == GE_POSE_ROOT_JOINT)
00117                 {
00118                         return &(P->RootJoint);
00119                 }
00120         else
00121                 {
00122                         return &(P->JointArray[Index]);
00123                 }
00124 }
00125 
00126 static void GENESISCC gePose_SetAttachmentRotationFlag( gePose_Joint *Joint)
00127 {
00128         geQuaternion Q = Joint->AttachmentRotation;
00129 #define GE_POSE_ROTATION_THRESHOLD (0.0001)  // if the rotation is closer than this to zero for
00130                                                                                      // quaterion elements X,Y,Z -> no rotation computed
00131         if (     (  (Q.X<GE_POSE_ROTATION_THRESHOLD) && (Q.X>-GE_POSE_ROTATION_THRESHOLD) ) 
00132                   && (  (Q.Y<GE_POSE_ROTATION_THRESHOLD) && (Q.Y>-GE_POSE_ROTATION_THRESHOLD) ) 
00133                   && (  (Q.Z<GE_POSE_ROTATION_THRESHOLD) && (Q.Z>-GE_POSE_ROTATION_THRESHOLD) )  )
00134                 {
00135                         Joint->NoAttachmentRotation = GE_TRUE;
00136                 }
00137         else
00138                 {
00139                         Joint->NoAttachmentRotation = GE_FALSE;
00140                 }
00141 }
00142 
00143 static void GENESISCC gePose_InitializeJoint(gePose_Joint *Joint, int ParentJointIndex, const geXForm3d *Attachment)
00144 {
00145         assert( Joint != NULL );
00146         
00147         Joint->ParentJoint = ParentJointIndex;
00148         if (Attachment != NULL)
00149                 {
00150                         geQuaternion_FromMatrix(Attachment,&(Joint->AttachmentRotation));
00151                         Joint->AttachmentTransform = *Attachment;
00152                         Joint->UnscaledAttachmentTranslation = Joint->AttachmentTransform.Translation;
00153                 }
00154         else
00155                 {
00156                         geQuaternion_SetNoRotation(&(Joint->AttachmentRotation));
00157                         geXForm3d_SetIdentity(&(Joint->AttachmentTransform));
00158                         Joint->UnscaledAttachmentTranslation = Joint->AttachmentTransform.Translation;
00159                 }
00160 
00161         geQuaternion_SetNoRotation(&(Joint->LocalRotation));
00162         
00163         geXForm3d_SetIdentity(Joint->Transform);
00164         geQuaternion_SetNoRotation(&(Joint->Rotation));
00165         
00166         geVec3d_Set( (&Joint->LocalTranslation),0.0f,0.0f,0.0f);
00167         geQuaternion_SetNoRotation(&(Joint->LocalRotation));
00168         Joint->Touched = GE_TRUE;               
00169         gePose_SetAttachmentRotationFlag(Joint);
00170 }
00171 
00172 
00173 
00174 gePose *GENESISCC gePose_Create(void)
00175 {
00176         gePose *P;
00177 
00178         P = GE_RAM_ALLOCATE_STRUCT(gePose);
00179 
00180         if ( P == NULL )
00181                 {
00182                         geErrorLog_Add(ERR_POSE_CREATE_ENOMEM, NULL);
00183                         goto PoseCreateFailure;
00184                 }
00185         P->JointCount = 0;
00186         P->OnlyThisJoint = GE_POSE_ROOT_JOINT-1;                
00187         P->JointNames = geStrBlock_Create();
00188         P->Touched = GE_FALSE;
00189         if ( P->JointNames == NULL )
00190                 {
00191                         geErrorLog_Add(ERR_POSE_CREATE_ENOMEM, NULL);
00192                         goto PoseCreateFailure;
00193                 }
00194         P->JointArray = GE_RAM_ALLOCATE_STRUCT( gePose_Joint );
00195         if (P->JointArray == NULL)
00196                 {
00197                         geErrorLog_Add(ERR_POSE_CREATE_ENOMEM, NULL);
00198                         goto PoseCreateFailure;
00199                 }
00200         P->TransformArray=NULL;
00201 
00202         P->Slave = GE_FALSE;
00203         P->Parent = NULL;
00204         gePose_ReattachTransforms(P);
00205         gePose_InitializeJoint(&(P->RootJoint),GE_POSE_ROOT_JOINT,NULL);
00206 
00207         P->Scale.X = P->Scale.Y = P->Scale.Z = 1.0f;
00208         return P;
00209         PoseCreateFailure:
00210         if (P!=NULL)
00211                 {
00212                         if (P->JointNames != NULL)
00213                                 geStrBlock_Destroy(&(P->JointNames));
00214                         if (P->JointArray != NULL)
00215                                 geRam_Free(P->JointArray);
00216                         geRam_Free(P);
00217                 }
00218         return NULL;
00219 }
00220 
00221 void GENESISCC gePose_Destroy(gePose **PP)
00222 {
00223         assert(PP   != NULL );
00224         assert(*PP  != NULL );
00225 
00226         assert( (*PP)->JointNames != NULL );
00227         assert( geStrBlock_GetCount((*PP)->JointNames) == (*PP)->JointCount );
00228         geStrBlock_Destroy( &( (*PP)->JointNames ) );
00229         if ((*PP)->TransformArray!=NULL)
00230                 {
00231                         geXFArray_Destroy(&( (*PP)->TransformArray) );
00232                 }
00233         if ((*PP)->JointArray != NULL)
00234                 geRam_Free((*PP)->JointArray);
00235         geRam_Free( *PP );
00236 
00237         *PP = NULL;
00238 }
00239 
00240 // uses J->LocalRotation and J->LocalTranslation to compute 
00241 //    J->Rotation,J->Translation and J->Transform
00242 static void GENESISCC gePose_JointRelativeToParent(
00243                  const gePose_Joint *Parent,
00244                  gePose_Joint *J)
00245 {
00246         
00247         #if 0
00248                 // the math in clearer (but slower) matrix form.
00249                 // W = PAK
00250                 geXForm3d X;
00251                 geXForm3d K;
00252 
00253                 geQuaternion_ToMatrix(&(J->LocalRotation),&K);
00254                 K.Translation = J->LocalTranslation;
00255 
00256                 geXForm3d_Multiply((Parent->Transform),&(J->AttachmentTransform),&X);
00257                 geXForm3d_Multiply(&X,&(K),J->Transform);
00258                 
00259                 J->LocalTranslation = K.Translation;
00260                 geQuaternion_FromMatrix(J->Transform,&(J->LocalRotation));
00261 
00262         #endif
00263 
00264 
00265         geVec3d *Translation = &(J->Transform->Translation);
00266         if (J->NoAttachmentRotation != GE_FALSE)
00267                 {
00268                         //    ( no attachment rotation )
00269                         //ROTATION:
00270                         // concatenate local rotation to parent rotation for complete rotation
00271                         geQuaternion_Multiply(&(Parent->Rotation), &(J->LocalRotation), &(J->Rotation));
00272                         
00273                         geQuaternion_ToMatrix(&(J->Rotation), (J->Transform));
00274                         //TRANSLATION:
00275                         geVec3d_Add(&(J->LocalTranslation),&(J->AttachmentTransform.Translation),Translation);
00276                         geXForm3d_Transform((Parent->Transform),Translation,Translation);
00277                 }
00278         else
00279                 {
00280                         //  (there is an attachment rotation)
00281                         
00282                         geQuaternion BaseRotation; // attachement transform applied to the parent transform:
00283                         //ROTATION:
00284                         // concatenate attachment rotation to parent rotation for base rotation
00285                         geQuaternion_Multiply(&(Parent->Rotation),&(J->AttachmentRotation),&BaseRotation);
00286                         // concatenate base rotation with local rotation for complete rotation
00287                         geQuaternion_Multiply(&BaseRotation, &(J->LocalRotation), &(J->Rotation));
00288 
00289                         geQuaternion_ToMatrix(&(J->Rotation), (J->Transform));
00290 
00291                         //TRANSLATION:
00292                         geXForm3d_Transform(&(J->AttachmentTransform),&(J->LocalTranslation),Translation);
00293                         geXForm3d_Transform((Parent->Transform),Translation,Translation);
00294                 }
00295 }
00296 
00297 
00298 geBoolean GENESISCC gePose_Attach(gePose *Slave, int SlaveBoneIndex,
00299                                   gePose *Master, int MasterBoneIndex, 
00300                                   const geXForm3d *Attachment)
00301 {
00302         gePose *P;
00303         P = Master;
00304 
00305         assert( Slave != NULL );
00306         assert( Master != NULL );
00307         assert( MasterBoneIndex >= 0);
00308         assert( MasterBoneIndex < Master->JointCount);
00309         assert( Attachment != NULL );
00310         assert( Master != Slave );
00311 
00312 
00313         assert( (SlaveBoneIndex >=0)                 || (SlaveBoneIndex==(GE_POSE_ROOT_JOINT)));
00314         assert( (SlaveBoneIndex < Slave->JointCount) || (SlaveBoneIndex==(GE_POSE_ROOT_JOINT)));
00315 
00316         while (P!=NULL)
00317                 {
00318                         if (P==Slave)
00319                                 {
00320                                         geErrorLog_Add(-1, NULL);//FIXME
00321                                         return GE_FALSE;
00322                                 }
00323                         P=P->Parent;
00324                 }
00325 
00326         Slave->SlaveJointIndex = SlaveBoneIndex;
00327         Slave->Parent = Master;
00328         if (SlaveBoneIndex == GE_POSE_ROOT_JOINT)
00329                 {
00330                         Slave->Slave = GE_FALSE;
00331                 }
00332         else
00333                 {
00334                         Slave->Slave = GE_TRUE;
00335                 }
00336 
00337         gePose_InitializeJoint(&(Slave->RootJoint),MasterBoneIndex,Attachment);
00338         Slave->Touched = GE_TRUE;
00339         Slave->ParentsLastTransform = *(Master->RootJoint.Transform);
00340         
00341         return GE_TRUE;
00342 }
00343 
00344 
00345 void GENESISCC gePose_Detach(gePose *P)
00346 {
00347         P->Parent = NULL;
00348         P->Slave = GE_FALSE;
00349         gePose_InitializeJoint(&(P->RootJoint),GE_POSE_ROOT_JOINT,NULL);
00350 }
00351 
00352 
00353 static geBoolean GENESISCC gePose_TransformCompare(const geXForm3d *T1, const geXForm3d *T2)
00354 {
00355         if (T1->AX != T2->AX) return GE_FALSE;
00356         if (T1->BX != T2->BX) return GE_FALSE;
00357         if (T1->CX != T2->CX) return GE_FALSE;
00358         if (T1->AY != T2->AY) return GE_FALSE;
00359         if (T1->BY != T2->BY) return GE_FALSE;
00360         if (T1->CY != T2->CY) return GE_FALSE;
00361         if (T1->AZ != T2->AZ) return GE_FALSE;
00362         if (T1->BZ != T2->BZ) return GE_FALSE;
00363         if (T1->CZ != T2->CZ) return GE_FALSE;
00364         
00365         if (T1->Translation.X != T2->Translation.X) return GE_FALSE;
00366         if (T1->Translation.Y != T2->Translation.Y) return GE_FALSE;
00367         if (T1->Translation.Z != T2->Translation.Z) return GE_FALSE;
00368         return GE_TRUE;
00369 }
00370         
00371         
00372 static void GENESISCC gePose_UpdateRecursively(gePose *P,int Joint)
00373 {
00374         gePose_Joint *J;
00375         assert( P != NULL );
00376         assert( Joint >= GE_POSE_ROOT_JOINT );
00377 
00378         J=&(P->JointArray[Joint]);
00379 
00380         assert( J->ParentJoint < Joint);
00381 
00382         if (J->ParentJoint != GE_POSE_ROOT_JOINT)
00383                 gePose_UpdateRecursively(P,J->ParentJoint);
00384 
00385         gePose_JointRelativeToParent(gePose_JointByIndex(P, J->ParentJoint) ,J);
00386 }
00387 
00388 //  updates a node if node->touched or if any of it's parents have been touched.
00389 //  returns GE_TRUE if any updates were made.
00390 static void GENESISCC gePose_UpdateRelativeToParent(gePose *P)
00391 {
00392         int i;
00393         gePose_Joint *J;
00394         const gePose_Joint *Parent;
00395         assert( P != NULL );
00396         
00397         if ( P->Parent != NULL )
00398                 {
00399                         gePose_UpdateRelativeToParent(P->Parent);
00400 // Wismerhill Attach Fix RF064
00401                         if (gePose_TransformCompare(
00402                                                 (P->Parent->RootJoint.Transform),&(P->ParentsLastTransform)) == GE_FALSE)
00403                                 {
00404                                         P->Touched = GE_TRUE;
00405                                         P->RootJoint.Touched = GE_TRUE;  // bubble touched down entire hierarchy
00406                                         P->ParentsLastTransform = *(P->Parent->RootJoint.Transform);
00407                                 }
00408                                 
00409                         if (P->Slave == GE_FALSE)
00410                                 {
00411                                         Parent = gePose_JointByIndex(P->Parent, P->RootJoint.ParentJoint);
00412                                         gePose_JointRelativeToParent(Parent,&(P->RootJoint));
00413                                 }
00414                         else
00415                                 {
00416                                         geXForm3d_SetIdentity(P->RootJoint.Transform);
00417                                         geQuaternion_SetNoRotation(&(P->RootJoint.Rotation));
00418                                 }
00419                 }
00420         else
00421                 {
00422                         // No parent.  RootJoint is relative to nothing.
00423                         J = &(P->RootJoint);
00424                         if (J->Touched)
00425                                 {
00426                                         geQuaternion_Multiply(&(J->AttachmentRotation),&(J->LocalRotation),&(J->Rotation));
00427                                         geQuaternion_ToMatrix(&(J->Rotation), (J->Transform));
00428                                         geXForm3d_Transform(&(J->AttachmentTransform),&(J->LocalTranslation),&(J->Transform->Translation));
00429                                 }
00430                 }
00431 
00432 
00433         if (P->Touched == GE_FALSE)
00434                 {
00435                         return;
00436                 }
00437 
00438 
00439         if (P->OnlyThisJoint>=GE_POSE_ROOT_JOINT)
00440                 {
00441                         gePose_UpdateRecursively(P,P->OnlyThisJoint);
00442                 }
00443         else
00444                 {
00445                         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
00446                                 {
00447                                         assert( J->ParentJoint < i);
00448 
00449                                         Parent = gePose_JointByIndex(P, J->ParentJoint);
00450                                         if (J->Touched == GE_TRUE)
00451                                                 {
00452                                                         gePose_JointRelativeToParent(Parent ,J);
00453                                                 }
00454                                         else
00455                                                 {
00456                                                         if (Parent->Touched)
00457                                                                 {
00458                                                                         J->Touched = GE_TRUE;
00459                                                                         gePose_JointRelativeToParent(Parent,J);
00460                                                                 }
00461                                                 }
00462                                 }
00463                         // touched flags don't mean anything when recursing backwards.  
00464                         P->RootJoint.Touched = GE_FALSE;
00465                         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
00466                                 {
00467                                         J->Touched = GE_FALSE;
00468                                 }
00469                 }
00470 
00471         if (P->Slave != GE_FALSE)
00472                 {
00473                         geXForm3d SlavedJointInverse;
00474                         geXForm3d FullSlaveTransform;
00475                         geXForm3d *MasterTransform;
00476                         geXForm3d MasterAttachment;
00477                         
00478                         MasterTransform = (P->Parent->JointArray[P->RootJoint.ParentJoint].Transform);
00479                         geXForm3d_GetTranspose((P->JointArray[P->SlaveJointIndex].Transform), &SlavedJointInverse);
00480 
00481                         geQuaternion_ToMatrix(&(P->RootJoint.AttachmentRotation), &MasterAttachment);
00482                         //MasterAttachment.Translation = P->RootJoint.AttachmentTranslation;
00483                         MasterAttachment.Translation = P->RootJoint.AttachmentTransform.Translation;
00484 
00485                         geXForm3d_Multiply(MasterTransform,&MasterAttachment,&FullSlaveTransform);
00486                         
00487                         *(P->RootJoint.Transform) = FullSlaveTransform;
00488                         
00489                         geXForm3d_Multiply(&FullSlaveTransform,&SlavedJointInverse,&FullSlaveTransform);
00490 
00491                         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
00492                                 {
00493                                         geXForm3d_Multiply(&FullSlaveTransform,
00494                                                                                 (P->JointArray[i].Transform),
00495                                                                                 (P->JointArray[i].Transform));
00496                                 }
00497                         
00498                 }
00499         P->Touched = GE_FALSE;
00500 }       
00501 
00502 
00503 geBoolean GENESISCC gePose_FindNamedJointIndex(const gePose *P, const char *JointName, int *Index)
00504 {
00505         int i;
00506 
00507         assert( P != NULL );
00508         assert( Index!= NULL );
00509         if (JointName == NULL )
00510                 return GE_FALSE;
00511 
00512         for (i=0; i<P->JointCount; i++)
00513                 {
00514                         const char *NthName = geStrBlock_GetString(P->JointNames,i);
00515                         assert( NthName!= NULL );
00516                         if ( strcmp(JointName,NthName)==0 )
00517                                 {
00518                                         *Index = i;
00519                                         return GE_TRUE;
00520                                 }       
00521                 }
00522         return GE_FALSE;
00523 }
00524         
00525 
00526 geBoolean GENESISCC gePose_AddJoint(
00527         gePose *P,
00528         int ParentJointIndex,
00529         const char *JointName,
00530         const geXForm3d *Attachment,
00531         int *JointIndex)
00532 {
00533         int JointCount;
00534         gePose_Joint *Joint;
00535 
00536         assert(  P != NULL );
00537         assert( JointIndex != NULL );
00538         assert( P->JointCount >= 0 );
00539         assert( (ParentJointIndex == GE_POSE_ROOT_JOINT) || 
00540                         ((ParentJointIndex >=0) && (ParentJointIndex <P->JointCount) ) );
00541 
00542         // Duplicate names ARE allowed
00543 
00544         JointCount = P->JointCount;
00545         {
00546                 gePose_Joint *NewJoints;
00547                 NewJoints = GE_RAM_REALLOC_ARRAY(P->JointArray,gePose_Joint,JointCount+1);
00548                 if (NewJoints == NULL)
00549                         {
00550                                 geErrorLog_Add(ERR_POSE_ADDJOINT_ENOMEM, NULL);
00551                                 return GE_FALSE;
00552                         }
00553                 P->JointArray = NewJoints;
00554         }
00555         
00556         assert( P->JointNames != NULL );
00557         assert( geStrBlock_GetCount(P->JointNames) == P->JointCount );
00558 
00559         if (geStrBlock_Append( &(P->JointNames), (JointName==NULL)?"":JointName )==GE_FALSE)
00560                 {
00561                         geErrorLog_Add(ERR_POSE_ADDJOINT_ENOMEM, NULL);
00562                         return GE_FALSE;
00563                 }
00564         
00565 
00566         {
00567                 geXFArray *NewXFA;
00568                 NewXFA = geXFArray_Create(JointCount+1);
00569                 if (NewXFA == NULL)
00570                         {
00571                                 geErrorLog_Add(ERR_POSE_ADDJOINT_ENOMEM, NULL);
00572                                 return GE_FALSE;
00573                         }
00574                 if (P->TransformArray != NULL)
00575                         {
00576                                 geXFArray_Destroy(&(P->TransformArray));
00577                         }
00578                 P->TransformArray = NewXFA;
00579         }
00580 
00581         P->JointCount = JointCount+1;
00582         gePose_ReattachTransforms(P);
00583         
00584         Joint = &( P->JointArray[JointCount] );
00585         gePose_InitializeJoint(Joint,ParentJointIndex, Attachment);
00586         P->Touched = GE_TRUE;
00587 
00588         *JointIndex = JointCount;
00589 
00590         P->NameChecksum = geStrBlock_GetChecksum( P->JointNames );
00591         return GE_TRUE;
00592 }
00593 
00594 void GENESISCC gePose_GetJointAttachment(const gePose *P,int JointIndex, geXForm3d *AttachmentTransform)
00595 {
00596         assert( P != NULL );
00597         assert( AttachmentTransform != NULL );
00598         {
00599                 const gePose_Joint *J;
00600                 J = gePose_JointByIndex(P, JointIndex);
00601                 *AttachmentTransform = J->AttachmentTransform;
00602         }
00603 }
00604 
00605 void GENESISCC gePose_SetJointAttachment(gePose *P,
00606         int JointIndex, 
00607         const geXForm3d *AttachmentTransform)
00608 {
00609         assert( P != NULL );
00610         assert( AttachmentTransform != NULL );
00611         {
00612                 gePose_Joint *J;
00613                 J = (gePose_Joint *)gePose_JointByIndex(P, JointIndex);
00614                 geQuaternion_FromMatrix(AttachmentTransform,&(J->AttachmentRotation));
00615                 J->Touched = GE_TRUE;
00616                 J->AttachmentTransform = *AttachmentTransform;
00617                 J->UnscaledAttachmentTranslation = J->AttachmentTransform.Translation;
00618                 gePose_SetAttachmentRotationFlag(J);
00619         }
00620         P->Touched = GE_TRUE;
00621 }
00622 
00623 void GENESISCC gePose_GetJointTransform(const gePose *P, int JointIndex,geXForm3d *Transform)
00624 {
00625         assert( P != NULL );
00626         assert( Transform != NULL );
00627         
00628         gePose_UpdateRelativeToParent((gePose *)P);
00629         
00630         {
00631                 const gePose_Joint *J;
00632                 J = gePose_JointByIndex(P, JointIndex);
00633                 *Transform = *(J->Transform);
00634         }
00635 }
00636 
00637 void GENESISCC gePose_GetJointLocalTransform(const gePose *P, int JointIndex,geXForm3d *Transform)
00638 {
00639         assert( P != NULL );
00640         assert( Transform != NULL );
00641         {
00642                 const gePose_Joint *J;
00643                 J = gePose_JointByIndex(P, JointIndex);
00644                 geQuaternion_ToMatrix(&(J->LocalRotation), Transform);
00645                 Transform->Translation = J->LocalTranslation;
00646         }
00647 }
00648 
00649 void GENESISCC gePose_SetJointLocalTransform(gePose *P, int JointIndex,const geXForm3d *Transform)
00650 {
00651         assert( P != NULL );
00652         assert( Transform != NULL );
00653         {
00654                 gePose_Joint *J;
00655                 J = (gePose_Joint *)gePose_JointByIndex(P, JointIndex);
00656                 geQuaternion_FromMatrix(Transform,&(J->LocalRotation));
00657                 J->LocalTranslation = Transform->Translation;
00658                 J->Touched = GE_TRUE;
00659         }
00660         P->Touched = GE_TRUE;
00661 }
00662 
00663 int GENESISCC gePose_GetJointCount(const gePose *P)
00664 {
00665         assert( P != NULL );
00666         assert( P->JointCount >= 0 );
00667         
00668         return P->JointCount;
00669 }
00670 
00671 geBoolean GENESISCC gePose_MatchesMotionExactly(const gePose *P, const geMotion *M)
00672 {
00673         if (geMotion_HasNames(M) != GE_FALSE)
00674                 {
00675                         if (geMotion_GetNameChecksum(M) == P->NameChecksum)
00676                                 return GE_TRUE;
00677                         else
00678                                 return GE_FALSE;
00679                 }
00680         return GE_FALSE;
00681 }
00682 
00683 // sets pose to it's base position: applies no modifier to the joints: only
00684 // it's attachment positioning is used.
00685 void GENESISCC gePose_Clear(gePose *P,const geXForm3d *Transform)
00686 {
00687         int i;
00688         gePose_Joint *J;
00689         
00690         assert( P != NULL );
00691         assert( P->JointCount >= 0 );
00692         P->OnlyThisJoint = GE_POSE_ROOT_JOINT-1;                // calling this function disables one-joint optimizations
00693         if (P->Parent==NULL)
00694                 {
00695                         if (Transform!=NULL)
00696                                 {
00697                                         geQuaternion_FromMatrix(Transform,&(P->RootJoint.LocalRotation));
00698                                         P->RootJoint.LocalTranslation = Transform->Translation;
00699                                 }
00700                         P->RootJoint.Touched = GE_TRUE;
00701                 }
00702                         
00703         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
00704                 {
00705                         geVec3d_Set( (&J->LocalTranslation),0.0f,0.0f,0.0f);
00706                         geQuaternion_SetNoRotation(&(J->LocalRotation));
00707                         assert( J->ParentJoint < i);
00708                         P->Touched = GE_TRUE;
00709                 }       
00710         P->Touched = GE_TRUE;
00711 }       
00712 
00713 void GENESISCC gePose_SetMotion(gePose *P, const geMotion *M, geFloat Time,
00714                                                         const geXForm3d *Transform)
00715 {
00716         geBoolean NameBinding;
00717         int i;
00718         gePose_Joint *J;
00719         geXForm3d RootTransform;
00720         
00721         assert( P != NULL );
00722 
00723         P->OnlyThisJoint = GE_POSE_ROOT_JOINT-1;                // calling this function disables one-joint optimizations
00724 
00725         if (P->Parent==NULL)
00726                 {
00727                         geBoolean SetRoot = GE_FALSE;
00728                         if (geMotion_GetTransform(M,Time,&RootTransform)!=GE_FALSE)
00729                                 {
00730                                         SetRoot = GE_TRUE;
00731 
00732                                         if ( Transform != NULL )
00733                                                 {
00734                                                         geXForm3d_Multiply(Transform,&RootTransform,&RootTransform);
00735                                                 }
00736                                 }
00737                         else
00738                                 {
00739                                         if ( Transform != NULL )
00740                                                 {
00741                                                         SetRoot = GE_TRUE;
00742                                                         RootTransform = *Transform;
00743                                                 }
00744                                 }
00745 
00746                         if (SetRoot != GE_FALSE)
00747                                 {
00748                                         geQuaternion_FromMatrix(&RootTransform,&(P->RootJoint.LocalRotation));
00749                                         P->RootJoint.LocalTranslation = RootTransform.Translation;
00750                                         P->RootJoint.Touched = GE_TRUE;
00751                                 }
00752                 }
00753 
00754         if (M==NULL)
00755                 {
00756                         return;
00757                 }
00758 
00759         if (gePose_MatchesMotionExactly(P,M)==GE_TRUE)
00760                 NameBinding = GE_FALSE;
00761         else
00762                 NameBinding = GE_TRUE;
00763 
00764         P->Touched = GE_TRUE;
00765         #pragma message("could optimize this by looping two ways (min(jointcount,pathcount))")
00766         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
00767                 {
00768                         //gePath *JointPath;
00769                         if (NameBinding == GE_FALSE)
00770                                 {
00771                                         geMotion_SampleChannels(M,i,Time,&(J->LocalRotation),&(J->LocalTranslation));
00772 
00773                                         //JointPath = geMotion_GetPath(M,i);
00774                                         //assert( JointPath != NULL );
00775                                 }
00776                         else
00777                                 {
00778                                         if (geMotion_SampleChannelsNamed(M,
00779                                                 geStrBlock_GetString(P->JointNames,i),
00780                                                 Time,&(J->LocalRotation),&(J->LocalTranslation))==GE_FALSE)
00781                                                 continue;
00782 
00783                                 }
00784                         J->Touched = GE_TRUE;
00785                         J->LocalTranslation.X *= P->Scale.X;
00786                         J->LocalTranslation.Y *= P->Scale.Y;
00787                         J->LocalTranslation.Z *= P->Scale.Z;
00788                 }
00789 }
00790 
00791 static void GENESISCC gePose_SetMotionForABoneRecursion(gePose *P, const geMotion *M, geFloat Time,
00792                                                         int BoneIndex,geBoolean NameBinding)
00793 {
00794         gePose_Joint *J;
00795         geBoolean Touched = GE_FALSE;
00796         assert(P!=NULL);
00797         assert(M!=NULL);
00798         assert( BoneIndex >= 0);
00799 
00800         J=&(P->JointArray[BoneIndex]);
00801 
00802         if (NameBinding == GE_FALSE)
00803                 {
00804                         geMotion_SampleChannels(M,BoneIndex,Time,&(J->LocalRotation),&(J->LocalTranslation));
00805                         Touched = GE_TRUE;
00806                 }
00807         else
00808                 {
00809                         if (geMotion_SampleChannelsNamed(M,
00810                                 geStrBlock_GetString(P->JointNames,BoneIndex),
00811                                 Time,&(J->LocalRotation),&(J->LocalTranslation))!=GE_FALSE)
00812                                 Touched = GE_TRUE;
00813                 }
00814         if (Touched != GE_FALSE)
00815                 {
00816                         J->Touched = GE_TRUE;
00817                         J->LocalTranslation.X *= P->Scale.X;
00818                         J->LocalTranslation.Y *= P->Scale.Y;
00819                         J->LocalTranslation.Z *= P->Scale.Z;
00820                 }
00821         if (J->ParentJoint != GE_POSE_ROOT_JOINT)
00822                 gePose_SetMotionForABoneRecursion(P,M,Time,J->ParentJoint,NameBinding);
00823         
00824 }
00825 
00826 void GENESISCC gePose_SetMotionForABone(gePose *P, const geMotion *M, geFloat Time,
00827                                                         const geXForm3d *Transform,int BoneIndex)
00828 {
00829         geBoolean NameBinding;
00830         geXForm3d RootTransform;
00831         
00832         assert( P != NULL );
00833         //assert( M != NULL );
00834         P->OnlyThisJoint = BoneIndex;           // calling this function enables single-joint optimizations
00835         
00836         if (P->Parent==NULL)
00837                 {
00838                         geBoolean SetRoot = GE_FALSE;
00839                         if (geMotion_GetTransform(M,Time,&RootTransform)!=GE_FALSE)
00840                                 {
00841                                         SetRoot = GE_TRUE;
00842 
00843                                         if ( Transform != NULL )
00844                                                 {
00845                                                         geXForm3d_Multiply(Transform,&RootTransform,&RootTransform);
00846                                                 }
00847                                 }
00848                         else
00849                                 {
00850                                         if ( Transform != NULL )
00851                                                 {
00852                                                         SetRoot = GE_TRUE;
00853                                                         RootTransform = *Transform;
00854                                                 }
00855                                 }
00856 
00857                         if (SetRoot != GE_FALSE)
00858                                 {
00859                                         geQuaternion_FromMatrix(&RootTransform,&(P->RootJoint.LocalRotation));
00860                                         P->RootJoint.LocalTranslation = RootTransform.Translation;
00861                                         P->RootJoint.Touched = GE_TRUE;
00862                                 }
00863                 }
00864 
00865         if (M==NULL)
00866                 {
00867                         return;
00868                 }
00869         if (BoneIndex == GE_POSE_ROOT_JOINT)
00870                 {
00871                         return;
00872                 }
00873 
00874         if (gePose_MatchesMotionExactly(P,M)==GE_TRUE)
00875                 NameBinding = GE_FALSE;
00876         else
00877                 NameBinding = GE_TRUE;
00878 
00879         P->Touched = GE_TRUE;
00880 
00881         gePose_SetMotionForABoneRecursion(P, M, Time, BoneIndex, NameBinding);
00882 }
00883         
00884 
00885 
00886 
00887 #define LINEAR_BLEND(a,b,t)  ( (t)*((b)-(a)) + (a) )    
00888                         // linear blend of a and b  0<t<1 where  t=0 ->a and t=1 ->b
00889 
00890 
00891 
00892 void GENESISCC gePose_BlendMotion(      
00893         gePose *P, const geMotion *M, geFloat Time,
00894         const geXForm3d *Transform,
00895         geFloat BlendAmount, gePose_BlendingType BlendingType)
00896 {
00897         int i;
00898         geBoolean NameBinding;
00899         gePose_Joint *J;
00900         geQuaternion R1;
00901         geVec3d      T1;
00902         geXForm3d    RootTransform;
00903         
00904         assert( P != NULL );
00905         //assert( M != NULL );  // M can be NULL
00906         assert( BlendingType == GE_POSE_BLEND_HERMITE || BlendingType == GE_POSE_BLEND_LINEAR);
00907         assert( BlendAmount >= 0.0f );
00908         assert( BlendAmount <= 1.0f );
00909 
00910         P->OnlyThisJoint = GE_POSE_ROOT_JOINT-1;                // calling this function disables one-joint optimizations
00911         if (BlendingType == GE_POSE_BLEND_HERMITE)
00912                 {
00913                         geFloat t2,t3;
00914                         t2 = BlendAmount * BlendAmount;
00915                         t3 = t2 * BlendAmount;
00916                         BlendAmount = t2*3.0f -t3-t3;
00917                 }
00918 
00919         if (P->Parent==NULL)
00920                 {
00921                         geBoolean SetRoot = GE_FALSE;
00922                         if (geMotion_GetTransform(M,Time,&RootTransform)!=GE_FALSE)
00923                                 {
00924                                         SetRoot = GE_TRUE;
00925 
00926                                         if ( Transform != NULL )
00927                                                 {
00928                                                         geXForm3d_Multiply(Transform,&RootTransform,&RootTransform);
00929                                                 }
00930                                 }
00931                         else
00932                                 {
00933                                         if ( Transform != NULL )
00934                                                 {
00935                                                         SetRoot = GE_TRUE;
00936                                                         RootTransform = *Transform;
00937                                                 }
00938                                 }
00939 
00940                         if (SetRoot != GE_FALSE)
00941                                 {
00942                                         geQuaternion_FromMatrix(&RootTransform,&R1);
00943                                         T1 = RootTransform.Translation;
00944                                         J  = &(P->RootJoint);
00945                                         geQuaternion_Slerp(&(J->LocalRotation),&(R1),BlendAmount,&(J->LocalRotation));
00946                                         {
00947                                                 geVec3d      *LT = &(J->LocalTranslation);
00948                                                 LT->X = LINEAR_BLEND(LT->X,T1.X,BlendAmount);
00949                                                 LT->Y = LINEAR_BLEND(LT->Y,T1.Y,BlendAmount);
00950                                                 LT->Z = LINEAR_BLEND(LT->Z,T1.Z,BlendAmount);
00951                                         }
00952                                         J->Touched = GE_TRUE;
00953                                 }
00954                 }
00955 
00956         if (M==NULL)
00957                 {
00958                         return;
00959                 }
00960 
00961         
00962         if (gePose_MatchesMotionExactly(P,M)==GE_TRUE)
00963                 NameBinding = GE_FALSE;
00964         else
00965                 NameBinding = GE_TRUE;
00966         
00967         P->Touched = GE_TRUE;
00968 
00969         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
00970                 {
00971                         //gePath *JointPath;
00972                                                         
00973                         if (NameBinding == GE_FALSE)
00974                                 {
00975                                         geMotion_SampleChannels(M,i,Time,&R1,&T1);
00976                                         //JointPath = geMotion_GetPath(M,i);
00977                                         //assert( JointPath != NULL );
00978                                 }
00979                         else
00980                                 {
00981                                         //JointPath = geMotion_GetPathNamed(M, geStrBlock_GetString(P->JointNames,i));
00982                                         //if (JointPath == NULL)
00983                                         //      continue;
00984                                         if (geMotion_SampleChannelsNamed(M,
00985                                                 geStrBlock_GetString(P->JointNames,i),
00986                                                 Time,&R1,&T1)==GE_FALSE)
00987                                                 continue;
00988 
00989                                 }
00990                         J->Touched = GE_TRUE;
00991 
00992                         //gePath_SampleChannels(JointPath,Time,&(R1),&(T1));
00993                         
00994                         T1.X *= P->Scale.X;
00995                         T1.Y *= P->Scale.Y;
00996                         T1.Z *= P->Scale.Z;
00997                         
00998                         geQuaternion_Slerp(&(J->LocalRotation),&(R1),BlendAmount,&(J->LocalRotation));
00999                                                 
01000                         {
01001                                 geVec3d      *LT = &(J->LocalTranslation);
01002                                 LT->X = LINEAR_BLEND(LT->X,T1.X,BlendAmount);
01003                                 LT->Y = LINEAR_BLEND(LT->Y,T1.Y,BlendAmount);
01004                                 LT->Z = LINEAR_BLEND(LT->Z,T1.Z,BlendAmount);
01005                         }
01006                 }
01007 }
01008 
01009 const char* GENESISCC gePose_GetJointName(const gePose* P, int JointIndex)
01010 {
01011         return geStrBlock_GetString(P->JointNames, JointIndex);
01012 }
01013 
01014 const geXFArray * GENESISCC gePose_GetAllJointTransforms(const gePose *P)
01015 {
01016         assert( P != NULL );
01017 
01018         gePose_UpdateRelativeToParent((gePose *)P);
01019         return P->TransformArray;
01020 }
01021 
01022 void GENESISCC gePose_GetScale(const gePose *P, geVec3d *Scale)
01023 {
01024         assert( P     != NULL );
01025         assert( Scale != NULL );
01026         *Scale = P->Scale;
01027 }
01028         
01029 
01030 void GENESISCC gePose_SetScale(gePose *P, const geVec3d *Scale )
01031 {
01032         assert( P != NULL );
01033         assert( geVec3d_IsValid(Scale) != GE_FALSE );
01034 
01035         {
01036                 int i;
01037                 gePose_Joint *J;
01038 
01039                 P->Scale = *Scale;
01040                 //geVec3d_Set(&(P->Scale),ScaleX,ScaleY,ScaleZ);
01041 
01042                 for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
01043                         {       
01044                                 J->AttachmentTransform.Translation.X = J->UnscaledAttachmentTranslation.X * Scale->X;
01045                                 J->AttachmentTransform.Translation.Y = J->UnscaledAttachmentTranslation.Y * Scale->Y;
01046                                 J->AttachmentTransform.Translation.Z = J->UnscaledAttachmentTranslation.Z * Scale->Z;
01047                                 //J->AttachmentTransform.Translation = J->AttachmentTranslation;
01048                                 J->Touched = GE_TRUE;
01049                         }
01050                 P->Touched = GE_TRUE;
01051         }
01052 }
01053 
01054 void GENESISCC gePose_ClearCoverage(gePose *P, int ClearTo)
01055 {
01056         int i;
01057         gePose_Joint *J;
01058 
01059         assert( P != NULL );
01060         assert( (ClearTo == GE_FALSE) || (ClearTo == GE_TRUE) );
01061 
01062         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
01063                 {       
01064                         J->Covered = ClearTo;
01065                 }
01066 }
01067 
01068 int GENESISCC gePose_AccumulateCoverage(gePose *P, const geMotion *M, geBoolean QueryOnly)
01069 {
01070         int i,SubMotions;
01071         geBoolean NameBinding;
01072         int Covers=0;
01073         gePose_Joint *J;
01074         
01075         assert( P != NULL );
01076         if (M==NULL)
01077                 {
01078                         return P->JointCount;
01079                 }
01080 
01081         SubMotions = geMotion_GetSubMotionCount(M);
01082         if (SubMotions>0)
01083                 {
01084                         for (i=0; i<SubMotions; i++)
01085                                 {
01086                                         int c = gePose_AccumulateCoverage(P, geMotion_GetSubMotion(M,i),QueryOnly);
01087                                         if (c > Covers)
01088                                                 {
01089                                                         Covers = c;
01090                                                 }
01091                                 }
01092                         return Covers;
01093                 }
01094         
01095         if (gePose_MatchesMotionExactly(P,M)==GE_TRUE)
01096                 NameBinding = GE_FALSE;
01097         else
01098                 NameBinding = GE_TRUE;
01099 
01100         for (i=0, J=&(P->JointArray[0]); i<P->JointCount; i++,J++)
01101                 {
01102                         gePath *JointPath;
01103                         if (J->Covered == GE_FALSE)
01104                                 {
01105                                         if (NameBinding == GE_TRUE)
01106                                                 {
01107                                                         JointPath = geMotion_GetPathNamed(M, geStrBlock_GetString(P->JointNames,i));
01108                                                         if (JointPath == NULL)
01109                                                                 continue;
01110                                                 }
01111                                         if (QueryOnly == GE_FALSE)
01112                                                 {
01113                                                         J->Covered = GE_TRUE;
01114                                                 }
01115                                         Covers ++;
01116                                 }
01117                 }
01118         return Covers;
01119 }
01120         

Generated on Tue Sep 30 12:36:11 2003 for GTestAndEngine by doxygen 1.3.2