00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <assert.h>
00023 #include <string.h>
00024 #include <math.h>
00025 #include <stdio.h>
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
00198
00199
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
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
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
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
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
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
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
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 {
00715 return GE_FALSE;
00716 }
00717 if (geBody_AddSkinVertex(B,Vertex2,U2,V2,(geBody_Index)BoneIndex2,&(F.VtxIndex[1]))==GE_FALSE)
00718 {
00719 return GE_FALSE;
00720 }
00721 if (geBody_AddSkinVertex(B,Vertex3,U3,V3,(geBody_Index)BoneIndex3,&(F.VtxIndex[2]))==GE_FALSE)
00722 {
00723 return GE_FALSE;
00724 }
00725
00726 if (geBody_AddNormal( B, Normal1, (geBody_Index)BoneIndex1, &(F.NormalIndex[0]) ) == GE_FALSE)
00727 {
00728 return GE_FALSE;
00729 }
00730 if (geBody_AddNormal( B, Normal2, (geBody_Index)BoneIndex2, &(F.NormalIndex[1]) ) == GE_FALSE)
00731 {
00732 return GE_FALSE;
00733 }
00734 if (geBody_AddNormal( B, Normal3, (geBody_Index)BoneIndex3, &(F.NormalIndex[2]) ) == GE_FALSE)
00735 {
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 {
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;
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
01012
01013
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
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
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
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 }