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

body.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  BODY.C                                                                              */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                    */
00005 /*  Description: Actor body 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 #include <assert.h>                                             //assert()
00023 #include <string.h>                                             //strlen(), strcpy()
00024 #include <math.h>                                               //fabs()
00025 #include <stdio.h>                                              //sscanf
00026 
00027 #include "body.h"
00028 #include "body._h"
00029 #include "ram.h"
00030 #include "errorlog.h"
00031 
00032 
00033 #define MAX(aa,bb)   ( (aa)>(bb)?(aa):(bb) )
00034 #define MIN(aa,bb)   ( (aa)<(bb)?(aa):(bb) )
00035 
00036 
00037 
00038 
00039 #if defined(DEBUG) || !defined(NDEBUG)
00040 static geBoolean GENESISCC geBody_SanityCheck(const geBody *B)
00041 {
00042         int i,j,k;
00043         int Lod,FaceCount,VertexCount,NormalCount,BoneCount;
00044         geBody_XSkinVertex *SV;
00045         geBody_Bone *Bone;
00046         geBody_Normal *N;
00047 
00048         Lod = B->LevelsOfDetail;
00049         VertexCount = B->XSkinVertexCount;
00050         NormalCount = B->SkinNormalCount;
00051         BoneCount   = B->BoneCount;
00052 
00053         if (B->MaterialNames == NULL )
00054                 return GE_FALSE;
00055         if (B->MaterialCount != geStrBlock_GetCount(B->MaterialNames))
00056                 return GE_FALSE;
00057 
00058         if (B->BoneNames == NULL)
00059                 return GE_FALSE;
00060         if (B->BoneCount != geStrBlock_GetCount(B->BoneNames))
00061                 return GE_FALSE;
00062 
00063         if ((B->XSkinVertexArray == NULL) && (B->XSkinVertexCount>0))
00064                 return GE_FALSE;
00065         if ((B->SkinNormalArray == NULL) && (B->SkinNormalCount>0))
00066                 return GE_FALSE;
00067         if ((B->BoneArray == NULL) && (B->BoneCount>0))
00068                 return GE_FALSE;
00069         if ((B->MaterialArray == NULL) && (B->MaterialCount>0))
00070                 return GE_FALSE;
00071 
00072 
00073         for (i=0; i<Lod; i++)
00074                 {
00075                         geBody_Triangle *F;
00076                         FaceCount = B->SkinFaces[i].FaceCount;
00077                         for (j=0,F=B->SkinFaces[i].FaceArray; j<FaceCount; j++,F++)
00078                                 {
00079                                         for (k=0; k<3; k++)
00080                                                 {
00081                                                         if ((F->VtxIndex[k]    < 0) || (F->VtxIndex[k]    >= VertexCount  ))
00082                                                                 return GE_FALSE;
00083                                                         if ((F->NormalIndex[k] < 0) || (F->NormalIndex[k] >= NormalCount  ))
00084                                                                 return GE_FALSE;
00085                                                         if ((F->MaterialIndex  < 0) || (F->MaterialIndex  >= B->MaterialCount))
00086                                                                 return GE_FALSE;
00087                                                 }
00088                                 }
00089                 }
00090         for (i=0,SV = B->XSkinVertexArray; i<VertexCount; i++,SV++)
00091                 {
00092                         if ((SV->BoneIndex < 0) || (SV->BoneIndex >= BoneCount))
00093                                 return GE_FALSE;
00094                 }
00095 
00096         for (i=0,N = B->SkinNormalArray; i<NormalCount; i++,N++)
00097                 {
00098                         if ((N->BoneIndex < 0) || (N->BoneIndex >= BoneCount))
00099                                 return GE_FALSE;
00100                 }
00101 
00102         for (i=0,Bone = B->BoneArray; i<BoneCount; i++,Bone++)
00103                 {
00104                         if (Bone->ParentBoneIndex != GE_BODY_NO_PARENT_BONE)
00105                                 {
00106                                         if ((Bone->ParentBoneIndex < 0) || (Bone->ParentBoneIndex > i))
00107                                                 return GE_FALSE;
00108                                 }
00109                 }
00110 
00111         return GE_TRUE;
00112                                 
00113 }
00114 #endif
00115 
00116 
00117 geBoolean GENESISCC geBody_IsValid(const geBody *B)
00118 {
00119         if ( B == NULL )
00120                 return GE_FALSE;
00121         if ( B -> IsValid != B )
00122                 return GE_FALSE;
00123         assert( geBody_SanityCheck(B) != GE_FALSE) ;
00124         return GE_TRUE;
00125 }
00126         
00127 
00128 static geBody *GENESISCC geBody_CreateNull(void)
00129 {
00130         geBody *B;
00131         int i;
00132 
00133         B = GE_RAM_ALLOCATE_STRUCT(geBody);
00134         if ( B == NULL)
00135                 {
00136                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00137                         return NULL;
00138                 }
00139         B->IsValid          = NULL;
00140         B->XSkinVertexCount     = 0;
00141         B->XSkinVertexArray     = NULL;
00142         
00143         B->SkinNormalCount      = 0;
00144         B->SkinNormalArray      = NULL;
00145 
00146         B->BoneCount            = 0;
00147         B->BoneArray            = NULL;
00148         B->BoneNames            = NULL;
00149                         
00150         B->MaterialCount        = 0;
00151         B->MaterialArray        = NULL;
00152         B->MaterialNames        = NULL;
00153         for (i=0; i<GE_BODY_NUMBER_OF_LOD; i++)
00154                 {
00155                         B->SkinFaces[i].FaceCount = 0;
00156                         B->SkinFaces[i].FaceArray = NULL;
00157                 }
00158         B->LevelsOfDetail = 1;
00159         B->IsValid = B;
00160 
00161         geVec3d_Set(&(B->BoundingBoxMin),0.0f,0.0f,0.0f);
00162         geVec3d_Set(&(B->BoundingBoxMax),0.0f,0.0f,0.0f);
00163         return B;
00164 }
00165 
00166 static void GENESISCC geBody_DestroyPossiblyIncompleteBody( geBody **PB ) 
00167 {
00168         geBody *B;
00169         int i;
00170 
00171         B = *PB;
00172         B->IsValid = NULL;
00173         if (B->XSkinVertexArray != NULL)
00174                 {
00175                         geRam_Free( B->XSkinVertexArray );
00176                         B->XSkinVertexArray = NULL;
00177                 }
00178         if (B->SkinNormalArray != NULL)
00179                 {
00180                         geRam_Free( B->SkinNormalArray );
00181                         B->SkinNormalArray = NULL;
00182                 }
00183         if (B->BoneNames != NULL)
00184                 {
00185                         geStrBlock_Destroy(&(B->BoneNames));
00186                         B->BoneNames = NULL;
00187                 }
00188         if (B->BoneArray != NULL)
00189                 {       
00190                         geRam_Free(B->BoneArray);
00191                         B->BoneArray = NULL;
00192                 }
00193         if (B->MaterialArray != NULL)
00194                 {
00195                         for (i=0; i<B->MaterialCount; i++)
00196                                 {
00197                                         // <> CB ; see note above
00198                                         // this doesn't seem to prevent us from crashing here
00199                                         //      when an actor has an error during _Create
00200                                         if ( (uint32)(B->MaterialArray[i].Bitmap) > 1 )
00201                                                 geBitmap_Destroy(&(B->MaterialArray[i].Bitmap));
00202                                         B->MaterialArray[i].Bitmap = NULL;
00203                                 }
00204                         geRam_Free( B->MaterialArray );
00205                         B->MaterialArray = NULL;
00206                 }
00207         if (B->MaterialNames != NULL)
00208                 {
00209                         geStrBlock_Destroy(&(B->MaterialNames));
00210                         B->MaterialNames = NULL;
00211                 }
00212         
00213         for (i=0; i<GE_BODY_NUMBER_OF_LOD; i++)
00214                 {
00215                         if (B->SkinFaces[i].FaceArray != NULL)
00216                                 {
00217                                         geRam_Free(B->SkinFaces[i].FaceArray);
00218                                         B->SkinFaces[i].FaceArray = NULL;
00219                                 }
00220                 }
00221         geRam_Free(*PB);
00222         *PB = NULL;
00223 }
00224 
00225 geBody *GENESISCC geBody_Create(void)
00226 {
00227         geBody *B;
00228 
00229         B = geBody_CreateNull();
00230         if ( B == NULL)
00231                 {
00232                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00233                         return NULL;
00234                 }
00235 
00236         B->BoneNames = geStrBlock_Create();
00237         if (B->BoneNames == NULL)
00238                 {
00239                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00240                         geBody_DestroyPossiblyIncompleteBody(&B);
00241                         return NULL;
00242                 }
00243         B->MaterialNames        = geStrBlock_Create();
00244 
00245         if (B->MaterialNames == NULL)
00246                 {
00247                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00248                         geBody_DestroyPossiblyIncompleteBody(&B);
00249                         return NULL;
00250                 }
00251 
00252         assert( geBody_SanityCheck(B) != GE_FALSE );
00253         return B;
00254 }
00255 
00256 void GENESISCC geBody_Destroy(geBody **PB)
00257 {
00258         assert(  PB != NULL );
00259         assert( *PB != NULL );
00260         assert( geBody_IsValid(*PB) != GE_FALSE );
00261         geBody_DestroyPossiblyIncompleteBody( PB );
00262 }
00263 
00264 
00265 geBoolean GENESISCC geBody_GetGeometryStats(const geBody *B, int lod, int *Vertices, int *Faces, int *Normals)
00266 {
00267         assert( geBody_IsValid(B) == GE_TRUE );
00268         assert( ( lod >=0 ) && ( lod < GE_BODY_NUMBER_OF_LOD ) );
00269         *Vertices = B->XSkinVertexCount;
00270         *Faces    = B->SkinFaces[lod].FaceCount;
00271         *Normals  = B->SkinNormalCount;
00272         return GE_TRUE;
00273 }
00274 
00275 
00276 
00277 int GENESISCC geBody_GetBoneCount(const geBody *B)
00278 {
00279         assert( B != NULL );
00280         assert( geBody_IsValid(B) != GE_FALSE );
00281         return B->BoneCount;
00282 }
00283         
00284 void GENESISCC geBody_GetBone(const geBody *B, 
00285         int BoneIndex, 
00286         const char **BoneName,
00287         geXForm3d *Attachment,
00288         int *ParentBoneIndex)
00289 {
00290         assert( B != NULL );
00291         assert( geBody_IsValid(B) != GE_FALSE );
00292         assert( Attachment != NULL );
00293         assert( ParentBoneIndex != NULL );
00294         assert(  BoneName != NULL );
00295 
00296         assert( BoneIndex >=0 );
00297         assert( BoneIndex < B->BoneCount );
00298         *Attachment = B->BoneArray[BoneIndex].AttachmentMatrix;
00299         *ParentBoneIndex = B->BoneArray[BoneIndex].ParentBoneIndex;
00300         *BoneName = geStrBlock_GetString(B->BoneNames,BoneIndex);
00301 }
00302 
00303 int32 GENESISCC geBody_GetBoneNameChecksum(const geBody *B)
00304 {
00305         assert( geBody_IsValid(B) != GE_FALSE );
00306         
00307         if (B->BoneNames != NULL)
00308                 {
00309                         return geStrBlock_GetChecksum( B->BoneNames );
00310                 }
00311         else
00312                 return 0;
00313 }
00314 
00315 
00316 geBoolean GENESISCC geBody_GetBoundingBox( const geBody *B, 
00317                                                         int BoneIndex, 
00318                                                         geVec3d *MinimumBoxCorner,
00319                                                         geVec3d *MaximumBoxCorner)
00320 {
00321         assert( B != NULL);
00322         assert( MinimumBoxCorner != NULL );
00323         assert( MaximumBoxCorner != NULL );
00324         assert( (BoneIndex >=0)            || (BoneIndex == GE_BODY_ROOT));
00325         assert( (BoneIndex < B->BoneCount) || (BoneIndex == GE_BODY_ROOT));
00326         if (BoneIndex == GE_BODY_ROOT)
00327                 {
00328                 #pragma message ("discontinue this?")
00329                         *MinimumBoxCorner = B->BoundingBoxMin;
00330                         *MaximumBoxCorner = B->BoundingBoxMax;
00331                 }
00332         else
00333                 {                       
00334                         geBody_Bone *Bone = &(B->BoneArray[BoneIndex]);
00335 
00336                         if (Bone->BoundingBoxMin.X > Bone->BoundingBoxMax.X)
00337                                 {
00338                                         return GE_FALSE;
00339                                 }
00340                         *MinimumBoxCorner = Bone->BoundingBoxMin;
00341                         *MaximumBoxCorner = Bone->BoundingBoxMax;
00342                 }
00343         return GE_TRUE;
00344 }
00345 
00346 void GENESISCC geBody_SetBoundingBox( geBody *B, 
00347                                                         int BoneIndex,
00348                                                         const geVec3d *MinimumBoxCorner,
00349                                                         const geVec3d *MaximumBoxCorner)
00350 {
00351         assert( B != NULL);
00352         assert( MinimumBoxCorner != NULL );
00353         assert( MaximumBoxCorner != NULL );
00354         assert( (BoneIndex >=0)            || (BoneIndex == GE_BODY_ROOT));
00355         assert( (BoneIndex < B->BoneCount) || (BoneIndex == GE_BODY_ROOT));
00356         if (BoneIndex == GE_BODY_ROOT)
00357                 {
00358                         B->BoundingBoxMin = *MinimumBoxCorner;
00359                         B->BoundingBoxMax = *MaximumBoxCorner;
00360                 }
00361         else
00362                 {                       
00363                         B->BoneArray[BoneIndex].BoundingBoxMin = *MinimumBoxCorner;
00364                         B->BoneArray[BoneIndex].BoundingBoxMax = *MaximumBoxCorner;
00365                 }
00366 }
00367                                                         
00368 
00369 
00370 
00371 geBoolean GENESISCC geBody_GetBoneByName(const geBody* B,
00372         const char* BoneName,
00373         int* pBoneIndex,
00374         geXForm3d* Attachment,
00375         int* pParentBoneIndex)
00376 {
00377         assert( B != NULL );
00378         assert( geBody_IsValid(B) != GE_FALSE );
00379         assert( Attachment != NULL );
00380         assert( pParentBoneIndex != NULL );
00381         assert( pBoneIndex != NULL );
00382         assert(  BoneName != NULL );
00383 
00384         if(geStrBlock_FindString(B->BoneNames, BoneName, pBoneIndex) == GE_TRUE)
00385         {
00386                 *Attachment = B->BoneArray[*pBoneIndex].AttachmentMatrix;
00387                 *pParentBoneIndex = B->BoneArray[*pBoneIndex].ParentBoneIndex;
00388 
00389                 return GE_TRUE;
00390         }
00391 
00392         return GE_FALSE;
00393 }
00394 
00395 int GENESISCC geBody_GetMaterialCount(const geBody *B)
00396 {
00397         assert( B != NULL );
00398         assert( geBody_IsValid(B) != GE_FALSE );
00399         return B->MaterialCount;
00400 }
00401 
00402 #define GE_BODY_TOLERANCE (0.001f)
00403 
00404 static geBoolean GENESISCC geBody_XSkinVertexCompare(
00405         const geBody_XSkinVertex *SV1,
00406         const geBody_XSkinVertex *SV2)
00407 {
00408         assert( SV1 != NULL );
00409         assert( SV2 != NULL );
00410         if (geVec3d_Compare( &(SV1->XPoint), &(SV2->XPoint),
00411                                                 GE_BODY_TOLERANCE) == GE_FALSE)
00412                 {
00413                         return GE_FALSE;
00414                 }
00415         if (geVec3d_Compare( &(SV1->XPoint), &(SV2->XPoint), 
00416                                                 GE_BODY_TOLERANCE) == GE_FALSE)
00417                 {
00418                         return GE_FALSE;
00419                 }
00420         if (fabs(SV1->XU - SV2->XU) > GE_BODY_TOLERANCE)
00421                 {
00422                         return GE_FALSE;
00423                 }
00424         if (fabs(SV1->XV - SV2->XV) > GE_BODY_TOLERANCE)
00425                 {
00426                         return GE_FALSE;
00427                 }
00428         return GE_TRUE;
00429 }       
00430 
00431 
00432 static void GENESISCC geBody_SwapVertexIndices( geBody *B, geBody_Index Index1, geBody_Index Index2)
00433         // zips through all triangles, and swaps index1 and index2.
00434 {
00435         int i,j,lod;
00436         geBody_Index Count;
00437         geBody_Triangle *T;
00438 
00439         assert( B!=NULL );      
00440         for (lod = 0; lod< GE_BODY_NUMBER_OF_LOD; lod++)
00441                 {
00442                         Count = B->SkinFaces[lod].FaceCount;
00443                         for (i=0,T=B->SkinFaces[lod].FaceArray;
00444                                         i<Count; 
00445                                         i++,T++)
00446                                 {
00447                                         for (j=0; j<3; j++)     
00448                                                 {       
00449                                                         if (T->VtxIndex[j] == Index1)
00450                                                                 {
00451                                                                         T->VtxIndex[j] = Index2;
00452                                                                 }
00453                                                         else
00454                                                                 {
00455                                                                         if (T->VtxIndex[j] == Index2)
00456                                                                                 {
00457                                                                                         T->VtxIndex[j] = Index1;
00458                                                                                 }
00459                                                                 }       
00460                                                 }
00461                                 }
00462                 }
00463 }
00464 
00465 static void GENESISCC geBody_ChangeVertexIndex( geBody *B, geBody_Index Index1, geBody_Index Index2)
00466         // zips through all triangles, and changes index1 to index2.
00467 {
00468         int i,j,lod;
00469         geBody_Index Count;
00470         geBody_Triangle *T;
00471 
00472         assert( B!=NULL );      
00473         for (lod = 0; lod< GE_BODY_NUMBER_OF_LOD; lod++)
00474                 {
00475                         Count = B->SkinFaces[lod].FaceCount;
00476                         for (i=0,T=B->SkinFaces[lod].FaceArray;
00477                                         i<Count; 
00478                                         i++,T++)
00479                                 {
00480                                         for (j=0; j<3; j++)     
00481                                                 {       
00482                                                         if (T->VtxIndex[j] == Index1)
00483                                                                 {
00484                                                                         T->VtxIndex[j] = Index2;
00485                                                                 }
00486                                                 }
00487                                 }
00488                 }
00489 }
00490 
00491 static void GENESISCC geBody_SortSkinVertices( geBody *B )
00492 {
00493         int i,j;
00494         int Count;
00495         geBoolean AnyChanges = GE_FALSE;
00496         assert( B != NULL );
00497 
00498         Count = B->XSkinVertexCount;
00499         for (i=0; i<Count; i++)
00500                 {
00501                         for (j=0; j<Count-1; j++)
00502                                 {
00503                                         if (B->XSkinVertexArray[j].BoneIndex > B->XSkinVertexArray[j+1].BoneIndex)
00504                                                 {
00505                                                         geBody_XSkinVertex Swap;
00506 
00507                                                         Swap= B->XSkinVertexArray[j];
00508                                                         B->XSkinVertexArray[j] = B->XSkinVertexArray[j+1];
00509                                                         B->XSkinVertexArray[j+1] = Swap;
00510                                                         geBody_SwapVertexIndices(B,(geBody_Index)j,(geBody_Index)(j+1));
00511                                                         AnyChanges = GE_TRUE;
00512                                                 }
00513                                 }
00514                         if (AnyChanges != GE_TRUE)
00515                                 {
00516                                         break;
00517                                 }
00518                         AnyChanges = GE_FALSE;
00519                 }
00520 }
00521 
00522         
00523 static geBoolean GENESISCC geBody_AddSkinVertex(        geBody *B,
00524         const geVec3d *Vertex, 
00525         geFloat U, geFloat V,
00526         geBody_Index BoneIndex, 
00527         geBody_Index *Index)
00528 {
00529         geBody_Bone *Bone;
00530         geBody_XSkinVertex *SV;
00531         geBody_XSkinVertex NewSV;
00532         int i;
00533         assert( B != NULL );
00534         assert( Vertex != NULL );
00535         assert( Index != NULL );
00536         assert( geBody_IsValid(B) != GE_FALSE );
00537                 
00538         assert( B->XSkinVertexCount+1 > 0 );
00539         
00540         NewSV.XPoint = *Vertex;
00541         NewSV.XU     =  U;
00542         NewSV.XV     =  V;
00543         NewSV.LevelOfDetailMask = GE_BODY_HIGHEST_LOD_MASK;
00544         NewSV.BoneIndex = BoneIndex;
00545         
00546         assert( B->BoneCount > BoneIndex );
00547         Bone = &(B->BoneArray[BoneIndex]);
00548         
00549 
00550         // see if new Vertex is alreay in XSkinVertexArray
00551         for (i=0; i<B->XSkinVertexCount; i++)
00552                 {
00553                         SV = &(B->XSkinVertexArray[i]);
00554                         if (SV->BoneIndex == BoneIndex)
00555                                 {
00556                                         if (geBody_XSkinVertexCompare(SV,&NewSV) == GE_TRUE )
00557                                                 {
00558                                                         *Index = (geBody_Index)i;
00559                                                         return GE_TRUE;
00560                                                 }
00561                                 }
00562                 }
00563         // new Vertex needs to be added to XSkinVertexArray
00564         SV = GE_RAM_REALLOC_ARRAY( B->XSkinVertexArray ,
00565                                         geBody_XSkinVertex, (B->XSkinVertexCount + 1) );
00566         if ( SV == NULL )
00567                 {
00568                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00569                         return GE_FALSE;
00570                 }
00571         B->XSkinVertexArray = SV;
00572 
00573         B->XSkinVertexArray[B->XSkinVertexCount] = NewSV;
00574         *Index = B->XSkinVertexCount;
00575 
00576         Bone->BoundingBoxMin.X = MIN(Bone->BoundingBoxMin.X,NewSV.XPoint.X);
00577         Bone->BoundingBoxMin.Y = MIN(Bone->BoundingBoxMin.Y,NewSV.XPoint.Y);
00578         Bone->BoundingBoxMin.Z = MIN(Bone->BoundingBoxMin.Z,NewSV.XPoint.Z);
00579         Bone->BoundingBoxMax.X = MAX(Bone->BoundingBoxMax.X,NewSV.XPoint.X);
00580         Bone->BoundingBoxMax.Y = MAX(Bone->BoundingBoxMax.Y,NewSV.XPoint.Y);
00581         Bone->BoundingBoxMax.Z = MAX(Bone->BoundingBoxMax.Z,NewSV.XPoint.Z);
00582 
00583         B->XSkinVertexCount ++ ;
00584         return GE_TRUE;
00585 }
00586 
00587 static geBoolean GENESISCC geBody_AddNormal( geBody *B, 
00588                 const geVec3d *Normal, 
00589                 geBody_Index BoneIndex, 
00590                 geBody_Index *Index )
00591 {
00592         geBody_Normal *NewNormalArray;
00593         geBody_Normal *N;
00594         geVec3d NNorm;
00595         int i;
00596 
00597         assert(      B != NULL );
00598         assert( Normal != NULL );
00599         assert(  Index != NULL );       
00600         assert( geBody_IsValid(B) != GE_FALSE );
00601         
00602         assert( B->SkinNormalCount+1 > 0 );
00603         NNorm = *Normal;
00604         geVec3d_Normalize(&NNorm);              
00605         // see if new normal is alreay in SkinNormalArray
00606         for (i=0, N = B->SkinNormalArray; i<B->SkinNormalCount; i++,N++)
00607                 {
00608                         if (N->BoneIndex == BoneIndex)
00609                                 {
00610                                         if ( geVec3d_Compare( &(N->Normal),&NNorm,GE_BODY_TOLERANCE ) == GE_TRUE )
00611                                                 {
00612                                                         *Index = (geBody_Index)i;
00613                                                         return GE_TRUE;
00614                                                 }
00615                                 }
00616                 }
00617 
00618         //  new normal needs to be added to SkinNormalArray
00619         NewNormalArray = GE_RAM_REALLOC_ARRAY( B->SkinNormalArray,              
00620                                                 geBody_Normal,(B->SkinNormalCount+1));
00621         if (NewNormalArray == NULL)
00622                 {
00623                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00624                         return GE_FALSE;
00625                 }
00626         B->SkinNormalArray = NewNormalArray;
00627         B->SkinNormalArray[ B->SkinNormalCount ].Normal    = NNorm;
00628         B->SkinNormalArray[ B->SkinNormalCount ].BoneIndex = BoneIndex;
00629         B->SkinNormalArray[ B->SkinNormalCount ].LevelOfDetailMask = GE_BODY_HIGHEST_LOD_MASK;
00630         *Index = B->SkinNormalCount;
00631         B->SkinNormalCount ++ ;
00632         return GE_TRUE;
00633 }
00634 
00635 static geBoolean GENESISCC geBody_AddToFaces( geBody *B, geBody_Triangle *F, int DetailLevel )
00636 {
00637         geBody_Triangle *NewFaceArray;
00638         geBody_TriangleList *FL;
00639         
00640         assert( B != NULL );
00641         assert( F != NULL );
00642         assert( DetailLevel >= 0);
00643         assert( DetailLevel < GE_BODY_NUMBER_OF_LOD );
00644         assert( geBody_IsValid(B) != GE_FALSE );
00645 
00646         FL = &( B->SkinFaces[DetailLevel] );
00647         
00648         assert( F->MaterialIndex >= 0 );
00649         assert( F->MaterialIndex < B->MaterialCount );
00650         
00651         NewFaceArray = GE_RAM_REALLOC_ARRAY( FL->FaceArray, 
00652                                                 geBody_Triangle,(FL->FaceCount+1) );
00653         if ( NewFaceArray == NULL )
00654                 {
00655                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00656                         return GE_FALSE;
00657                 }
00658 
00659         FL->FaceArray = NewFaceArray;
00660         
00661         {
00662                 int i;
00663                 // insertion sort new face into FaceArray keyed on MaterialIndex
00664                 geBody_Index MaterialIndex = F->MaterialIndex;
00665                 for (i=FL->FaceCount; i>=1; i--)
00666                         {
00667                                 if (FL->FaceArray[i-1].MaterialIndex <= MaterialIndex)
00668                                         break;
00669                                 FL->FaceArray[i] = FL->FaceArray[i-1];
00670                         }
00671                                         
00672                 FL->FaceArray[i] = *F;
00673         }
00674         FL->FaceCount ++;
00675 
00676         return GE_TRUE;
00677 }
00678                         
00679 
00680 
00681 geBoolean GENESISCC geBody_AddFace(     geBody *B,
00682         const geVec3d *Vertex1, const geVec3d *Normal1, 
00683                 geFloat U1, geFloat V1, int BoneIndex1,
00684         const geVec3d *Vertex2, const geVec3d *Normal2, 
00685                 geFloat U2, geFloat V2, int BoneIndex2,
00686         const geVec3d *Vertex3, const geVec3d *Normal3, 
00687                 geFloat U3, geFloat V3, int BoneIndex3,
00688         int MaterialIndex)
00689 {
00690         geBody_Triangle F;
00691         
00692         assert( B != NULL );
00693         assert( Vertex1 != NULL );
00694         assert( Normal1 != NULL );
00695         assert( geBody_IsValid(B) != GE_FALSE );
00696 
00697         assert( BoneIndex1 >= 0 );
00698         assert( BoneIndex1 < B->BoneCount );
00699 
00700         assert( Vertex2 != NULL );
00701         assert( Normal2 != NULL );
00702         assert( BoneIndex2 >= 0 );
00703         assert( BoneIndex2 < B->BoneCount );
00704 
00705         assert( Vertex3 != NULL );
00706         assert( Normal3 != NULL );
00707         assert( BoneIndex3 >= 0 );
00708         assert( BoneIndex3 < B->BoneCount );
00709 
00710         assert( MaterialIndex >= 0 );
00711         assert( MaterialIndex < B->MaterialCount );
00712 
00713         if (geBody_AddSkinVertex(B,Vertex1,U1,V1,(geBody_Index)BoneIndex1,&(F.VtxIndex[0]))==GE_FALSE)
00714                 {       // error already recorded
00715                         return GE_FALSE;
00716                 }
00717         if (geBody_AddSkinVertex(B,Vertex2,U2,V2,(geBody_Index)BoneIndex2,&(F.VtxIndex[1]))==GE_FALSE)
00718                 {       // error already recorded
00719                         return GE_FALSE;
00720                 }
00721         if (geBody_AddSkinVertex(B,Vertex3,U3,V3,(geBody_Index)BoneIndex3,&(F.VtxIndex[2]))==GE_FALSE)
00722                 {       // error already recorded
00723                         return GE_FALSE;
00724                 }
00725 
00726         if (geBody_AddNormal( B, Normal1, (geBody_Index)BoneIndex1, &(F.NormalIndex[0]) ) == GE_FALSE)
00727                 {       // error already recorded
00728                         return GE_FALSE;
00729                 }
00730         if (geBody_AddNormal( B, Normal2, (geBody_Index)BoneIndex2, &(F.NormalIndex[1]) ) == GE_FALSE)
00731                 {       // error already recorded
00732                         return GE_FALSE;
00733                 }
00734         if (geBody_AddNormal( B, Normal3, (geBody_Index)BoneIndex3, &(F.NormalIndex[2]) ) == GE_FALSE)
00735                 {       // error already recorded
00736                         return GE_FALSE;
00737                 }
00738 
00739         F.MaterialIndex = (geBody_Index)MaterialIndex;
00740         if (geBody_AddToFaces( B, &F, GE_BODY_HIGHEST_LOD ) == GE_FALSE)
00741                 {       // error already recorded
00742                         return GE_FALSE;
00743                 }
00744                 
00745         geBody_SortSkinVertices(B);
00746                 
00747         return GE_TRUE;
00748                         
00749 }
00750 
00751 
00752 geBoolean GENESISCC geBody_AddMaterial( geBody *B, 
00753         const char *MaterialName, 
00754         geBitmap *Bitmap,
00755         geFloat Red, geFloat Green, geFloat Blue,
00756         int *MaterialIndex)
00757 {
00758         int FoundIndex;
00759         geBody_Material *NewMaterial;
00760         assert( B != NULL );
00761         assert( MaterialIndex != NULL );
00762         assert( geBody_IsValid(B) != GE_FALSE );
00763         assert( B->MaterialCount >= 0 );
00764 
00765         if (MaterialName == NULL)
00766                 {
00767                         geErrorLog_AddString(-1,"Can't add material - name can not be NULL", NULL);
00768                         return GE_FALSE;
00769                 }
00770         if (MaterialName[0] == 0)
00771                 {
00772                         geErrorLog_AddString(-1,"Can't add material - name must have > 0 length", NULL);
00773                         return GE_FALSE;
00774                 }
00775         if (geStrBlock_FindString(B->MaterialNames, MaterialName, &FoundIndex) == GE_TRUE)
00776                 {
00777                         geErrorLog_AddString(-1,"Can't add material - name already used", NULL);
00778                         return GE_FALSE;
00779                 }
00780         
00781         
00782         NewMaterial = GE_RAM_REALLOC_ARRAY( B->MaterialArray, 
00783                                                 geBody_Material,(B->MaterialCount+1) );
00784         if ( NewMaterial == NULL )
00785                 {
00786                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00787                         return GE_FALSE;
00788                 }
00789         
00790         
00791         B->MaterialArray = NewMaterial;
00792         if (geStrBlock_Append(&(B->MaterialNames),MaterialName) == GE_FALSE)
00793                 {
00794                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00795                         return GE_FALSE;
00796                 }
00797 
00798         {
00799                 geBody_Material *M = &(B->MaterialArray[B->MaterialCount]);
00800                 M->Bitmap = Bitmap;
00801                 if (Bitmap != NULL)
00802                         geBitmap_CreateRef(Bitmap);
00803                 M->Red    = Red;
00804                 M->Green  = Green;
00805                 M->Blue   = Blue;
00806 
00807         }
00808         *MaterialIndex = B->MaterialCount; 
00809         B->MaterialCount ++;
00810         return GE_TRUE;
00811 }
00812                         
00813 geBoolean GENESISCC geBody_GetMaterial(const geBody *B, int MaterialIndex,
00814                                                                                 const char **MaterialName,
00815                                                                                 geBitmap **Bitmap, geFloat *Red, geFloat *Green, geFloat *Blue)
00816 {
00817         assert( B      != NULL );
00818         assert( geBody_IsValid(B) != GE_FALSE );
00819         assert( Red    != NULL );
00820         assert( Green  != NULL );
00821         assert( Blue   != NULL );
00822         assert( Bitmap != NULL );
00823         assert( MaterialIndex >= 0 );
00824         assert( MaterialIndex < B->MaterialCount );
00825         assert( MaterialName != NULL );
00826         *MaterialName      = geStrBlock_GetString(B->MaterialNames,MaterialIndex);
00827 
00828         {
00829                 geBody_Material *M = &(B->MaterialArray[MaterialIndex]);
00830                 *Bitmap = M->Bitmap;
00831                 *Red    = M->Red;
00832                 *Green  = M->Green;
00833                 *Blue   = M->Blue;
00834         }
00835         return GE_TRUE;
00836 }
00837 
00838 geBoolean GENESISCC geBody_SetMaterial(geBody *B, int MaterialIndex,
00839                                                                                 geBitmap *Bitmap,  geFloat Red,  geFloat Green,  geFloat Blue)
00840 {
00841         assert( geBody_IsValid(B) != GE_FALSE );
00842         assert( MaterialIndex >= 0 );
00843         assert( MaterialIndex < B->MaterialCount );
00844         {
00845                 geBody_Material *M = &(B->MaterialArray[MaterialIndex]);
00846                 M->Bitmap = Bitmap;
00847                 if (Bitmap != NULL)
00848                         geBitmap_CreateRef(Bitmap);
00849                 M->Red    = Red;
00850                 M->Green  = Green;
00851                 M->Blue   = Blue;
00852         }
00853         return GE_TRUE;
00854 }
00855 
00856 
00857 
00858 
00859 geBoolean GENESISCC geBody_AddBone( geBody *B, 
00860         int ParentBoneIndex,
00861         const char *BoneName, 
00862         const geXForm3d *AttachmentMatrix,
00863         int *BoneIndex)
00864 {
00865         geBody_Bone *NewBones;
00866         assert( B != NULL );
00867         assert( BoneName != NULL );
00868         assert( BoneIndex != NULL );
00869         assert( geBody_IsValid(B) != GE_FALSE );
00870 
00871         assert( ParentBoneIndex < B->BoneCount );
00872         assert( ( ParentBoneIndex >= 0)  || (ParentBoneIndex == GE_BODY_NO_PARENT_BONE));
00873         assert( B->BoneCount >= 0 );
00874         
00875         NewBones = GE_RAM_REALLOC_ARRAY( B->BoneArray, 
00876                                                 geBody_Bone, (B->BoneCount+1) );
00877         if ( NewBones == NULL )
00878                 {
00879                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00880                         return GE_FALSE;
00881                 }
00882         
00883         B->BoneArray = NewBones;
00884         if (geStrBlock_Append(&(B->BoneNames),BoneName) == GE_FALSE)
00885                 {
00886                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00887                         return GE_FALSE;
00888                 }
00889         
00890         {
00891                 geBody_Bone *Bone = &(B->BoneArray[B->BoneCount]);
00892                 geVec3d_Set(&(Bone->BoundingBoxMin),
00893                         GE_BODY_REALLY_BIG_NUMBER,GE_BODY_REALLY_BIG_NUMBER,GE_BODY_REALLY_BIG_NUMBER);
00894                 geVec3d_Set(&(Bone->BoundingBoxMax),
00895                         -GE_BODY_REALLY_BIG_NUMBER,-GE_BODY_REALLY_BIG_NUMBER,-GE_BODY_REALLY_BIG_NUMBER);
00896                 Bone->AttachmentMatrix = *AttachmentMatrix;
00897                 Bone->ParentBoneIndex = (geBody_Index)ParentBoneIndex;
00898         }
00899         *BoneIndex = B->BoneCount;
00900         B->BoneCount++;
00901         return GE_TRUE;
00902 }
00903 
00904 
00905 
00906 geBoolean GENESISCC geBody_ComputeLevelsOfDetail( geBody *B ,int Levels)
00907 {
00908         assert( B != NULL);
00909         assert( Levels >= 0 );
00910         assert( Levels < GE_BODY_NUMBER_OF_LOD );
00911         assert( geBody_IsValid(B) != GE_FALSE );
00912         #pragma message ("LOD code goes here:")
00913         B->LevelsOfDetail = GE_BODY_HIGHEST_LOD_MASK; // Levels
00914         Levels;
00915         return GE_TRUE;
00916 }       
00917 
00918 
00919 
00920 
00921 
00922 #define GE_BODY_GEOMETRY_NAME "Geometry"
00923 #define GE_BODY_BITMAP_DIRECTORY_NAME "Bitmaps"
00924 
00925 #define GE_BODY_FILE_TYPE 0x5E444F42     // 'BODY'
00926 #define GE_BODY_FILE_VERSION 0x00F1             // Restrict version to 16 bits
00927 
00928 
00929 
00930 
00931 static geBoolean GENESISCC geBody_ReadGeometry(geBody *B, geVFile *pFile)
00932 {
00933         uint32 u;
00934         int i;
00935 
00936         assert( B != NULL );
00937         assert( pFile != NULL );
00938         if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00939                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     return GE_FALSE; }
00940         if (u!=GE_BODY_FILE_TYPE)
00941                 {       geErrorLog_Add( ERR_BODY_FILE_PARSE , NULL);  return GE_FALSE; }
00942 
00943 
00944         if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00945                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     return GE_FALSE; }
00946         if (u!=GE_BODY_FILE_VERSION)
00947                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);   return GE_FALSE; }
00948         
00949 
00950         if(geVFile_Read(pFile, &(B->BoundingBoxMin), sizeof(B->BoundingBoxMin)) == GE_FALSE)
00951                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
00952 
00953         if(geVFile_Read(pFile, &(B->BoundingBoxMax), sizeof(B->BoundingBoxMax)) == GE_FALSE)
00954                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
00955 
00956         if(geVFile_Read(pFile, &(B->XSkinVertexCount), sizeof(B->XSkinVertexCount)) == GE_FALSE)
00957                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
00958 
00959         if (B->XSkinVertexCount>0)
00960                 {
00961                         u = sizeof(geBody_XSkinVertex) * B->XSkinVertexCount;
00962                         B->XSkinVertexArray = geRam_Allocate(u);
00963                         if (B->XSkinVertexArray == NULL)
00964                                 {       geErrorLog_Add( ERR_BODY_ENOMEM , NULL);   return GE_FALSE;  }
00965                         if(geVFile_Read(pFile, B->XSkinVertexArray, u) == GE_FALSE)
00966                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
00967                 }
00968 
00969         if(geVFile_Read(pFile, &(B->SkinNormalCount), sizeof(B->SkinNormalCount)) == GE_FALSE)
00970                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
00971 
00972         if (B->SkinNormalCount>0)
00973                 {
00974                         u = sizeof(geBody_Normal) * B->SkinNormalCount;
00975                         B->SkinNormalArray = geRam_Allocate(u);
00976                         if (B->SkinNormalArray == NULL)
00977                                 {       geErrorLog_Add( ERR_BODY_ENOMEM , NULL);   return GE_FALSE;  }
00978                         if(geVFile_Read(pFile, B->SkinNormalArray, u) == GE_FALSE)
00979                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     return GE_FALSE; }
00980                 }
00981 
00982         if(geVFile_Read(pFile, &(B->BoneCount), sizeof(B->BoneCount)) == GE_FALSE)
00983                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);  return GE_FALSE; }
00984 
00985         if (B->BoneCount>0)
00986                 {
00987                         u = sizeof(geBody_Bone) * B->BoneCount;
00988                         B->BoneArray = geRam_Allocate(u);
00989                         if (B->BoneArray == NULL)
00990                                 {       geErrorLog_Add( ERR_BODY_ENOMEM , NULL);   return GE_FALSE;  }
00991                         if(geVFile_Read(pFile, B->BoneArray, u) == GE_FALSE)
00992                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);  return GE_FALSE; }
00993                 }
00994 
00995         B->BoneNames = geStrBlock_CreateFromFile(pFile);
00996         if (B->BoneNames==NULL)
00997                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
00998         
00999         if(geVFile_Read(pFile, &(B->MaterialCount), sizeof(B->MaterialCount)) == GE_FALSE)
01000                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01001 
01002         if (B->MaterialCount>0)
01003                 {
01004                         u = sizeof(geBody_Material) * B->MaterialCount;
01005                         B->MaterialArray = geRam_Allocate(u);
01006                         if (B->MaterialArray == NULL)
01007                                 {       geErrorLog_Add( ERR_BODY_ENOMEM , NULL);   return GE_FALSE;  }
01008                         if(geVFile_Read(pFile, B->MaterialArray, u) == GE_FALSE)
01009                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01010 
01011                         // CB added this nastiness because it seems the Bitmap pointer is
01012                         //      read in with the Material array, and is later used as a boolean
01013                         //      for "should this material have a texture"
01014                         for(u=0;u<(uint32)B->MaterialCount;u++)
01015                         {
01016                                 if ( B->MaterialArray[u].Bitmap )
01017                                         B->MaterialArray[u].Bitmap = (geBitmap *)1;
01018                         }
01019                 }
01020         
01021         B->MaterialNames = geStrBlock_CreateFromFile(pFile);
01022         if ( B->MaterialNames == NULL )
01023                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01024 
01025         if(geVFile_Read(pFile, &(B->LevelsOfDetail), sizeof(B->LevelsOfDetail)) == GE_FALSE)
01026                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01027 
01028         if (B->LevelsOfDetail > GE_BODY_NUMBER_OF_LOD)
01029                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01030 
01031         for (i=0; i<B->LevelsOfDetail; i++)
01032                 {
01033                         if(geVFile_Read(pFile, &(u), sizeof(u)) == GE_FALSE)
01034                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01035                         B->SkinFaces[i].FaceCount = (geBody_Index)u;
01036                         
01037                         if (u>0)
01038                                 {
01039                                         u = sizeof(geBody_Triangle) * u;
01040                                         B->SkinFaces[i].FaceArray = geRam_Allocate(u);
01041                                         if (B->SkinFaces[i].FaceArray == NULL)
01042                                                 {       geErrorLog_Add( ERR_BODY_ENOMEM , NULL);   return GE_FALSE;  }
01043                                         if(geVFile_Read(pFile, B->SkinFaces[i].FaceArray, u) == GE_FALSE)
01044                                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);      return GE_FALSE; }
01045                                 }
01046                 }
01047 
01048         assert( geBody_IsValid(B) != GE_FALSE );
01049         return GE_TRUE;
01050 }
01051 
01052 geBody *GENESISCC geBody_CreateFromFile(geVFile *pFile)
01053 {
01054         geBody  *B;
01055         int i;
01056 
01057         geVFile *VFile;
01058         geVFile *SubFile=NULL;
01059         geVFile *BitmapDirectory=NULL;  
01060         
01061         assert( pFile != NULL );
01062 
01063         VFile = geVFile_OpenNewSystem(pFile,GE_VFILE_TYPE_VIRTUAL, NULL, 
01064                                                                         NULL, GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_READONLY);
01065         if (VFile == NULL)
01066                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     goto CreateError;}
01067         
01068         SubFile = geVFile_Open(VFile,GE_BODY_GEOMETRY_NAME,GE_VFILE_OPEN_READONLY);
01069         if (SubFile == NULL)
01070                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     goto CreateError;}
01071 
01072         B = geBody_CreateNull();
01073         if (B==NULL)
01074                 {       geErrorLog_Add( ERR_BODY_ENOMEM , NULL);  goto CreateError;  }
01075 
01076         if (geBody_ReadGeometry(B,SubFile)==GE_FALSE)
01077                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     goto CreateError;}
01078         geVFile_Close(SubFile);
01079 
01080         BitmapDirectory = geVFile_Open(VFile,GE_BODY_BITMAP_DIRECTORY_NAME, 
01081                                                                         GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_READONLY);
01082         if (BitmapDirectory == NULL)
01083                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     goto CreateError;}
01084         
01085         for (i=0; i<B->MaterialCount; i++)
01086                 {
01087                         geBody_Material *M;
01088                         M = &(B->MaterialArray[i]);
01089 
01090                         if (M->Bitmap != NULL)
01091                                 {
01092                                         char FName[1000];
01093                                         sprintf(FName,"%d",i);
01094                                         
01095                                         SubFile = geVFile_Open(BitmapDirectory,FName,GE_VFILE_OPEN_READONLY);
01096                                         if (SubFile == NULL)
01097                                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     goto CreateError;}
01098 
01099                                         M->Bitmap = geBitmap_CreateFromFile(SubFile);
01100 
01101                                         if (M->Bitmap == NULL)
01102                                                 {       geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     goto CreateError;}
01103 
01104                                 #if 1
01105                                         // Set the number of mips to 4
01106                                         if (!geBitmap_SetMipCount(M->Bitmap, 4))
01107                                         {       
01108                                                 geErrorLog_Add( ERR_BODY_FILE_READ , NULL);     
01109                                                 goto CreateError;
01110                                         }
01111                                 #endif
01112 
01113                                         geVFile_Close(SubFile);
01114                                 }
01115                 }
01116         geVFile_Close(BitmapDirectory);
01117         geVFile_Close(VFile);
01118         return B;
01119 
01120         CreateError:
01121                 geBody_DestroyPossiblyIncompleteBody(&B);
01122                 if (SubFile != NULL)
01123                         geVFile_Close(SubFile);
01124                 if (BitmapDirectory != NULL)
01125                         geVFile_Close(BitmapDirectory);
01126                 if (VFile != NULL)
01127                         geVFile_Close(VFile);
01128                 return NULL;
01129 }
01130 
01131 
01132 
01133 geBoolean GENESISCC geBody_WriteGeometry(const geBody *B,geVFile *pFile)
01134 {
01135         uint32 u;
01136         int i;
01137 
01138         assert( B != NULL );
01139         assert( pFile != NULL );
01140         assert( geBody_IsValid(B) != GE_FALSE );
01141 
01142         // Write the format flag
01143         u = GE_BODY_FILE_TYPE;
01144         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
01145                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01146 
01147         // Write the version
01148         u = GE_BODY_FILE_VERSION;
01149         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
01150                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01151         
01152         if(geVFile_Write(pFile, &(B->BoundingBoxMin), sizeof(B->BoundingBoxMin)) == GE_FALSE)
01153                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01154 
01155         if(geVFile_Write(pFile, &(B->BoundingBoxMax), sizeof(B->BoundingBoxMax)) == GE_FALSE)
01156                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01157 
01158         if(geVFile_Write(pFile, &(B->XSkinVertexCount), sizeof(B->XSkinVertexCount)) == GE_FALSE)
01159                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01160 
01161         assert( (B->XSkinVertexCount==0) || (B->XSkinVertexArray!=NULL));
01162         
01163         if (B->XSkinVertexCount>0)
01164                 {
01165                         u = sizeof(geBody_XSkinVertex) * B->XSkinVertexCount;
01166                         if(geVFile_Write(pFile, B->XSkinVertexArray, u) == GE_FALSE)
01167                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01168                 }
01169 
01170         if(geVFile_Write(pFile, &(B->SkinNormalCount), sizeof(B->SkinNormalCount)) == GE_FALSE)
01171                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01172 
01173         if (B->SkinNormalCount>0)
01174                 {
01175                         u = sizeof(geBody_Normal) * B->SkinNormalCount;
01176                         if(geVFile_Write(pFile, B->SkinNormalArray, u) == GE_FALSE)
01177                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01178                 }
01179 
01180         if(geVFile_Write(pFile, &(B->BoneCount), sizeof(B->BoneCount)) == GE_FALSE)
01181                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01182 
01183         if (B->BoneCount>0)
01184                 {
01185                         u = sizeof(geBody_Bone) * B->BoneCount;
01186                         if(geVFile_Write(pFile, B->BoneArray, u) == GE_FALSE)
01187                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01188                 }
01189 
01190         if (geStrBlock_WriteToBinaryFile(B->BoneNames,pFile)==GE_FALSE)
01191                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01192         
01193         if(geVFile_Write(pFile, &(B->MaterialCount), sizeof(B->MaterialCount)) == GE_FALSE)
01194                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01195 
01196         if (B->MaterialCount>0)
01197                 {
01198                         u = sizeof(geBody_Material) * B->MaterialCount;
01199                         if(geVFile_Write(pFile, B->MaterialArray, u) == GE_FALSE)
01200                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01201                 }
01202         
01203         if (geStrBlock_WriteToBinaryFile(B->MaterialNames,pFile)==GE_FALSE)
01204                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01205         
01206         if(geVFile_Write(pFile, &(B->LevelsOfDetail), sizeof(B->LevelsOfDetail)) == GE_FALSE)
01207                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01208 
01209         for (i=0; i<B->LevelsOfDetail; i++)
01210                 {
01211                         u = B->SkinFaces[i].FaceCount;
01212                         if(geVFile_Write(pFile, &(u), sizeof(u)) == GE_FALSE)
01213                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01214                         if (u>0)
01215                                 {
01216                                         u = sizeof(geBody_Triangle) * u;
01217                                         if(geVFile_Write(pFile, B->SkinFaces[i].FaceArray, u) == GE_FALSE)
01218                                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    return GE_FALSE; }
01219                                 }
01220                 }
01221         return GE_TRUE;
01222 }
01223 
01224 
01225 geBoolean GENESISCC geBody_WriteToFile(const geBody *B, geVFile *pFile)
01226 {
01227         int i;
01228         geVFile *VFile;
01229         geVFile *SubFile;
01230         geVFile *BitmapDirectory;
01231 
01232         assert( geBody_IsValid(B) != GE_FALSE );
01233         assert( pFile != NULL );
01234 
01235         VFile = geVFile_OpenNewSystem(pFile,GE_VFILE_TYPE_VIRTUAL, NULL, 
01236                                                                         NULL, GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_CREATE);
01237         if (VFile == NULL)
01238                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01239         
01240         SubFile = geVFile_Open(VFile,GE_BODY_GEOMETRY_NAME,GE_VFILE_OPEN_CREATE);
01241         if (SubFile == NULL)
01242                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01243 
01244         if (geBody_WriteGeometry(B,SubFile)==GE_FALSE)
01245                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01246         if (geVFile_Close(SubFile)==GE_FALSE)
01247                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01248                 
01249         BitmapDirectory = geVFile_Open(VFile,GE_BODY_BITMAP_DIRECTORY_NAME, 
01250                                                                         GE_VFILE_OPEN_DIRECTORY | GE_VFILE_OPEN_CREATE);
01251         if (BitmapDirectory == NULL)
01252                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01253         
01254         for (i=0; i<B->MaterialCount; i++)
01255                 {
01256                         geBody_Material *M;
01257                         M = &(B->MaterialArray[i]);
01258 
01259                         if (M->Bitmap != NULL)
01260                                 {
01261                                         char FName[1000];
01262                                         sprintf(FName,"%d",i);
01263 
01264                                         SubFile = geVFile_Open(BitmapDirectory,FName,GE_VFILE_OPEN_CREATE);
01265                                         if (SubFile == NULL)
01266                                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01267 
01268                                         if (geBitmap_WriteToFile(M->Bitmap,SubFile)==GE_FALSE)
01269                                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01270                                                         
01271                                         if (geVFile_Close(SubFile)==GE_FALSE)
01272                                                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01273                                 }
01274                 }
01275         if (geVFile_Close(BitmapDirectory)==GE_FALSE)
01276                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01277         if (geVFile_Close(VFile)==GE_FALSE)
01278                 {       geErrorLog_Add( ERR_BODY_FILE_WRITE , NULL);    goto WriteError;}
01279         
01280         return GE_TRUE;
01281         WriteError:
01282                 return GE_FALSE;
01283 }

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