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

actor.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  ACTOR.C                                                                             */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                    */
00005 /*  Description:  Actor 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 /*
00023 
00024         TODO:
00025           make cued motions keyed to a 'root' bone.  Register the root bone, and then 
00026           all requests are relative to that bone, rather than the current 'anchor' point.
00027           actually, this doesn't really change much, just _AnimationCue() - and it allows
00028           a more efficient _TestStep()
00029 
00030         
00031 */
00032 #include <assert.h>
00033 #include <string.h>  //strnicmp         memmove()
00034 #include <math.h>        // fabs()
00035 #include <stdio.h>       //sscanf
00036 
00037 #include "world.h"      // to expose _Render apis in actor.h
00038 
00039 #include "Actor.h"
00040 #include "Ram.h"
00041 #include "Puppet.h"
00042 #include "Body.h"
00043 #include "Motion.h"
00044 #include "ErrorLog.h"
00045 #include "strblock.h"
00046 #ifdef _DEBUG
00047 #include <crtdbg.h>
00048 #endif
00049 
00050 /* to do:
00051                 need to utilize extbox module rather than hard coding vector corners of boxes
00052                 (BoundingBoxMinCorner,BoundingBoxMaxCorner)
00053 */
00054 
00055 #define ACTOR_MOTIONS_MAX 0x0FFFF               // really arbitrary. just for sanity checking
00056 #define ACTOR_CUES_MAX    0x0FFFF               // arbitrary. 
00057 
00058 typedef struct geActor
00059 {
00060         int32                            RefCount;                              // this is the number of owners.
00061         gePuppet                        *Puppet;
00062         gePose                          *Pose;
00063         geActor_BlendingType BlendingType;
00064         geActor_Def                     *ActorDefinition;               // actor definition this is an instance of
00065         
00066         geMotion                        *CueMotion;
00067         geVec3d                         BoundingBoxMinCorner;
00068         geVec3d                         BoundingBoxMaxCorner;
00069         int                                     BoundingBoxCenterBoneIndex;
00070         int                                     StepBoneIndex;                  // used for single-bone motion optimization.
00071         void *                          UserData;
00072 
00073         geExtBox                        RenderHintExtBox;
00074         int                                     RenderHintExtBoxCenterBoneIndex;
00075         geBoolean                       RenderHintExtBoxEnabled;
00076 } geActor;
00077 
00078 
00079 typedef struct geActor_Def
00080 {
00081         geBody                          *Body;
00082         geVFile *                        TextureFileContext;
00083         
00084         int32                            MotionCount;
00085         geMotion                   **MotionArray;
00086 
00087         int32                            RefCount;                              // this is the number of owners.
00088 
00089         geActor_Def                     *ValidityCheck;
00090 } geActor_Def;
00091 
00092         // these are useful globals to monitor resources
00093 int geActor_Count       = 0;
00094 int geActor_RefCount    = 0;
00095 int geActor_DefCount    = 0;
00096 int geActor_DefRefCount = 0;
00097 
00098         // returns number of actors that are currently created.
00099 GENESISAPI int GENESISCC geActor_GetCount(void)
00100 {
00101         return geActor_Count;
00102 }
00103 
00104 GENESISAPI geBoolean GENESISCC geActor_IsValid(const geActor *A)
00105 {
00106         if (A==NULL)
00107                 return GE_FALSE;
00108         if (geActor_DefIsValid(A->ActorDefinition)==GE_FALSE)
00109                 return GE_FALSE;
00110         if (A->Pose == NULL)
00111                 return GE_FALSE;
00112         if (A->CueMotion == NULL)
00113                 return GE_FALSE;
00114         if (geBody_IsValid(A->ActorDefinition->Body) == GE_FALSE )
00115                 return GE_FALSE;
00116 
00117         return GE_TRUE;
00118 }
00119         
00120 
00121 //MRB BEGIN
00122 GENESISAPI void GENESISCC geActor_GetNonWorldExtBox(const geActor *A, geExtBox *ExtBox)
00123 {
00124         assert( geActor_IsValid(A) != GE_FALSE);
00125         assert( ExtBox != NULL );
00126         
00127         geVec3d_Copy(&(A->BoundingBoxMinCorner), &(ExtBox->Min));
00128         geVec3d_Copy(&(A->BoundingBoxMaxCorner), &(ExtBox->Max));
00129 }
00130 GENESISAPI void GENESISCC geActor_GetPosition(const geActor *A, geVec3d *Pos)
00131 {
00132         geXForm3d Transform;
00133         assert( geActor_IsValid(A) != GE_FALSE);
00134         assert( Pos != NULL );
00135         gePose_GetJointTransform( A->Pose,
00136                 A->BoundingBoxCenterBoneIndex,
00137                 &Transform); 
00138         assert ( geXForm3d_IsOrthonormal(&Transform) != GE_FALSE );
00139         geVec3d_Copy(&(Transform.Translation), Pos);
00140 }
00141 //MRB END
00142 
00143 // LWM_ACTOR_RENDERING:
00144 GENESISAPI geFloat GENESISCC geActor_GetAlpha(const geActor *A)
00145 {
00146         assert( A != NULL ) ;
00147         assert( A->Puppet != NULL ) ;
00148         return gePuppet_GetAlpha(A->Puppet);
00149 }
00150 
00151 // LWM_ACTOR_RENDERING:
00152 GENESISAPI void GENESISCC geActor_SetAlpha(geActor *A, geFloat Alpha)
00153 {
00154         assert( A != NULL ) ;
00155         assert( A->Puppet != NULL ) ;
00156         gePuppet_SetAlpha( A->Puppet, Alpha ) ;
00157 }
00158 
00159 GENESISAPI geBoolean GENESISCC geActor_DefIsValid(const geActor_Def *A)
00160 {
00161         if (A==NULL)
00162                 return GE_FALSE;
00163         if (A->ValidityCheck != A)
00164                 return GE_FALSE;
00165         return GE_TRUE;
00166 }
00167 
00168 static geBoolean GENESISCC geActor_GetBoneIndex(const geActor *A, const char *BoneName, int *BoneIndex)
00169 {
00170         geXForm3d Dummy;
00171         int ParentBoneIndex;
00172         assert( geActor_IsValid(A) != GE_FALSE);
00173         assert( BoneIndex != NULL );
00174 
00175         if ( BoneName != NULL )
00176                 {
00177                         if (geBody_GetBoneByName(A->ActorDefinition->Body,
00178                                                                          BoneName,
00179                                                                          BoneIndex,
00180                                                                          &Dummy,
00181                                                                          &ParentBoneIndex) ==GE_FALSE)
00182                                 {
00183                                         geErrorLog_AddString(-1,"Named bone not found:", BoneName);
00184                                         //geErrorLog_AppendString(BoneName);
00185                                         return GE_FALSE;                        
00186                                 }
00187                 }
00188         else
00189                 {
00190                         *BoneIndex = GE_POSE_ROOT_JOINT;
00191                 }
00192         return GE_TRUE;
00193 }
00194 
00195 
00196 GENESISAPI geActor_Def *GENESISCC geActor_GetActorDef(const geActor *A)
00197 {
00198         assert( geActor_DefIsValid(A->ActorDefinition) != GE_FALSE );
00199         return A->ActorDefinition;
00200 }
00201 
00202 GENESISAPI void GENESISCC geActor_DefCreateRef(geActor_Def *A)
00203 {
00204         assert( geActor_DefIsValid(A) != GE_FALSE );
00205         A->RefCount++;
00206         geActor_DefRefCount++;
00207 }
00208 
00209 GENESISAPI geActor_Def *GENESISCC geActor_DefCreate(void)
00210 {
00211         geActor_Def *Ad;
00212 
00213         Ad = GE_RAM_ALLOCATE_STRUCT( geActor_Def );
00214         if ( Ad == NULL )
00215                 {
00216                         geErrorLog_Add( ERR_ACTOR_ENOMEM , NULL);
00217                         return NULL;
00218                 }
00219 
00220         Ad->Body                                = NULL;
00221         Ad->MotionCount                 = 0;
00222         Ad->MotionArray                 = NULL;
00223         Ad->ValidityCheck               = Ad;
00224         Ad->RefCount            = 0;
00225         geActor_DefCount++;
00226         return Ad;
00227 }
00228 
00229 GENESISAPI void GENESISCC geActor_CreateRef(geActor *Actor)
00230 {
00231         assert( geActor_IsValid(Actor) );
00232         Actor->RefCount ++;
00233         geActor_RefCount++;
00234 }
00235 
00236 GENESISAPI geActor *GENESISCC geActor_Create(geActor_Def *ActorDefinition)
00237 {
00238         geActor *A;
00239         assert( geActor_DefIsValid(ActorDefinition)      != GE_FALSE );
00240         
00241         if (ActorDefinition->Body == NULL)
00242                 {
00243                         geErrorLog_AddString(-1,"geActor_Def must have a body before Actors can be created", NULL);
00244                         return NULL;
00245                 }
00246         assert( geBody_IsValid(ActorDefinition->Body) != GE_FALSE );
00247 
00248         A = GE_RAM_ALLOCATE_STRUCT( geActor );
00249         if ( A == NULL )
00250                 {
00251                         geErrorLog_Add( ERR_ACTOR_ENOMEM , NULL);
00252                         goto ActorCreateFailure;
00253                 }
00254         A->Puppet = NULL;
00255         A->Pose   = NULL;
00256         A->CueMotion = NULL;
00257 
00258         A->Pose = gePose_Create();
00259         if (A->Pose == NULL)
00260                 {
00261                         geErrorLog_Add(ERR_ACTOR_ENOMEM, NULL);
00262                         goto ActorCreateFailure;
00263                 }
00264         
00265         A->RefCount          = 0;
00266         A->BlendingType          = GE_ACTOR_BLEND_HERMITE;
00267         A->ActorDefinition   = ActorDefinition;
00268         A->CueMotion             = geMotion_Create(GE_TRUE);
00269         A->BoundingBoxCenterBoneIndex = GE_POSE_ROOT_JOINT;
00270         A->RenderHintExtBoxCenterBoneIndex = GE_POSE_ROOT_JOINT;
00271         A->RenderHintExtBoxEnabled = GE_FALSE;
00272         A->StepBoneIndex     = GE_POSE_ROOT_JOINT;
00273         geExtBox_Set(&(A->RenderHintExtBox), 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f);
00274         if (A->CueMotion == NULL)
00275                 {
00276                         geErrorLog_Add( ERR_ACTOR_ENOMEM , NULL);
00277                         goto ActorCreateFailure;
00278                 }
00279 
00280 
00281         {
00282                 int i; 
00283                 int BoneCount;
00284 
00285                 BoneCount = geBody_GetBoneCount(A->ActorDefinition->Body);
00286                 for (i=0; i<BoneCount; i++)
00287                         {
00288                                 const char *Name;
00289                                 geXForm3d Attachment;
00290                                 int ParentBone;
00291                                 int Index;
00292                                 geBody_GetBone( A->ActorDefinition->Body, i, &Name,&Attachment, &ParentBone );
00293                                 if (gePose_AddJoint( A->Pose,
00294                                                                         ParentBone,Name,&Attachment,&Index)==GE_FALSE)
00295                                         {
00296                                                 geErrorLog_Add(ERR_ACTOR_ENOMEM, NULL);
00297                                                 goto ActorCreateFailure;
00298                                         }
00299                         }
00300         }
00301 
00302 
00303         geVec3d_Clear(&(A->BoundingBoxMinCorner));
00304         geVec3d_Clear(&(A->BoundingBoxMaxCorner));
00305         assert( geActor_IsValid(A) != GE_FALSE );
00306         geActor_DefCreateRef(ActorDefinition);
00307         geActor_Count++;
00308         return A;
00309 
00310         ActorCreateFailure:
00311         if ( A!= NULL)
00312                 {
00313                         if (A->Pose != NULL)
00314                                 gePose_Destroy(&(A->Pose));
00315                         if (A->CueMotion != NULL)
00316                                 geMotion_Destroy(&(A->CueMotion));
00317                         geRam_Free( A );
00318                 }
00319         return NULL;
00320 }       
00321 
00322 GENESISAPI geBoolean GENESISCC geActor_DefDestroy(geActor_Def **pActorDefinition)
00323 {
00324         int i;
00325         geActor_Def *Ad;
00326         assert(  pActorDefinition != NULL );
00327         assert( *pActorDefinition != NULL );
00328         assert( geActor_DefIsValid( *pActorDefinition ) != GE_FALSE );
00329 
00330         Ad = *pActorDefinition;
00331 
00332         if (Ad->RefCount > 0)
00333                 {
00334                         Ad->RefCount--;
00335                         geActor_DefRefCount--;
00336                         return GE_FALSE;
00337                 }
00338 
00339         if (Ad->Body != NULL)
00340                 {
00341                         geBody_Destroy( &(Ad->Body) );
00342                         Ad->Body = NULL;
00343                 }
00344         if (Ad->MotionArray != NULL)
00345                 {
00346                         for (i=0; i<Ad->MotionCount; i++)
00347                                 {
00348                                         geMotion_Destroy( &(Ad->MotionArray[i]) );
00349                                         Ad->MotionArray[i] = NULL;
00350                                 }
00351                         geRam_Free( Ad->MotionArray );
00352                         Ad->MotionArray = NULL;
00353                 }
00354                                 
00355         Ad->MotionCount = 0;
00356 
00357         geRam_Free(*pActorDefinition);
00358         *pActorDefinition = NULL;
00359         geActor_DefCount--;
00360         return GE_TRUE;
00361 }
00362 
00363 
00364 GENESISAPI geBoolean GENESISCC geActor_Destroy(geActor **pA)
00365 {
00366         geActor *A;
00367         assert(  pA != NULL );
00368         assert( *pA != NULL );
00369         assert( geActor_IsValid(*pA) != GE_FALSE );
00370         
00371         A = *pA;
00372         if (A->RefCount > 0)
00373                 {
00374                         A->RefCount --;
00375                         geActor_RefCount--;
00376                         return GE_FALSE;
00377                 }
00378 
00379         geActor_DefDestroy(&(A->ActorDefinition));
00380         if (A->Puppet != NULL)
00381                 {
00382                         gePuppet_Destroy( &(A->Puppet) );
00383                         A->Puppet = NULL;
00384                 }
00385         if ( A->Pose != NULL )
00386                 {
00387                         gePose_Destroy( &( A->Pose ) );
00388                         A->Pose = NULL;
00389                 }
00390         if ( A->CueMotion != NULL )
00391                 {
00392                         geMotion_Destroy(&(A->CueMotion));
00393                         A->CueMotion = NULL;
00394                 }
00395         geRam_Free(*pA);
00396         geActor_Count--;
00397         *pA = NULL;
00398         return GE_TRUE;
00399 
00400 }
00401 
00402 
00403 GENESISAPI geBoolean GENESISCC geActor_DestroyDirect(geActor **pA)
00404 {
00405                 geActor         *CurrentActor=NULL;
00406                 int                     i=0;
00407 
00408                 // dumb brute force deletion of actors in ActorArray
00409 
00410                 // destroy the actor
00411                 CurrentActor = *pA;
00412 
00413                 if(!CurrentActor)
00414                         return GE_FALSE;
00415 
00416                 gePuppet_Destroy( &(CurrentActor->Puppet) );
00417                 gePose_Destroy( &( CurrentActor->Pose ) );
00418                 geMotion_Destroy(&(CurrentActor->CueMotion));
00419 
00420                 assert( _CrtIsValidPointer( &CurrentActor->ActorDefinition, sizeof(CurrentActor->ActorDefinition), FALSE ) );
00421 
00422                 if(geActor_DefIsValid(CurrentActor->ActorDefinition)==GE_TRUE )
00423                 {
00424                 // destroy the definition
00425                 if (CurrentActor->ActorDefinition->Body != NULL)
00426                         {
00427                         geBody_Destroy( &(CurrentActor->ActorDefinition->Body) );
00428                         CurrentActor->ActorDefinition->Body = NULL;
00429                         }
00430                 if (CurrentActor->ActorDefinition->MotionArray != NULL)
00431                         {
00432                                 for (i=0; i<CurrentActor->ActorDefinition->MotionCount; i++)
00433                                         {
00434                                         geMotion_Destroy( &(CurrentActor->ActorDefinition->MotionArray[i]) );
00435                                         CurrentActor->ActorDefinition->MotionArray[i] = NULL;
00436                                         }
00437                                 geRam_Free( CurrentActor->ActorDefinition->MotionArray );
00438                                 CurrentActor->ActorDefinition->MotionArray = NULL;
00439                         }
00440                                         
00441                 CurrentActor->ActorDefinition->TextureFileContext=NULL;
00442                 CurrentActor->ActorDefinition->ValidityCheck = NULL;
00443                 
00444                 //free the def
00445                 geRam_Free(CurrentActor->ActorDefinition);
00446                 CurrentActor->ActorDefinition = NULL;
00447                 
00448                 }
00449 
00450                 CurrentActor->UserData = NULL;
00451 
00452                 // free the actor
00453                 geRam_Free(CurrentActor);
00454                 CurrentActor = NULL;
00455 
00456 return GE_TRUE;
00457 }
00458 
00459 GENESISAPI geBoolean GENESISCC geActor_SetBody( geActor_Def *ActorDefinition, geBody *BodyGeometry)
00460 {
00461         assert( geBody_IsValid(BodyGeometry) != GE_FALSE );
00462         
00463         if (ActorDefinition->RefCount > 0)
00464                 {       
00465                         geErrorLog_Add(-1, NULL);  // ActorDef already used by a body. cant change now
00466                         return GE_FALSE;
00467                 }
00468 
00469         if (ActorDefinition->Body != NULL)
00470                 {
00471                         geBody_Destroy( &(ActorDefinition->Body) );
00472                 }
00473         
00474         ActorDefinition->Body          = BodyGeometry;
00475         return GE_TRUE;
00476 }
00477 
00478 
00479 #pragma message ("consider removing this and related parameters to setpose")
00480 GENESISAPI void GENESISCC geActor_SetBlendingType( geActor *A, geActor_BlendingType BlendingType )
00481 {
00482         assert( geActor_IsValid(A) != GE_FALSE );
00483 
00484         assert( (BlendingType == GE_ACTOR_BLEND_LINEAR) || 
00485                         (BlendingType == GE_ACTOR_BLEND_HERMITE) );
00486 
00487         if (BlendingType == GE_ACTOR_BLEND_LINEAR)
00488                 {
00489                         A->BlendingType = GE_POSE_BLEND_LINEAR;
00490                 }
00491         else
00492                 {
00493                         A->BlendingType = GE_POSE_BLEND_HERMITE;
00494                 }
00495 }
00496 
00497 GENESISAPI geVFile *geActor_DefGetFileContext(const geActor_Def *A)
00498 {
00499         assert( geActor_DefIsValid(A) != GE_FALSE );
00500         return A->TextureFileContext;
00501 }
00502 
00503 
00504 
00505 GENESISAPI geBoolean GENESISCC geActor_AddMotion(geActor_Def *Ad, geMotion *NewMotion, int *Index)
00506 {
00507         geMotion **NewMArray;
00508         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00509         assert( NewMotion != NULL );
00510         assert( Index != NULL );
00511 
00512         if (Ad->MotionCount >= ACTOR_MOTIONS_MAX)
00513                 {
00514                         geErrorLog_Add(ERR_ACTOR_TOO_MANY_MOTIONS, NULL);
00515                         return GE_FALSE;
00516                 }
00517         NewMArray = GE_RAM_REALLOC_ARRAY( Ad->MotionArray, geMotion*, Ad->MotionCount +1 );
00518         if ( NewMArray == NULL )
00519                 {
00520                         geErrorLog_Add(ERR_ACTOR_ENOMEM, NULL);
00521                         return GE_FALSE;
00522                 }
00523 
00524         Ad->MotionArray = NewMArray;
00525 
00526         Ad->MotionArray[Ad->MotionCount]= NewMotion;
00527         Ad->MotionCount++;
00528         *Index = Ad->MotionCount;
00529         return GE_TRUE;
00530 };
00531 
00532 GENESISAPI void GENESISCC geActor_ClearPose(geActor *A, const geXForm3d *Transform)
00533 {
00534         assert( geActor_IsValid(A) != GE_FALSE );
00535         assert ( (Transform==NULL) || (geXForm3d_IsOrthonormal(Transform) != GE_FALSE) );
00536         gePose_Clear( A->Pose ,Transform);
00537 }
00538 
00539 GENESISAPI void GENESISCC geActor_SetPose(geActor *A, const geMotion *M, 
00540                                                                 geFloat Time, const geXForm3d *Transform)
00541 {
00542         assert( geActor_IsValid(A) != GE_FALSE );
00543         assert( M != NULL );
00544         assert ( (Transform==NULL) || (geXForm3d_IsOrthonormal(Transform) != GE_FALSE) );
00545 
00546         gePose_SetMotion( A->Pose,M,Time,Transform);
00547 }
00548 
00549 GENESISAPI void GENESISCC geActor_BlendPose(geActor *A, const geMotion *M, 
00550                                                                 geFloat Time,  
00551                                                                 const geXForm3d *Transform,
00552                                                                 geFloat BlendAmount)
00553 {
00554         assert( geActor_IsValid(A) != GE_FALSE );
00555         assert( M != NULL );
00556         assert ( (Transform==NULL) || (geXForm3d_IsOrthonormal(Transform) != GE_FALSE) );
00557 
00558         gePose_BlendMotion( A->Pose,M,Time,Transform,
00559                                                 BlendAmount,A->BlendingType);
00560 }
00561 
00562 
00563 GENESISAPI int GENESISCC geActor_GetMotionCount(const geActor_Def *Ad)
00564 {
00565         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00566         return Ad->MotionCount;
00567 }
00568         
00569 
00570 GENESISAPI geMotion *GENESISCC geActor_GetMotionByIndex(const geActor_Def *Ad, int Index )
00571 {
00572         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00573         assert( Index >= 0 );
00574         assert( Index < Ad->MotionCount );
00575         assert( Ad->MotionArray != NULL );
00576 
00577         return Ad->MotionArray[Index];
00578 }
00579 
00580 GENESISAPI geMotion *GENESISCC geActor_GetMotionByName(const geActor_Def *Ad, const char *Name )
00581 {
00582         int i;
00583         const char *TestName;
00584         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00585         assert( Name != NULL );
00586         for (i=0; i<Ad->MotionCount; i++)
00587                 {
00588                         TestName = geMotion_GetName(Ad->MotionArray[i]);
00589                         if (TestName != NULL)
00590                                 {
00591                                         if (strcmp(TestName,Name)==0)
00592                                                 return Ad->MotionArray[i];
00593                                 }
00594 
00595                 }
00596         return NULL;
00597 }
00598 
00599 GENESISAPI const char *GENESISCC geActor_GetMotionName(const geActor_Def *Ad, int Index )
00600 {
00601         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00602         assert( Index >= 0 );
00603         assert( Index < Ad->MotionCount );
00604         assert( Ad->MotionArray != NULL );
00605         return geMotion_GetName(Ad->MotionArray[Index]);
00606 }
00607         
00608 GENESISAPI geBody *GENESISCC geActor_GetBody(const geActor_Def *Ad)
00609 {
00610         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00611         return Ad->Body;
00612 }
00613         
00614 #pragma message ("Keep this function: geActor_DefHasBoneNamed()?")
00615 // Returns GE_TRUE if the actor definition has a bone named 'Name'
00616 GENESISAPI geBoolean GENESISCC geActor_DefHasBoneNamed(const geActor_Def *Ad, const char *Name )
00617 {
00618         int DummyIndex,DummyParent;
00619         geXForm3d DummyAttachment;
00620 
00621         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00622         assert( Name != NULL );
00623         if (geBody_GetBoneByName(geActor_GetBody(Ad),Name,
00624                         &DummyIndex, &DummyAttachment, &DummyParent ) == GE_FALSE )
00625                 {
00626                         return GE_FALSE;
00627                 }
00628         return GE_TRUE;
00629 }
00630 
00631 
00632 #define GE_ACTOR_BODY_NAME       "Body"
00633 #define GE_ACTOR_HEADER_NAME     "Header"
00634 #define GE_MOTION_DIRECTORY_NAME "Motions"
00635 
00636 #define ACTOR_FILE_TYPE 0x52544341      // 'ACTR'
00637 #define ACTOR_FILE_VERSION 0x00F1               // Restrict version to 16 bits
00638 
00639 
00640 
00641 static geActor_Def * GENESISCC geActor_DefCreateHeader(geVFile *pFile, geBoolean *HasBody)
00642 {
00643         uint32 u;
00644         uint32 version;
00645         geActor_Def *Ad;
00646 
00647         assert( pFile != NULL );
00648         assert( HasBody != NULL );
00649 
00650         if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00651                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    return NULL;}
00652         if (u != ACTOR_FILE_TYPE)
00653                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    return NULL;}
00654 
00655         if(geVFile_Read(pFile, &version, sizeof(version)) == GE_FALSE)
00656                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    return NULL;}
00657         if ( (version != ACTOR_FILE_VERSION) )
00658                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    return NULL;}
00659 
00660         Ad = geActor_DefCreate();
00661         if (Ad==NULL)
00662                 {       geErrorLog_Add( ERR_ACTOR_ENOMEM , NULL); return NULL; }
00663 
00664         Ad->TextureFileContext = geVFile_GetContext(pFile);
00665         assert(Ad->TextureFileContext);
00666 
00667         if(geVFile_Read(pFile, HasBody, sizeof(*HasBody)) == GE_FALSE)
00668                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    geActor_DefDestroy(&Ad); return NULL;}
00669 
00670         if(geVFile_Read(pFile, &(Ad->MotionCount), sizeof(Ad->MotionCount)) == GE_FALSE)
00671                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    geActor_DefDestroy(&Ad); return NULL;}
00672 
00673         return Ad;
00674 }
00675 
00676 
00677 static geBoolean GENESISCC geActor_DefWriteHeader(const geActor_Def *Ad, geVFile *pFile)
00678 {
00679         uint32 u;
00680         geBoolean Flag;
00681         
00682         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00683         assert( pFile != NULL );
00684 
00685         // Write the format flag
00686         u = ACTOR_FILE_TYPE;
00687         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
00688                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   return GE_FALSE; }
00689 
00690 
00691         u = ACTOR_FILE_VERSION;
00692         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
00693                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   return GE_FALSE;}
00694 
00695         if (Ad->Body != NULL)
00696                 Flag = GE_TRUE;
00697         else 
00698                 Flag = GE_FALSE;
00699 
00700         if(geVFile_Write(pFile, &Flag, sizeof(Flag)) == GE_FALSE)
00701                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   return GE_FALSE;}
00702 
00703         if(geVFile_Write(pFile, &(Ad->MotionCount), sizeof(Ad->MotionCount)) == GE_FALSE)
00704                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   return GE_FALSE;}
00705 
00706         return GE_TRUE;
00707 }
00708         
00709 
00710 
00711 GENESISAPI geActor_Def *GENESISCC geActor_DefCreateFromFile(geVFile *pFile)
00712 {
00713         int i;
00714         geActor_Def *Ad   = NULL;
00715         geVFile *VFile    = NULL;
00716         geVFile *SubFile  = NULL;
00717         geVFile *MotionDirectory = NULL;        
00718         geBoolean HasBody = GE_FALSE;
00719         geBody * Body     = NULL;
00720                         
00721         assert( pFile != NULL );
00722 
00723         VFile = geVFile_OpenNewSystem(pFile,GE_VFILE_TYPE_VIRTUAL, NULL, 
00724                                                                         NULL, GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_READONLY);
00725         if (VFile == NULL)
00726                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError;}
00727         
00728         SubFile = geVFile_Open(VFile,GE_ACTOR_HEADER_NAME,GE_VFILE_OPEN_READONLY);
00729         if (SubFile == NULL)
00730                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError;}
00731 
00732         Ad = geActor_DefCreateHeader(SubFile,&HasBody);
00733         if (Ad == NULL)
00734                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError;}
00735         geVFile_Close(SubFile);
00736 
00737 
00738         if (HasBody != GE_FALSE)
00739                 {
00740                         SubFile = geVFile_Open(VFile,GE_ACTOR_BODY_NAME,GE_VFILE_OPEN_READONLY);
00741                         if (SubFile == NULL)
00742                                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError;}
00743 
00744                         Body = geBody_CreateFromFile(SubFile);
00745                         if (Body == NULL)
00746                                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError; }
00747                         if (geActor_SetBody(Ad,Body)==GE_FALSE)
00748                                 {       geErrorLog_Add( ERR_ACTOR_ENOMEM , NULL);       goto CreateError; }
00749                         geVFile_Close(SubFile);
00750                 }
00751 
00752         MotionDirectory = geVFile_Open(VFile,GE_MOTION_DIRECTORY_NAME, 
00753                                                                         GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_READONLY);
00754         if (MotionDirectory == NULL)
00755                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    return NULL;}
00756 
00757         if (Ad->MotionCount>0)
00758                 {
00759                         Ad->MotionArray = GE_RAM_ALLOCATE_ARRAY( geMotion*, Ad->MotionCount);
00760                         for (i=0; i<Ad->MotionCount; i++)
00761                                 Ad->MotionArray[i] = NULL;
00762         
00763                         for (i=0; i<Ad->MotionCount; i++)
00764                                 {
00765                                         char FName[1000];
00766                                         sprintf(FName,"%d",i);
00767 
00768                                         SubFile = geVFile_Open(MotionDirectory,FName,GE_VFILE_OPEN_READONLY);
00769                                         if (SubFile == NULL)
00770                                                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError;}
00771                                         Ad->MotionArray[i] = geMotion_CreateFromFile(SubFile);
00772                                         if (Ad->MotionArray[i] == NULL)
00773                                                 {       geErrorLog_Add( ERR_ACTOR_FILE_READ , NULL);    goto CreateError;}
00774                                         geVFile_Close(SubFile);
00775                                 }
00776                 }
00777         else
00778                 {
00779                         Ad->MotionArray = NULL;
00780                 }
00781         geVFile_Close(MotionDirectory);
00782         geVFile_Close(VFile);
00783         return Ad;
00784 
00785         CreateError:
00786                 if (SubFile != NULL)
00787                         geVFile_Close(SubFile);
00788                 if (MotionDirectory != NULL)
00789                         geVFile_Close(MotionDirectory);
00790                 if (VFile != NULL)
00791                         geVFile_Close(VFile);
00792                 if (Ad != NULL)
00793                         geActor_DefDestroy(&Ad);
00794                 return NULL;
00795 }
00796 
00797 
00798 GENESISAPI geBoolean GENESISCC geActor_DefWriteToFile(const geActor_Def *Ad, geVFile *pFile)
00799 {
00800         int i;
00801         geVFile *VFile;
00802         geVFile *SubFile;
00803         geVFile *MotionDirectory;
00804 
00805         assert( geActor_DefIsValid(Ad) != GE_FALSE );
00806         assert( pFile != NULL );
00807 
00808         VFile = geVFile_OpenNewSystem(pFile,GE_VFILE_TYPE_VIRTUAL, NULL, 
00809                                                                         NULL, GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_CREATE);
00810         if (VFile == NULL)
00811                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00812         
00813         SubFile = geVFile_Open(VFile,GE_ACTOR_HEADER_NAME,GE_VFILE_OPEN_CREATE);
00814         if (SubFile == NULL)
00815                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00816 
00817         if (geActor_DefWriteHeader(Ad,SubFile)==GE_FALSE)
00818                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00819         if (geVFile_Close(SubFile)==GE_FALSE)
00820                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00821 
00822         if (Ad->Body != NULL)
00823                 {
00824                         SubFile = geVFile_Open(VFile,GE_ACTOR_BODY_NAME,GE_VFILE_OPEN_CREATE);
00825                         if (SubFile == NULL)
00826                                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00827                         if (geBody_WriteToFile(Ad->Body,SubFile)==GE_FALSE)
00828                                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00829                         if (geVFile_Close(SubFile)==GE_FALSE)
00830                                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00831                 }
00832 
00833         MotionDirectory = geVFile_Open(VFile,GE_MOTION_DIRECTORY_NAME, 
00834                                                                         GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_CREATE);
00835         if (MotionDirectory == NULL)
00836                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00837         
00838         for (i=0; i<Ad->MotionCount; i++)
00839                 {
00840                         char FName[1000];
00841                         sprintf(FName,"%d",i);
00842 
00843                         SubFile = geVFile_Open(MotionDirectory,FName,GE_VFILE_OPEN_CREATE);
00844                         if (SubFile == NULL)
00845                                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00846                         if (geMotion_WriteToBinaryFile(Ad->MotionArray[i],SubFile)==GE_FALSE)
00847                                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00848                         if (geVFile_Close(SubFile)==GE_FALSE)
00849                                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00850                 }
00851 
00852         if (geVFile_Close(MotionDirectory)==GE_FALSE)
00853                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00854         if (geVFile_Close(VFile)==GE_FALSE)
00855                 {       geErrorLog_Add( ERR_ACTOR_FILE_WRITE , NULL);   goto WriteError;}
00856         
00857         return GE_TRUE;
00858         WriteError:
00859                 return GE_FALSE;
00860 }
00861 
00862 GENESISAPI geBoolean GENESISCC geActor_GetBoneTransform(const geActor *A, const char *BoneName, geXForm3d *Transform)
00863 {
00864         int BoneIndex;
00865 
00866         assert( geActor_IsValid(A)!=GE_FALSE );
00867         assert( Transform!= NULL );
00868         
00869         if (geActor_GetBoneIndex(A,BoneName,&BoneIndex)==GE_FALSE)
00870                 {
00871                         geErrorLog_AddString(-1,"Named bone not found", BoneName);
00872                         return GE_FALSE;
00873                 }
00874 
00875         gePose_GetJointTransform(   A->Pose, BoneIndex, Transform);
00876         assert ( geXForm3d_IsOrthonormal(Transform) != GE_FALSE );
00877 
00878         return GE_TRUE;
00879 }
00880 
00881 
00882 GENESISAPI geBoolean GENESISCC geActor_GetBoneTransformByIndex(const geActor *A, int BoneIndex, geXForm3d *Transform)
00883 {
00884         assert( geActor_IsValid(A)!=GE_FALSE );
00885         assert( Transform!= NULL );
00886         
00887         gePose_GetJointTransform(   A->Pose, BoneIndex, Transform);
00888         assert ( geXForm3d_IsOrthonormal(Transform) != GE_FALSE );
00889 
00890         return GE_TRUE;
00891 }
00892 
00893 static void GENESISCC geActor_AccumulateMinMax(
00894         geVec3d *P,geVec3d *Mins,geVec3d *Maxs)
00895 {
00896         assert( geVec3d_IsValid( P  ) != GE_FALSE );
00897         assert( geVec3d_IsValid(Mins) != GE_FALSE );
00898         assert( geVec3d_IsValid(Maxs) != GE_FALSE );
00899         
00900         if (P->X < Mins->X) Mins->X = P->X;
00901         if (P->Y < Mins->Y) Mins->Y = P->Y;
00902         if (P->Z < Mins->Z) Mins->Z = P->Z;
00903 
00904         if (P->X > Maxs->X) Maxs->X = P->X;
00905         if (P->Y > Maxs->Y) Maxs->Y = P->Y;
00906         if (P->Z > Maxs->Z) Maxs->Z = P->Z;
00907 }
00908 
00909 
00910 static geBoolean GENESISCC geActor_GetBoneBoundingBoxByIndex(
00911         const geActor *A, 
00912         int BoneIndex,
00913         geVec3d   *Corner,
00914         geVec3d   *DX,
00915         geVec3d   *DY,
00916         geVec3d   *DZ)
00917 {
00918         geVec3d Min,Max;
00919         geVec3d Orientation;
00920         geXForm3d Transform;
00921         
00922         assert( geActor_IsValid(A) != GE_FALSE );       
00923         assert( geActor_DefIsValid(A->ActorDefinition) != GE_FALSE );
00924         assert( A->ActorDefinition->Body   != NULL );
00925 
00926         assert( Corner      );
00927         assert( DX          );
00928         assert( DY          );
00929         assert( DZ          );
00930         assert( (BoneIndex < gePose_GetJointCount(A->Pose)) || (BoneIndex ==GE_POSE_ROOT_JOINT));
00931         assert( (BoneIndex >=0)                             || (BoneIndex ==GE_POSE_ROOT_JOINT));
00932         
00933         if (geBody_GetBoundingBox( A->ActorDefinition->Body, BoneIndex, &Min, &Max )==GE_FALSE)
00934                 {
00935                         return GE_FALSE;
00936                 }
00937 
00938         // scale bounding box:
00939         {
00940                 geVec3d Scale;
00941                 gePose_GetScale(A->Pose, &Scale);
00942                 assert( geVec3d_IsValid(&Scale) != GE_FALSE );
00943 
00944                 Min.X *= Scale.X;
00945                 Min.Y *= Scale.Y;
00946                 Min.Z *= Scale.Z;
00947                 
00948                 Max.X *= Scale.X;
00949                 Max.Y *= Scale.Y;
00950                 Max.Z *= Scale.Z;
00951         }
00952 
00953 
00954         gePose_GetJointTransform(A->Pose,BoneIndex,&(Transform));
00955 
00956         geVec3d_Subtract(&Max,&Min,&Orientation);
00957                         
00958         DX->X = Orientation.X;  DX->Y = DX->Z = 0.0f;
00959         DY->Y = Orientation.Y;  DY->X = DY->Z = 0.0f;
00960         DZ->Z = Orientation.Z;  DZ->X = DZ->Y = 0.0f;
00961                         
00962         // transform into world space
00963         geXForm3d_Transform(&(Transform),&Min,&Min);
00964         geXForm3d_Rotate(&(Transform),DX,DX);
00965         geXForm3d_Rotate(&(Transform),DY,DY);
00966         geXForm3d_Rotate(&(Transform),DZ,DZ);
00967 
00968         *Corner = Min;
00969         return GE_TRUE;
00970 }
00971 
00972 
00973 
00974 GENESISAPI geBoolean GENESISCC geActor_GetBoneExtBoxByIndex(
00975         const geActor *A, 
00976         int BoneIndex,
00977         geExtBox *ExtBox)
00978 {
00979         geVec3d Min;
00980         geVec3d DX,DY,DZ,Corner;
00981 
00982         assert( ExtBox );
00983                 
00984         if (geActor_GetBoneBoundingBoxByIndex(A,BoneIndex,&Min,&DX,&DY,&DZ)==GE_FALSE)
00985                 {
00986                         return GE_FALSE;
00987                 }
00988 
00989         ExtBox->Min = Min;
00990         ExtBox->Max = Min;
00991         Corner = Min;
00992         // should use extent box (extbox) methods rather than this
00993         geVec3d_Add(&Corner,&DX,&Corner);
00994         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
00995         geVec3d_Add(&Corner,&DZ,&Corner);
00996         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
00997         geVec3d_Subtract(&Corner,&DX,&Corner);
00998         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
00999         geVec3d_Add(&Corner,&DY,&Corner);
01000         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
01001         geVec3d_Add(&Corner,&DX,&Corner);
01002         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
01003         geVec3d_Subtract(&Corner,&DZ,&Corner);
01004         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
01005         geVec3d_Subtract(&Corner,&DX,&Corner);
01006         geActor_AccumulateMinMax(&Corner,&(ExtBox->Min),&(ExtBox->Max));
01007 
01008         return GE_TRUE;
01009 }
01010 
01011 GENESISAPI geBoolean GENESISCC geActor_GetBoneExtBox(const geActor *A,
01012                                                                          const char *BoneName,
01013                                                                          geExtBox *ExtBox)
01014 {
01015         int BoneIndex;
01016         assert( geActor_IsValid(A) != GE_FALSE);
01017         assert( ExtBox != NULL );
01018         
01019         if (geActor_GetBoneIndex(A,BoneName,&BoneIndex)==GE_FALSE)
01020                 {
01021                         geErrorLog_AddString(-1,"Named bone for bounding box not found", BoneName);
01022                         return GE_FALSE;
01023                 }
01024         return geActor_GetBoneExtBoxByIndex(A,BoneIndex,ExtBox);
01025 }
01026 
01027 
01028 GENESISAPI geBoolean GENESISCC geActor_GetBoneBoundingBox(const geActor *A,
01029                                                                  const char *BoneName,
01030                                                                  geVec3d *Corner,
01031                                                                  geVec3d *DX,
01032                                                                  geVec3d *DY,
01033                                                                  geVec3d *DZ)
01034 {
01035         int BoneIndex;
01036         assert( geActor_IsValid(A) != GE_FALSE);
01037         assert( Corner    != NULL );
01038         assert( DX        != NULL );
01039         assert( DY        != NULL );
01040         assert( DZ        != NULL );
01041 
01042         if (geActor_GetBoneIndex(A,BoneName,&BoneIndex)==GE_FALSE)
01043                 {
01044                         geErrorLog_AddString(-1,"Named bone for bounding box not found", BoneName);
01045                         return GE_FALSE;
01046                 }
01047         if (geActor_GetBoneBoundingBoxByIndex(A,BoneIndex,Corner,DX,DY,DZ)==GE_FALSE)
01048                 {
01049                         geErrorLog_AddString(-1,"Failed to get bounding box named:", BoneName);
01050                         //geErrorLog_AppendString(BoneName);
01051                         return GE_FALSE;
01052                 }
01053         return GE_TRUE;
01054 }
01055 
01056 
01057 
01058 GENESISAPI geBoolean GENESISCC geActor_GetExtBox(const geActor *A, geExtBox *ExtBox)
01059 {
01060         geXForm3d Transform;
01061         
01062         assert( geActor_IsValid(A) != GE_FALSE);
01063         assert( ExtBox != NULL );
01064         
01065         gePose_GetJointTransform(   A->Pose,
01066                                                                 A->BoundingBoxCenterBoneIndex,
01067                                                                 &Transform);    
01068         assert ( geXForm3d_IsOrthonormal(&Transform) != GE_FALSE );
01069         geVec3d_Add( &(Transform.Translation), &(A->BoundingBoxMinCorner), &(ExtBox->Min));
01070         geVec3d_Add( &(Transform.Translation), &(A->BoundingBoxMaxCorner), &(ExtBox->Max));
01071         return GE_TRUE;
01072 }
01073 
01074 
01075 GENESISAPI geBoolean GENESISCC geActor_SetExtBox(geActor *A,
01076                                                                                                  const geExtBox *ExtBox,
01077                                                                                                  const char *CenterOnThisNamedBone)
01078 {
01079         
01080         assert( geActor_IsValid(A) != GE_FALSE);
01081         assert( geExtBox_IsValid(ExtBox) != GE_FALSE);
01082         
01083         A->BoundingBoxMinCorner = ExtBox->Min;
01084         A->BoundingBoxMaxCorner = ExtBox->Max;
01085         
01086         if (geActor_GetBoneIndex(A,CenterOnThisNamedBone,&(A->BoundingBoxCenterBoneIndex))==GE_FALSE)
01087                 {
01088                         geErrorLog_AddString(-1,"Named bone for bounding box not found", CenterOnThisNamedBone);
01089                         return GE_FALSE;
01090                 }
01091         
01092         return GE_TRUE;
01093 }
01094 
01095 
01096         // Gets the rendering hint bounding box from the actor
01097 GENESISAPI geBoolean GENESISCC geActor_GetRenderHintExtBox(const geActor *A, geExtBox *Box, geBoolean *Enabled)
01098 {
01099         geXForm3d Transform;
01100 
01101         assert( geActor_IsValid(A) != GE_FALSE);
01102         assert( Box != NULL );
01103         assert( Enabled != NULL );
01104 
01105         gePose_GetJointTransform( A->Pose,
01106                                                                 A->RenderHintExtBoxCenterBoneIndex,
01107                                                                 &Transform);    
01108         assert ( geXForm3d_IsOrthonormal(&Transform) != GE_FALSE );
01109 
01110         *Box = A->RenderHintExtBox;
01111         geExtBox_Translate ( Box, Transform.Translation.X,
01112                                                           Transform.Translation.Y,
01113                                                           Transform.Translation.Z );
01114         
01115         *Enabled = A->RenderHintExtBoxEnabled;
01116         return GE_TRUE;
01117 }
01118 
01119         // Sets a rendering hint bounding box from the actor
01120 GENESISAPI geBoolean GENESISCC geActor_SetRenderHintExtBox(geActor *A, const geExtBox *Box, 
01121                                                                                                 const char *CenterOnThisNamedBone)
01122 {
01123         assert( geActor_IsValid(A) != GE_FALSE);
01124         assert( Box != NULL );
01125         assert( Box->Max.X >= Box->Min.X );
01126         assert( Box->Max.Y >= Box->Min.Y );
01127         assert( Box->Max.Z >= Box->Min.Z );
01128         
01129         if (geActor_GetBoneIndex(A,CenterOnThisNamedBone,&(A->RenderHintExtBoxCenterBoneIndex))==GE_FALSE)
01130                 {
01131                         geErrorLog_AddString(-1,"Named bone for render hint box not found", CenterOnThisNamedBone);
01132                         return GE_FALSE;
01133                 }
01134                 
01135         A->RenderHintExtBox = *Box;
01136         if (   (Box->Min.X == 0.0f) && (Box->Max.X == 0.0f)
01137                 && (Box->Min.Y == 0.0f) && (Box->Max.Y == 0.0f) 
01138                 && (Box->Min.Z == 0.0f) && (Box->Max.Z == 0.0f) )
01139                 {
01140                         A->RenderHintExtBoxEnabled = GE_FALSE;
01141                 }
01142         else
01143                 {
01144                         A->RenderHintExtBoxEnabled = GE_TRUE;
01145                 }
01146 
01147         return GE_TRUE;
01148 }
01149 
01150 
01151 GENESISAPI void *GENESISCC geActor_GetUserData(const geActor *A)
01152 {
01153         assert( geActor_IsValid(A) != GE_FALSE);
01154         return A->UserData;
01155 }
01156 
01157 GENESISAPI void GENESISCC geActor_SetUserData(geActor *A, void *UserData)
01158 {
01159         assert( geActor_IsValid(A) != GE_FALSE);
01160         A->UserData = UserData;
01161 }
01162 
01163 #define MAX(aa,bb)   ( (aa)>(bb)?(aa):(bb) )
01164 #define MIN(aa,bb)   ( (aa)<(bb)?(aa):(bb) )
01165 
01166 static void GENESISCC geActor_StretchBoundingBox( geVec3d *Min, geVec3d *Max,
01167                                                         const geVec3d *Corner, 
01168                                                         const geVec3d *DX, const geVec3d *DY, const geVec3d *DZ)
01169 {
01170         geVec3d P;
01171 
01172         P = *Corner;
01173         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01174         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01175 
01176         geVec3d_Add     (Corner ,DX,&P);
01177         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01178         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01179 
01180         geVec3d_Add     (&P, DZ,&P);
01181         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01182         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01183 
01184         geVec3d_Subtract(&P,DX,&P);
01185         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01186         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01187 
01188         geVec3d_Add     (&P,DY,&P);
01189         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01190         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01191 
01192         geVec3d_Add     (&P,DX,&P);
01193         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01194         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01195 
01196         geVec3d_Subtract(&P,DZ,&P);
01197         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01198         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01199 
01200         geVec3d_Subtract(&P,DX,&P);
01201         Min->X = MIN(Min->X,P.X);       Min->Y = MIN(Min->Y,P.Y);       Min->Z = MIN(Min->Z,P.Z);
01202         Max->X = MAX(Max->X,P.X);       Max->Y = MAX(Max->Y,P.Y);       Max->Z = MAX(Max->Z,P.Z);
01203 }
01204 
01205 //      eaa3 07/27/2000
01206 
01207 GENESISAPI int geActor_GetBoneCount(const geActor *A)
01208 {
01209         return geBody_GetBoneCount( A->ActorDefinition->Body );
01210 }
01211 
01212 GENESISAPI geBoolean GENESISCC geActor_GetDynamicExtBox( const geActor *A, geExtBox *ExtBox)
01213 {
01214 #define GE_ACTOR_REALLY_BIG_NUMBER (9e9f)
01215 
01216         geVec3d Corner;
01217         geVec3d DX;
01218         geVec3d DY;
01219         geVec3d DZ;
01220         int Count,i,BCount;
01221 
01222         assert( geActor_IsValid(A) != GE_FALSE);
01223         assert( A->ActorDefinition->Body   != NULL );
01224 
01225         geVec3d_Set(&(ExtBox->Min),
01226                         GE_ACTOR_REALLY_BIG_NUMBER,GE_ACTOR_REALLY_BIG_NUMBER,GE_ACTOR_REALLY_BIG_NUMBER);
01227         geVec3d_Set(&(ExtBox->Max),
01228                         -GE_ACTOR_REALLY_BIG_NUMBER,-GE_ACTOR_REALLY_BIG_NUMBER,-GE_ACTOR_REALLY_BIG_NUMBER);
01229                 
01230         BCount = 0;
01231         Count = geBody_GetBoneCount( A->ActorDefinition->Body );
01232         for (i=0; i< Count; i++)
01233                 {
01234                         if (geActor_GetBoneBoundingBoxByIndex(A,i,&Corner,&DX,&DY,&DZ)!=GE_FALSE)
01235                                 {
01236                                         geActor_StretchBoundingBox( &(ExtBox->Min),
01237                                                                                                 &(ExtBox->Max),&Corner,&DX,&DY,&DZ);
01238                                         BCount ++;
01239                                 }
01240                 }
01241         if (BCount>0)
01242                 {
01243                         return GE_TRUE;
01244                 }
01245         return GE_FALSE;
01246 }
01247 
01248 
01249 
01250 GENESISAPI geBoolean GENESISCC geActor_Attach( geActor *Slave,  const char *SlaveBoneName,
01251                                                 const geActor *Master, const char *MasterBoneName, 
01252                                                 const geXForm3d *Attachment)
01253 {
01254         int SlaveBoneIndex,MasterBoneIndex;
01255 
01256         assert( geActor_IsValid(Slave) != GE_FALSE);
01257         assert( geActor_IsValid(Master) != GE_FALSE);
01258         assert( geXForm3d_IsOrthonormal(Attachment) != GE_FALSE );
01259         
01260         assert( MasterBoneName != NULL );               // might this be possible?
01261         
01262         if (geActor_GetBoneIndex(Slave,SlaveBoneName,&(SlaveBoneIndex))==GE_FALSE)
01263                 {
01264                         geErrorLog_AddString(-1,"Named bone for slave not found", SlaveBoneName);
01265                         return GE_FALSE;
01266                 }
01267         
01268         if (geActor_GetBoneIndex(Master,MasterBoneName,&(MasterBoneIndex))==GE_FALSE)
01269                 {
01270                         geErrorLog_AddString(-1,"Named bone for master not found", MasterBoneName);
01271                         return GE_FALSE;
01272                 }
01273         
01274         return gePose_Attach(   Slave->Pose,   SlaveBoneIndex,
01275                                                         Master->Pose, MasterBoneIndex, 
01276                                                         Attachment);
01277 }
01278 
01279 
01280 GENESISAPI void GENESISCC geActor_Detach(geActor *A)
01281 {
01282         assert( geActor_IsValid(A) != GE_FALSE);
01283 
01284         gePose_Detach( A->Pose );
01285 }
01286 
01287 
01288 GENESISAPI geBoolean GENESISCC geActor_GetBoneAttachment(const geActor *A,
01289                                                                 const char *BoneName,
01290                                                                 geXForm3d *Attachment)
01291 {
01292 
01293         int BoneIndex;
01294         assert( geActor_IsValid(A) != GE_FALSE);
01295         assert( Attachment != NULL );
01296         
01297         if (geActor_GetBoneIndex(A,BoneName,&(BoneIndex))==GE_FALSE)
01298                 {
01299                         geErrorLog_AddString(-1,"Named bone not found", BoneName);
01300                         return GE_FALSE;
01301                 }
01302         
01303         gePose_GetJointAttachment(A->Pose,BoneIndex, Attachment);
01304         assert ( geXForm3d_IsOrthonormal(Attachment) != GE_FALSE );
01305 
01306         return GE_TRUE;
01307 }
01308 
01309 GENESISAPI geBoolean GENESISCC geActor_SetBoneAttachment(geActor *A,
01310                                                                 const char *BoneName,
01311                                                                 geXForm3d *Attachment)
01312 {
01313 
01314         int BoneIndex;
01315 
01316         assert( geActor_IsValid(A) != GE_FALSE);
01317         assert( geXForm3d_IsOrthonormal(Attachment) != GE_FALSE );
01318         
01319         if (geActor_GetBoneIndex(A,BoneName,&(BoneIndex))==GE_FALSE)
01320                 {
01321                         geErrorLog_AddString(-1,"Named bone not found", BoneName);
01322                         return GE_FALSE;
01323                 }
01324         
01325         gePose_SetJointAttachment(A->Pose,BoneIndex, Attachment);
01326         return GE_TRUE;
01327 }
01328 
01329 
01330 //-------------------------------------------------------------------------------------------------
01331 // Actor Cuing system
01332 //-------------------------------------------------------------------------------------------------
01333 #define ACTOR_CUE_MINIMUM_BLEND (0.0001f)
01334 #define ACTOR_CUE_MAXIMUM_BLEND (0.999f)
01335 
01336 
01337 static geBoolean GENESISCC geActor_IsAnimationCueDead(geActor *A, int Index)
01338 {
01339         geBoolean Kill= GE_FALSE;
01340         geFloat BlendAmount;
01341         geMotion *M;
01342         assert( geActor_IsValid(A) != GE_FALSE);
01343         assert( (Index>=0) && (Index<geMotion_GetSubMotionCount(A->CueMotion)));
01344 
01345         M = A->CueMotion;
01346 
01347         BlendAmount = geMotion_GetBlendAmount(M,Index,0.0f);
01348         if (BlendAmount <= ACTOR_CUE_MINIMUM_BLEND)
01349                 {
01350                         int KeyCount;
01351                         gePath *P; 
01352                         geFloat KeyTime;
01353 
01354                         P = geMotion_GetBlendPath(M,Index);
01355                         assert( P != NULL );
01356                         KeyCount = gePath_GetKeyframeCount(P,GE_PATH_TRANSLATION_CHANNEL);
01357                         if (KeyCount>0)
01358                                 {
01359                                         geXForm3d Dummy;
01360                                         geFloat TimeOffset = -geMotion_GetTimeOffset( M, Index);
01361                                         gePath_GetKeyframe( P, KeyCount-1, GE_PATH_TRANSLATION_CHANNEL, &KeyTime, &Dummy );
01362         
01363                                         if ( KeyTime <= TimeOffset )
01364                                                 {
01365                                                         Kill = GE_TRUE;
01366                                                 }
01367                                 }
01368                         else
01369                                 {
01370                                         Kill = GE_TRUE;
01371                                 }
01372                 }
01373         return Kill;
01374 }
01375 
01376 
01377 static void GENESISCC geActor_KillCue( geActor *A, int Index )
01378 {
01379         geMotion *M;
01380         assert( geActor_IsValid(A) != GE_FALSE);
01381         assert( (Index>=0) && (Index<geMotion_GetSubMotionCount(A->CueMotion)));
01382         M  = geMotion_RemoveSubMotion(A->CueMotion,Index);
01383 }
01384 
01385 GENESISAPI geBoolean GENESISCC geActor_AnimationNudge(geActor *A, geXForm3d *Offset)
01386 {
01387         geMotion *M;
01388         int i,Count;
01389         assert( geActor_IsValid(A) != GE_FALSE);
01390         assert( geXForm3d_IsOrthonormal(Offset) != GE_FALSE );
01391         M = A->CueMotion;
01392         Count = geMotion_GetSubMotionCount(M);
01393         
01394         for (i=Count-1; i>=0; i--)      
01395                 {
01396                         geXForm3d Transform;
01397                         const geXForm3d *pTransform;
01398                         pTransform = geMotion_GetBaseTransform( M, i );
01399                         if ( pTransform != NULL )
01400                                 {
01401                                         Transform = *pTransform;
01402                         
01403                                         geXForm3d_Multiply(Offset,&Transform,&Transform);
01404                                         geXForm3d_Orthonormalize(&Transform);
01405 
01406                                         geMotion_SetBaseTransform( M, i, &Transform);
01407                                 }
01408                 }
01409         return GE_TRUE;
01410 }
01411 
01412 GENESISAPI geBoolean GENESISCC geActor_AnimationRemoveLastCue( geActor *A )
01413 {
01414         int Count;
01415         assert( geActor_IsValid(A) != GE_FALSE);
01416         Count = geMotion_GetSubMotionCount(A->CueMotion);
01417         if (Count>0)
01418                 {
01419                         geActor_KillCue( A, Count-1 );
01420                         return GE_TRUE;
01421                 }
01422         return GE_FALSE;
01423 }
01424 
01425 GENESISAPI geBoolean GENESISCC geActor_AnimationCue( geActor *A, 
01426                                                                 geMotion *Motion,
01427                                                                 geFloat TimeScaleFactor,
01428                                                                 geFloat TimeIntoMotion,
01429                                                                 geFloat BlendTime, 
01430                                                                 geFloat BlendFromAmount, 
01431                                                                 geFloat BlendToAmount,
01432                                                                 const geXForm3d *MotionTransform)
01433 {
01434         int Index;
01435 
01436         assert( geActor_IsValid(A) != GE_FALSE);
01437 
01438         assert( (BlendFromAmount>=0.0f) && (BlendFromAmount<=1.0f));
01439         assert( (  BlendToAmount>=0.0f) && (  BlendToAmount<=1.0f));
01440         assert( (MotionTransform==NULL) || (geXForm3d_IsOrthonormal(MotionTransform)) != GE_FALSE );
01441 
01442         assert( Motion != NULL );
01443         
01444         assert( BlendTime >= 0.0f);
01445         if (BlendTime==0.0f)
01446                 {
01447                         BlendFromAmount = BlendToAmount;
01448                         BlendTime = 1.0f;       // anything that is > GE_TKA_TIME_TOLERANCE
01449                 }
01450 
01451         if (geMotion_AddSubMotion( A->CueMotion, TimeScaleFactor, -TimeIntoMotion, Motion, 
01452                                                         TimeIntoMotion, BlendFromAmount, 
01453                                                         TimeIntoMotion + BlendTime, BlendToAmount, 
01454                                                         MotionTransform, &Index )==GE_FALSE)
01455                 {       
01456                         return GE_FALSE;
01457                 }
01458                 
01459         return GE_TRUE;
01460 }
01461 
01462 
01463 GENESISAPI geBoolean GENESISCC geActor_AnimationStep(geActor *A, geFloat DeltaTime )
01464 {
01465         int i,Coverage,Count;
01466         geMotion *M;
01467         geMotion *SubM;
01468         
01469         assert( geActor_IsValid(A) != GE_FALSE);
01470         assert( DeltaTime >= 0.0f );
01471         
01472         gePose_ClearCoverage(A->Pose,0);
01473 
01474         M = A->CueMotion;
01475 
01476         Count = geMotion_GetSubMotionCount(M);
01477 
01478         for (i=Count-1; i>=0; i--)      
01479                 {
01480                         geFloat TimeOffset = geMotion_GetTimeOffset( M, i );
01481                         TimeOffset = TimeOffset - DeltaTime;
01482                         geMotion_SetTimeOffset( M, i, TimeOffset);
01483 
01484                         if (geActor_IsAnimationCueDead(A,i))
01485                                 {
01486                                         geActor_KillCue(A,i);
01487                                 }
01488                         else
01489                                 {
01490                                         geBoolean SetWithBlending= GE_TRUE;
01491                                         geFloat BlendAmount;
01492                                         
01493                                         SubM = geMotion_GetSubMotion(M,i);
01494                                         assert( SubM != NULL );
01495                                         
01496                                         BlendAmount = geMotion_GetBlendAmount( M,i,0.0f );
01497                                         
01498                                         if (BlendAmount >= ACTOR_CUE_MAXIMUM_BLEND)
01499                                                 {
01500                                                         SetWithBlending = GE_FALSE;
01501                                                 }
01502                                         Coverage = gePose_AccumulateCoverage(A->Pose,SubM, SetWithBlending);
01503                                         if ( Coverage == 0 )
01504                                                 {
01505                                                         geActor_KillCue(A,i);
01506                                                 }
01507                                 }
01508                 }
01509 
01510         gePose_SetMotion( A->Pose, M, 0.0f, NULL );
01511         geMotion_SetupEventIterator(M,-DeltaTime,0.0f);
01512 
01513         return GE_TRUE;
01514 }
01515 
01516 
01517 GENESISAPI geBoolean GENESISCC geActor_AnimationStepBoneOptimized(geActor *A, geFloat DeltaTime, const char *BoneName )
01518 {
01519         int i,Coverage,Count;
01520         geMotion *M;
01521         geMotion *SubM;
01522         
01523         assert( geActor_IsValid(A) != GE_FALSE);
01524         assert( DeltaTime >= 0.0f );
01525         
01526         if (BoneName == NULL)
01527                 {
01528                         A->StepBoneIndex = GE_POSE_ROOT_JOINT;
01529                 }
01530         else
01531                 {
01532                         geBoolean LookupBoneName= GE_TRUE;
01533                         const char *LastBoneName;
01534                         geXForm3d Attachment;
01535                         int LastParentBoneIndex;
01536                         if (A->StepBoneIndex >= 0)
01537                                 {
01538                                         geBody_GetBone( A->ActorDefinition->Body,A->StepBoneIndex,&LastBoneName,&Attachment,&LastParentBoneIndex);
01539                                         if (  (LastBoneName != NULL) )
01540                                                 if (strcmp(LastBoneName,BoneName)==0) 
01541                                                         LookupBoneName = GE_FALSE;
01542                                 }
01543                         if (LookupBoneName != GE_FALSE)
01544                                 {
01545                                         if (geActor_GetBoneIndex(A,BoneName,&(A->StepBoneIndex))==GE_FALSE)
01546                                                 {
01547                                                         geErrorLog_AddString(-1,"Named bone not found", BoneName);
01548                                                         return GE_FALSE;
01549                                                 }
01550                                 }
01551                 }
01552                         
01553 
01554         gePose_ClearCoverage(A->Pose,0);
01555 
01556         M = A->CueMotion;
01557 
01558         Count = geMotion_GetSubMotionCount(M);
01559 
01560         for (i=Count-1; i>=0; i--)      
01561                 {
01562                         geFloat TimeOffset = geMotion_GetTimeOffset( M, i );
01563                         TimeOffset = TimeOffset - DeltaTime;
01564                         geMotion_SetTimeOffset( M, i, TimeOffset);
01565 
01566                         if (geActor_IsAnimationCueDead(A,i))
01567                                 {
01568                                         geActor_KillCue(A,i);
01569                                 }
01570                         else
01571                                 {
01572                                         geBoolean SetWithBlending= GE_TRUE;
01573                                         geFloat BlendAmount;
01574                                         
01575                                         SubM = geMotion_GetSubMotion(M,i);
01576                                         assert( SubM != NULL );
01577                                         
01578                                         BlendAmount = geMotion_GetBlendAmount( M,i,0.0f );
01579                                         
01580                                         if (BlendAmount >= ACTOR_CUE_MAXIMUM_BLEND)
01581                                                 {
01582                                                         SetWithBlending = GE_FALSE;
01583                                                 }
01584                                         Coverage = gePose_AccumulateCoverage(A->Pose,SubM, SetWithBlending);
01585                                         if ( Coverage == 0 )
01586                                                 {
01587                                                         geActor_KillCue(A,i);
01588                                                 }
01589                                 }
01590                 }
01591 
01592         gePose_SetMotionForABone( A->Pose, M, 0.0f, NULL, A->StepBoneIndex );
01593         geMotion_SetupEventIterator(M,-DeltaTime,0.0f);
01594 
01595         return GE_TRUE;
01596 }
01597 
01598 
01599                 
01600 GENESISAPI geBoolean GENESISCC geActor_AnimationTestStep(geActor *A, geFloat DeltaTime)
01601 {
01602         assert( geActor_IsValid(A) != GE_FALSE);
01603         assert( DeltaTime >= 0.0f );
01604 
01605         gePose_SetMotion( A->Pose, A->CueMotion , DeltaTime, NULL );
01606 
01607         return GE_TRUE;
01608 }
01609 
01610 GENESISAPI geBoolean GENESISCC geActor_AnimationTestStepBoneOptimized(geActor *A, geFloat DeltaTime, const char *BoneName)
01611 {
01612         assert( geActor_IsValid(A) != GE_FALSE);
01613         assert( DeltaTime >= 0.0f );
01614 
01615         if (BoneName == NULL)
01616                 {
01617                         A->StepBoneIndex = GE_POSE_ROOT_JOINT;
01618                 }
01619         else
01620                 {
01621                         geBoolean LookupBoneName= GE_TRUE;
01622                         const char *LastBoneName;
01623                         geXForm3d Attachment;
01624                         int LastParentBoneIndex;
01625                         if (A->StepBoneIndex >= 0)
01626                                 {
01627                                         geBody_GetBone( A->ActorDefinition->Body,A->StepBoneIndex,&LastBoneName,&Attachment,&LastParentBoneIndex);
01628                                         if (  (LastBoneName != NULL) )
01629                                                 if (strcmp(LastBoneName,BoneName)==0) 
01630                                                         LookupBoneName = GE_FALSE;
01631                                 }
01632                         if (LookupBoneName != GE_FALSE)
01633                                 {
01634                                         if (geActor_GetBoneIndex(A,BoneName,&(A->StepBoneIndex))==GE_FALSE)
01635                                                 {
01636                                                         geErrorLog_AddString(-1,"Named bone not found", BoneName);
01637                                                         return GE_FALSE;
01638                                                 }
01639                                 }
01640                 }
01641         gePose_SetMotionForABone( A->Pose, A->CueMotion , DeltaTime, NULL,A->StepBoneIndex );
01642 
01643         return GE_TRUE;
01644 }
01645 
01646 
01647 
01648 GENESISAPI geBoolean GENESISCC geActor_GetAnimationEvent(
01649         geActor *A,                                             
01650         const char **ppEventString)             // Return data, if found
01651         // returns the event string for the 'next' event that occured during the last 
01652         // animation step time delta.
01653         // if the return value is GE_FALSE, there are no more events, and ppEventString will be Empty
01654 {
01655         geFloat Time;
01656         assert( geActor_IsValid(A) != GE_FALSE);
01657 
01658         return geMotion_GetNextEvent(A->CueMotion, &Time, ppEventString );
01659 }
01660 
01661 
01662 #ifndef NDEBUG
01663 static geBoolean GENESISCC geActor_TransformCompare(const geXForm3d *T1, const geXForm3d *T2)
01664 {
01665         #define SINGLE_TERM_ERROR_THRESHOLD (0.0001f)
01666         if (fabs(T1->AX - T2->AX)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01667         if (fabs(T1->BX - T2->BX)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01668         if (fabs(T1->CX - T2->CX)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01669         if (fabs(T1->AY - T2->AY)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01670         if (fabs(T1->BY - T2->BY)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01671         if (fabs(T1->CY - T2->CY)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01672         if (fabs(T1->AZ - T2->AZ)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01673         if (fabs(T1->BZ - T2->BZ)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01674         if (fabs(T1->CZ - T2->CZ)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01675         
01676         if (fabs(T1->Translation.X - T2->Translation.X)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01677         if (fabs(T1->Translation.Y - T2->Translation.Y)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01678         if (fabs(T1->Translation.Z - T2->Translation.Z)>SINGLE_TERM_ERROR_THRESHOLD) return GE_FALSE;
01679         return GE_TRUE;
01680 }
01681 #endif
01682 
01683 
01684 
01685 GENESISAPI geBoolean GENESISCC geActor_GetLightingOptions(const geActor *Actor,
01686         geBoolean *UseFillLight,
01687         geVec3d *FillLightNormal,
01688         geFloat *FillLightRed,                          
01689         geFloat *FillLightGreen,                                
01690         geFloat *FillLightBlue,                         
01691         geFloat *AmbientLightRed,                       
01692         geFloat *AmbientLightGreen,                     
01693         geFloat *AmbientLightBlue,                      
01694         geBoolean *UseAmbientLightFromFloor,
01695         int *MaximumDynamicLightsToUse,         
01696         const char **LightReferenceBoneName,
01697         geBoolean *PerBoneLighting)
01698 {
01699         int BoneIndex;
01700         assert( geActor_IsValid(Actor)!=GE_FALSE );
01701 
01702         assert( UseFillLight != NULL );
01703         assert( FillLightNormal != NULL );
01704         assert( FillLightRed != NULL ); 
01705         assert( FillLightGreen != NULL );       
01706         assert( FillLightBlue != NULL );        
01707         assert( AmbientLightRed != NULL );
01708         assert( AmbientLightGreen != NULL );                    
01709         assert( AmbientLightBlue != NULL );                     
01710         assert( UseAmbientLightFromFloor != NULL );
01711         assert( MaximumDynamicLightsToUse != NULL );    
01712         assert( LightReferenceBoneName != NULL );
01713 
01714         if (Actor->Puppet == NULL)
01715                 {
01716                         geErrorLog_AddString(-1,"Can't set lighting options until actor is prepared for rendering", NULL);
01717                         return GE_FALSE;
01718                 }
01719         
01720         gePuppet_GetLightingOptions(    Actor->Puppet,
01721                                                                         UseFillLight,
01722                                                                         FillLightNormal,
01723                                                                         FillLightRed,   
01724                                                                         FillLightGreen, 
01725                                                                         FillLightBlue,  
01726                                                                         AmbientLightRed,
01727                                                                         AmbientLightGreen,              
01728                                                                         AmbientLightBlue,               
01729                                                                         UseAmbientLightFromFloor,
01730                                                                         MaximumDynamicLightsToUse,
01731                                                                         &BoneIndex,
01732                                                                         PerBoneLighting);
01733 
01734         if (BoneIndex>=0 && (BoneIndex < geBody_GetBoneCount(Actor->ActorDefinition->Body)))
01735                 {
01736                         geXForm3d DummyAttachment;
01737                         int DummyParentBoneIndex;
01738                         geBody_GetBone( Actor->ActorDefinition->Body,
01739                                                         BoneIndex,
01740                                                         LightReferenceBoneName,
01741                                                         &DummyAttachment,
01742                                                         &DummyParentBoneIndex);
01743                 }
01744         else
01745                 {
01746                         LightReferenceBoneName = NULL;
01747                 }
01748 
01749         return GE_TRUE; // CB
01750 }
01751 
01752 //Actor-level environmental mapping code
01753 GENESISAPI void GENESISCC geActor_SetEnvironOptions( geActor *A, geEnvironmentOptions *opts )
01754 {
01755         assert ( geActor_IsValid(A) != GE_FALSE );
01756         assert ( A->Puppet != NULL );
01757         gePuppet_SetEnvironmentOptions( A->Puppet, opts );
01758 }
01759 
01760 GENESISAPI geEnvironmentOptions GENESISCC geActor_GetEnvironOptions( geActor *A )
01761 {
01762         assert ( geActor_IsValid(A) != GE_FALSE );
01763         assert ( A->Puppet != NULL );
01764         return gePuppet_GetEnvironmentOptions( A->Puppet );
01765 }
01766 
01767 GENESISAPI geBoolean GENESISCC geActor_SetLightingOptions(geActor *A,
01768         geBoolean UseFillLight,
01769         const geVec3d *FillLightNormal,
01770         geFloat FillLightRed,                           // 0 .. 255
01771         geFloat FillLightGreen,                         // 0 .. 255
01772         geFloat FillLightBlue,                          // 0 .. 255
01773         geFloat AmbientLightRed,                        // 0 .. 255
01774         geFloat AmbientLightGreen,                      // 0 .. 255
01775         geFloat AmbientLightBlue,                       // 0 .. 255
01776         geBoolean AmbientLightFromFloor,
01777         int MaximumDynamicLightsToUse,          // 0 for none
01778         const char *LightReferenceBoneName,
01779         geBoolean PerBoneLighting       )
01780 {
01781         int BoneIndex;
01782 
01783         assert( geActor_IsValid(A)!=GE_FALSE );
01784         assert( FillLightNormal != NULL );
01785         
01786         if (A->Puppet == NULL)
01787                 {
01788                         geErrorLog_AddString(-1,"Can't set lighting options until actor is prepared for rendering", NULL);
01789                         return GE_FALSE;
01790                 }
01791         if (geActor_GetBoneIndex(A,LightReferenceBoneName,&BoneIndex)==GE_FALSE)
01792                 {
01793                         geErrorLog_AddString(-1,"Named bone for light reference not found", LightReferenceBoneName);
01794                         return GE_FALSE;
01795                 }
01796 
01797         gePuppet_SetLightingOptions(    A->Puppet,
01798                                                                         UseFillLight,
01799                                                                         FillLightNormal,
01800                                                                         FillLightRed,   
01801                                                                         FillLightGreen, 
01802                                                                         FillLightBlue,  
01803                                                                         AmbientLightRed,
01804                                                                         AmbientLightGreen,              
01805                                                                         AmbientLightBlue,               
01806                                                                         AmbientLightFromFloor,
01807                                                                         MaximumDynamicLightsToUse,
01808                                                                         BoneIndex,
01809                                                                         PerBoneLighting);
01810         return GE_TRUE;
01811 }
01812 
01813 GENESISAPI void GENESISCC geActor_SetScale(geActor *A, geFloat ScaleX,geFloat ScaleY,geFloat ScaleZ)
01814 {
01815         geVec3d S;
01816         assert( A != NULL );
01817                 
01818         geVec3d_Set(&S,ScaleX,ScaleY,ScaleZ);
01819         gePose_SetScale(A->Pose,&S);
01820 }
01821 
01822 
01823 
01824 GENESISAPI geBoolean GENESISCC geActor_SetShadow(geActor *A, 
01825                 geBoolean DoShadow, 
01826                 geFloat Radius,
01827                 const geBitmap *ShadowMap,
01828                 const char *BoneName)
01829 {
01830         int BoneIndex;
01831 
01832         assert( geActor_IsValid(A)!=GE_FALSE );
01833         assert( (DoShadow==GE_FALSE) || (DoShadow==GE_TRUE));
01834         assert( Radius >= 0.0f);
01835         
01836         if (A->Puppet == GE_FALSE)
01837                 {
01838                         geErrorLog_AddString(-1,"Can't set shadow options until actor is prepared for rendering", NULL);
01839                         return GE_FALSE;
01840                 }
01841         
01842         if (geActor_GetBoneIndex(A,BoneName,&BoneIndex)==GE_FALSE)
01843                 {
01844                         geErrorLog_AddString(-1,"Named bone for shadow not found", BoneName);
01845                         return GE_FALSE;
01846                 }
01847 
01848         gePuppet_SetShadow(A->Puppet,DoShadow,Radius,ShadowMap,BoneIndex);
01849 
01850         return GE_TRUE;
01851 }
01852 
01853 
01854 geBoolean GENESISCC geActor_RenderPrep( geActor *A, geWorld *World)
01855 {
01856         assert( geActor_IsValid(A) != GE_FALSE );
01857         #pragma message ("need to make a world method that does this. so World doesn't get passed in")
01858         assert( geActor_DefIsValid(A->ActorDefinition) != GE_FALSE );
01859         assert( geBody_IsValid(A->ActorDefinition->Body) != GE_FALSE );
01860 
01861         if (A->Puppet!=NULL)
01862                 {
01863                         gePuppet_Destroy(&(A->Puppet));
01864                         A->Puppet =NULL;
01865                 }
01866                 
01867         A->Puppet = gePuppet_Create(A->ActorDefinition->TextureFileContext, A->ActorDefinition->Body,World);
01868         if ( A->Puppet == NULL )
01869                 {
01870                         geErrorLog_Add( ERR_ACTOR_RENDER_PREP , NULL);
01871                         return GE_FALSE;
01872                 }
01873         {
01874                 geExtBox EB;
01875                 //initialize body bounding box
01876                 geActor_GetDynamicExtBox(A, &EB);
01877                 geBody_SetBoundingBox(A->ActorDefinition->Body, GE_BODY_ROOT, &EB.Min,    &EB.Max);
01878                 if (geActor_GetBoneExtBoxByIndex(A,GE_POSE_ROOT_JOINT,&EB) == GE_FALSE)
01879                         {
01880                                 geErrorLog_AddString(-1,"Failure to get Root Bounding box from puppet", NULL);
01881                                 return GE_FALSE;                        
01882                         }
01883                 
01884                 A->BoundingBoxMinCorner = EB.Min;
01885                 A->BoundingBoxMaxCorner = EB.Max;
01886         }
01887         
01888         return GE_TRUE;
01889 }
01890 
01891 geBoolean GENESISCC geActor_RenderThroughFrustum(const geActor *A, geEngine *Engine, geWorld *World,geCamera *Camera, Frustum_Info *FInfo)
01892 {
01893         geExtBox        Box;
01894 
01895         assert( geActor_IsValid(A) != GE_FALSE );
01896         assert( A->Puppet != NULL );
01897 
01898         if (!geActor_GetDynamicExtBox( A, &Box))
01899         {
01900                         geErrorLog_AddString(-1, "geActor_RenderThroughFrustum:  geActor_GetDynamicAABoundingBox failed.", NULL);
01901                         return GE_FALSE;
01902         }
01903 
01904         if (gePuppet_RenderThroughFrustum( A->Puppet, A->Pose, &Box, Engine, World, Camera, FInfo)==GE_FALSE)
01905                 {
01906                         geErrorLog_Add( ERR_ACTOR_RENDER_FAILED , NULL);
01907                         return GE_FALSE;
01908                 }
01909         return GE_TRUE;
01910 }
01911 
01912 geBoolean GENESISCC geActor_Render(const geActor *A, geEngine *Engine, geWorld *World,geCamera *Camera)
01913 {
01914         assert( geActor_IsValid(A) != GE_FALSE );
01915         assert( A->Puppet != NULL );
01916 
01917         if (A->RenderHintExtBoxEnabled)
01918                 {
01919                         geBoolean Enabled;
01920                         geExtBox Box;
01921                         if (geActor_GetRenderHintExtBox(A, &Box, &Enabled)==GE_FALSE)
01922                                 {
01923                                         geErrorLog_Add( -1 , NULL);     //?
01924                                         return GE_FALSE;
01925                                 }
01926                         if (gePuppet_Render( A->Puppet, A->Pose, Engine,World, Camera, &Box )==GE_FALSE)
01927                                 {
01928                                         geErrorLog_Add( ERR_ACTOR_RENDER_FAILED , NULL);
01929                                         return GE_FALSE;
01930                                 }
01931                 }
01932         else
01933                 {
01934                         if (gePuppet_Render( A->Puppet, A->Pose, Engine,World, Camera, NULL )==GE_FALSE)
01935                                 {
01936                                         geErrorLog_Add( ERR_ACTOR_RENDER_FAILED , NULL);
01937                                         return GE_FALSE;
01938                                 }
01939                 }
01940         return GE_TRUE;
01941 }
01942 
01943 GENESISAPI int GENESISCC geActor_GetMaterialCount(const geActor *A)
01944 {
01945         assert( geActor_IsValid(A) != GE_FALSE );
01946         assert( A->Puppet != NULL );
01947 
01948         return gePuppet_GetMaterialCount( A->Puppet );
01949 }
01950 
01951 GENESISAPI geBoolean GENESISCC geActor_GetMaterial(const geActor *A, int MaterialIndex,
01952                                                                                 geBitmap **Bitmap, geFloat *Red, geFloat *Green, geFloat *Blue)
01953 {
01954         assert( geActor_IsValid(A) != GE_FALSE );
01955         assert( A->Puppet != NULL );
01956 
01957         return gePuppet_GetMaterial(A->Puppet, MaterialIndex, Bitmap, Red, Green, Blue );
01958 }
01959 
01960 
01961 GENESISAPI geBoolean GENESISCC geActor_SetMaterial(geActor *A, int MaterialIndex,
01962                                                                                 geBitmap *Bitmap,  geFloat Red,  geFloat Green,  geFloat Blue)
01963 {
01964         assert( geActor_IsValid(A) != GE_FALSE );
01965         assert( A->Puppet != NULL );
01966 
01967         return gePuppet_SetMaterial(A->Puppet,MaterialIndex, Bitmap, Red, Green, Blue );
01968 }
01969 
01970 GENESISAPI geBoolean GENESISCC geActor_SetStaticLightingOptions(geActor *A,     geBoolean AmbientLightFromStaticLights, geBoolean TestRayCollision,     int MaxStaticLightsToUse        )
01971 {       assert( geActor_IsValid(A)!=GE_FALSE );
01972                 if (A->Puppet == NULL)
01973                 {                       
01974                         geErrorLog_AddString(-1,"Can't set lighting options until actor is prepared for rendering", NULL);
01975                         return GE_FALSE;                
01976                 }
01977                 gePuppet_SetStaticLightingOptions( A->Puppet,
01978                                                                   AmbientLightFromStaticLights,
01979                                                                   MaxStaticLightsToUse,
01980                                                                   TestRayCollision
01981                                                                   );
01982                 return GE_TRUE;
01983 }
01984 
01985 GENESISAPI geBoolean GENESISCC geActor_GetStaticLightingOptions(        const geActor *Actor,   geBoolean *UseAmbientLightFromStaticLights,     geBoolean *TestRayCollision,    int *MaxStaticLightsToUse       )
01986 {       assert( geActor_IsValid(Actor)!=GE_FALSE );
01987         assert( UseAmbientLightFromStaticLights != NULL );
01988         assert( TestRayCollision != NULL );
01989         if (Actor->Puppet == NULL)
01990         {
01991                 geErrorLog_AddString(-1,"Can't set lighting options until actor is prepared    for rendering", NULL);
01992                 return GE_FALSE;
01993         }
01994 
01995         gePuppet_GetStaticLightingOptions( Actor->Puppet,
01996                                                                   UseAmbientLightFromStaticLights,
01997                                                                   TestRayCollision,
01998                                                                   MaxStaticLightsToUse
01999                                                                   );
02000         return GE_TRUE;
02001 }

Generated on Tue Sep 30 12:35:14 2003 for GTestAndEngine by doxygen 1.3.2