00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00036
00037
00038
00039
00040
00041
00042 typedef struct gePose_Joint
00043 {
00044 int ParentJoint;
00045 geXForm3d *Transform;
00046 geQuaternion Rotation;
00047
00048 geVec3d UnscaledAttachmentTranslation;
00049
00050 geQuaternion AttachmentRotation;
00051 geXForm3d AttachmentTransform;
00052
00053 geVec3d LocalTranslation;
00054 geQuaternion LocalRotation;
00055
00056 geBoolean Touched;
00057 geBoolean NoAttachmentRotation;
00058 int Covered;
00059 } gePose_Joint;
00060
00061 typedef struct gePose
00062 {
00063 int JointCount;
00064 int32 NameChecksum;
00065 geBoolean Touched;
00066 geStrBlock *JointNames;
00067 geVec3d Scale;
00068
00069 geBoolean Slave;
00070 int SlaveJointIndex;
00071 gePose *Parent;
00072 gePose_Joint RootJoint;
00073 geXForm3d ParentsLastTransform;
00074 geXForm3d RootTransform;
00075 geXFArray *TransformArray;
00076 gePose_Joint *JointArray;
00077 int OnlyThisJoint;
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
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
00241
00242 static void GENESISCC gePose_JointRelativeToParent(
00243 const gePose_Joint *Parent,
00244 gePose_Joint *J)
00245 {
00246
00247 #if 0
00248
00249
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
00269
00270
00271 geQuaternion_Multiply(&(Parent->Rotation), &(J->LocalRotation), &(J->Rotation));
00272
00273 geQuaternion_ToMatrix(&(J->Rotation), (J->Transform));
00274
00275 geVec3d_Add(&(J->LocalTranslation),&(J->AttachmentTransform.Translation),Translation);
00276 geXForm3d_Transform((Parent->Transform),Translation,Translation);
00277 }
00278 else
00279 {
00280
00281
00282 geQuaternion BaseRotation;
00283
00284
00285 geQuaternion_Multiply(&(Parent->Rotation),&(J->AttachmentRotation),&BaseRotation);
00286
00287 geQuaternion_Multiply(&BaseRotation, &(J->LocalRotation), &(J->Rotation));
00288
00289 geQuaternion_ToMatrix(&(J->Rotation), (J->Transform));
00290
00291
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);
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
00389
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
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;
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
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
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
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
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
00684
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;
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;
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
00769 if (NameBinding == GE_FALSE)
00770 {
00771 geMotion_SampleChannels(M,i,Time,&(J->LocalRotation),&(J->LocalTranslation));
00772
00773
00774
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
00834 P->OnlyThisJoint = BoneIndex;
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
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
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;
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
00972
00973 if (NameBinding == GE_FALSE)
00974 {
00975 geMotion_SampleChannels(M,i,Time,&R1,&T1);
00976
00977
00978 }
00979 else
00980 {
00981
00982
00983
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
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
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
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