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

bodyinst.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  BODYINST.C                                                                          */
00003 /*                                                                                      */
00004 /*  Author: Mike Sandige                                                                    */
00005 /*  Description: Actor body instance 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 
00024 #include "body._h"
00025 #include "bodyinst.h"
00026 #include "ram.h"
00027 #include "errorlog.h"
00028 #include "strblock.h"
00029 
00030 
00031 
00032 typedef struct geBodyInst
00033 {
00034         const geBody                    *BodyTemplate;
00035         geBodyInst_Geometry              ExportGeometry;
00036         int                                              LastLevelOfDetail;
00037         geBodyInst_Index                 FaceCount;
00038 } geBodyInst;
00039 
00040 
00041 
00042 void GENESISCC geBodyInst_PostScale(const geXForm3d *M,const geVec3d *S,geXForm3d *Scaled)
00043 {
00044         Scaled->AX = M->AX * S->X;
00045         Scaled->BX = M->BX * S->X;
00046         Scaled->CX = M->CX * S->X;
00047 
00048         Scaled->AY = M->AY * S->Y;
00049         Scaled->BY = M->BY * S->Y;
00050         Scaled->CY = M->CY * S->Y;
00051 
00052         Scaled->AZ = M->AZ * S->Z;
00053         Scaled->BZ = M->BZ * S->Z;
00054         Scaled->CZ = M->CZ * S->Z;
00055         Scaled->Translation = M->Translation;
00056 }
00057 
00058 
00059 geBodyInst *GENESISCC geBodyInst_Create(const geBody *B)
00060 {
00061         geBodyInst *BI;
00062         assert( B != NULL );
00063         assert( geBody_IsValid(B) != GE_FALSE );
00064         
00065         BI = GE_RAM_ALLOCATE_STRUCT(geBodyInst);
00066         if (BI == NULL)
00067                 {
00068                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00069                         return NULL;
00070                 }
00071         BI->BodyTemplate = B;
00072         {
00073                 geBodyInst_Geometry *G = &(BI->ExportGeometry);
00074                 G->SkinVertexCount =0;
00075                 G->SkinVertexArray = NULL;
00076                 
00077                 G->NormalCount = 0;
00078                 G->NormalArray = NULL;
00079                 
00080                 G->FaceCount = (geBody_Index) 0;
00081                 G->FaceListSize = 0; 
00082                 G->FaceList = NULL;
00083         }
00084 
00085         BI->LastLevelOfDetail   = -1;
00086         BI->FaceCount =  0;
00087 
00088         return BI;
00089 }
00090                         
00091 
00092 void GENESISCC geBodyInst_Destroy( geBodyInst **BI)
00093 {
00094         geBodyInst_Geometry *G;
00095         assert( BI != NULL );
00096         assert( *BI != NULL );
00097         G = &( (*BI)->ExportGeometry );
00098         if (G->SkinVertexArray != NULL )
00099                 {
00100                         geRam_Free( G->SkinVertexArray );
00101                         G->SkinVertexArray = NULL;
00102                 }
00103         if (G->NormalArray != NULL )
00104                 {
00105                         geRam_Free( G->NormalArray );
00106                         G->NormalArray = NULL;
00107                 }
00108         if (G->FaceList != NULL )
00109                 {
00110                         geRam_Free( G->FaceList );
00111                         G->FaceList = NULL;
00112                 }
00113         geRam_Free( *BI );
00114         *BI = NULL;
00115 }
00116 
00117 
00118 
00119 #define GE_BODYINST_FACELIST_SIZE_FOR_TRIANGLE (8)
00120 
00121 static geBodyInst_Geometry *GENESISCC geBodyInst_GetGeometryPrep(       
00122         geBodyInst *BI, 
00123         int LevelOfDetail)
00124 {
00125         const geBody *B;
00126         geBodyInst_Geometry *G;
00127         
00128         assert( BI != NULL );
00129         assert( geBody_IsValid(BI->BodyTemplate) != GE_FALSE );
00130         B = BI->BodyTemplate;
00131 
00132         G = &(BI->ExportGeometry);
00133         assert( G  != NULL );
00134 
00135         if (G->SkinVertexCount != B->XSkinVertexCount)
00136                 {
00137                         if (G->SkinVertexArray!=NULL)
00138                                 {
00139                                         geRam_Free(G->SkinVertexArray);
00140                                 }
00141                         G->SkinVertexArray = GE_RAM_ALLOCATE_ARRAY(geBodyInst_SkinVertex,B->XSkinVertexCount);
00142                         if ( G->SkinVertexArray == NULL )
00143                                 {
00144                                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00145                                         G->SkinVertexCount = 0;
00146                                         return NULL;
00147                                 }
00148                         G->SkinVertexCount  = B->XSkinVertexCount;
00149                 }
00150 
00151         if (G->NormalCount != B->SkinNormalCount)
00152                 {
00153                         if (G->NormalArray!=NULL)
00154                                 {
00155                                         geRam_Free(G->NormalArray);
00156                                 }
00157                         G->NormalArray = GE_RAM_ALLOCATE_ARRAY( geVec3d,B->SkinNormalCount);
00158                         if ( G->NormalArray == NULL )
00159                                 {
00160                                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00161                                         G->NormalCount = 0;
00162                                         return NULL;
00163                                 }
00164                         G->NormalCount  = B->SkinNormalCount;
00165                 }
00166 
00167         if (BI->FaceCount != B->SkinFaces[GE_BODY_HIGHEST_LOD].FaceCount)
00168                 {
00169                         if (G->FaceList!=NULL)
00170                                 {
00171                                         geRam_Free(G->FaceList);
00172                                 }
00173                         G->FaceListSize = sizeof(geBody_Index) * 
00174                                         B->SkinFaces[GE_BODY_HIGHEST_LOD].FaceCount * 
00175                                         GE_BODYINST_FACELIST_SIZE_FOR_TRIANGLE;
00176                         G->FaceList = GE_RAM_ALLOCATE_ARRAY(geBody_Index,
00177                                                         B->SkinFaces[GE_BODY_HIGHEST_LOD].FaceCount * 
00178                                                         GE_BODYINST_FACELIST_SIZE_FOR_TRIANGLE);
00179                         if ( G->FaceList == NULL )
00180                                 {
00181                                         geErrorLog_Add(ERR_BODY_ENOMEM, NULL);
00182                                         BI->FaceCount = 0;
00183                                         return NULL;
00184                                 }
00185                         BI->FaceCount = B->SkinFaces[GE_BODY_HIGHEST_LOD].FaceCount;
00186                 }
00187         return G;
00188 }
00189 
00190 const geBodyInst_Geometry *GENESISCC geBodyInst_GetGeometry(
00191         const geBodyInst *BI, 
00192         const geVec3d *ScaleVector,
00193         const geXFArray *BoneTransformArray,
00194         int LevelOfDetail,
00195         const geCamera *Camera)
00196 {
00197         geBodyInst_Geometry *G;
00198         const geBody *B;
00199         geXForm3d *BoneXFArray;
00200         int      BoneXFCount;
00201         geBody_Index BoneIndex;
00202 
00203         geBoolean GottaUpdateFaces = GE_FALSE;
00204         assert( BI != NULL );
00205         assert( BoneTransformArray != NULL );
00206         assert( geBody_IsValid(BI->BodyTemplate) != GE_FALSE );
00207         
00208         G = geBodyInst_GetGeometryPrep((geBodyInst *)BI,LevelOfDetail);
00209         if (G == NULL)
00210                 {
00211                         return NULL;
00212                 }
00213                 
00214 
00215         B = BI->BodyTemplate;
00216 
00217         BoneXFArray = geXFArray_GetElements(BoneTransformArray,&BoneXFCount);
00218         if ( BoneXFArray == NULL)
00219                 {
00220                         geErrorLog_Add(ERR_BODY_BONEXFARRAY, NULL);
00221                         return NULL;
00222                 }
00223         if (BoneXFCount != B->BoneCount)
00224                 {       
00225                         geErrorLog_Add(ERR_BODY_BONEXFARRAY, NULL);
00226                         return NULL;
00227                 }
00228 
00229 
00230         {       
00231                 int i,LevelOfDetailBit;
00232         
00233                 if (Camera != NULL)
00234                         {
00235                                 // transform and project all appropriate points
00236                                 geBody_XSkinVertex *S;
00237                                 geBodyInst_SkinVertex  *D;
00238                                 LevelOfDetailBit = 1 << LevelOfDetail;
00239                                 BoneIndex = -1;  // S->BoneIndex won't ever be this.
00240                                 geVec3d_Set(&(G->Maxs), -GE_BODY_REALLY_BIG_NUMBER, -GE_BODY_REALLY_BIG_NUMBER, -GE_BODY_REALLY_BIG_NUMBER );
00241                                 geVec3d_Set(&(G->Mins), GE_BODY_REALLY_BIG_NUMBER, GE_BODY_REALLY_BIG_NUMBER, GE_BODY_REALLY_BIG_NUMBER );
00242                                 for (i=B->XSkinVertexCount,S=B->XSkinVertexArray,D=G->SkinVertexArray; 
00243                                          i>0; 
00244                                          i--,S++,D++)
00245                                         {
00246                                                 geXForm3d ObjectToCamera;
00247                                                 if (S->BoneIndex!=BoneIndex)
00248                                                         { //Keep XSkinVertexArray sorted by BoneIndex for best performance
00249                                                                 BoneIndex = S->BoneIndex;
00250                                                                 geXForm3d_Multiply(             geCamera_GetCameraSpaceXForm(Camera), 
00251                                                                                                                 &(BoneXFArray[BoneIndex]),
00252                                                                                                                 &ObjectToCamera);
00253                                                                 geBodyInst_PostScale(&ObjectToCamera,ScaleVector,&ObjectToCamera);
00254                                                         }
00255                                                 if ( S->LevelOfDetailMask && LevelOfDetailBit )
00256                                                         {
00257                                                                 geVec3d *VecDestPtr = &(D->SVPoint);
00258                                                                 geXForm3d_Transform(  &(ObjectToCamera),
00259                                                                                                         &(S->XPoint),VecDestPtr);
00260                                                                 #ifdef ONE_OVER_Z_PIPELINE
00261                                                                 geCamera_ProjectZ( Camera, VecDestPtr, VecDestPtr);
00262                                                                 #else
00263                                                                 geCamera_Project( Camera, VecDestPtr, VecDestPtr);
00264                                                                 #endif
00265                                                                 D->SVU = S->XU;
00266                                                                 D->SVV = S->XV;
00267                                                                 if (VecDestPtr->X > G->Maxs.X ) G->Maxs.X = VecDestPtr->X;
00268                                                                 if (VecDestPtr->X < G->Mins.X ) G->Mins.X = VecDestPtr->X;
00269                                                                 if (VecDestPtr->Y > G->Maxs.Y ) G->Maxs.Y = VecDestPtr->Y;
00270                                                                 if (VecDestPtr->Y < G->Mins.Y ) G->Mins.Y = VecDestPtr->Y;
00271                                                                 if (VecDestPtr->Z > G->Maxs.Z ) G->Maxs.Z = VecDestPtr->Z;
00272                                                                 if (VecDestPtr->Z < G->Mins.Z ) G->Mins.Z = VecDestPtr->Z;
00273                                                                 D->ReferenceBoneIndex=BoneIndex;
00274                                                         }
00275                                         }
00276                         }
00277                 else
00278                         {
00279                                 // transform all appropriate points
00280                                 geBody_XSkinVertex *S;
00281                                 geBodyInst_SkinVertex  *D;
00282                                 LevelOfDetailBit = 1 << LevelOfDetail;
00283                                 BoneIndex = -1;  // S->BoneIndex won't ever be this.
00284                                 geVec3d_Set(&(G->Maxs), -GE_BODY_REALLY_BIG_NUMBER, -GE_BODY_REALLY_BIG_NUMBER, -GE_BODY_REALLY_BIG_NUMBER );
00285                                 geVec3d_Set(&(G->Mins), GE_BODY_REALLY_BIG_NUMBER, GE_BODY_REALLY_BIG_NUMBER, GE_BODY_REALLY_BIG_NUMBER );
00286                                 
00287                                 for (i=B->XSkinVertexCount,S=B->XSkinVertexArray,D=G->SkinVertexArray; 
00288                                          i>0; 
00289                                          i--,S++,D++)
00290                                         {
00291                                                 geXForm3d ObjectToWorld;
00292                                                 if (S->BoneIndex!=BoneIndex)
00293                                                         { //Keep XSkinVertexArray sorted by BoneIndex for best performance
00294                                                                 BoneIndex = S->BoneIndex;
00295                                                                 geBodyInst_PostScale(&BoneXFArray[BoneIndex],ScaleVector,&ObjectToWorld);
00296 
00297                                                         }
00298                                                 if ( S->LevelOfDetailMask && LevelOfDetailBit )
00299                                                         {
00300                                                                 geVec3d *VecDestPtr = &(D->SVPoint);
00301                                                                 geXForm3d_Transform(  &(ObjectToWorld),
00302                                                                                                         &(S->XPoint),VecDestPtr);
00303                                                                 D->SVU = S->XU;
00304                                                                 D->SVV = S->XV;
00305                                                                 if (VecDestPtr->X > G->Maxs.X ) G->Maxs.X = VecDestPtr->X;
00306                                                                 if (VecDestPtr->X < G->Mins.X ) G->Mins.X = VecDestPtr->X;
00307                                                                 if (VecDestPtr->Y > G->Maxs.Y ) G->Maxs.Y = VecDestPtr->Y;
00308                                                                 if (VecDestPtr->Y < G->Mins.Y ) G->Mins.Y = VecDestPtr->Y;
00309                                                                 if (VecDestPtr->Z > G->Maxs.Z ) G->Maxs.Z = VecDestPtr->Z;
00310                                                                 if (VecDestPtr->Z < G->Mins.Z ) G->Mins.Z = VecDestPtr->Z;
00311                                                                 D->ReferenceBoneIndex=BoneIndex;
00312                                                         }
00313                                         }
00314                         }
00315 
00316                         {
00317                                 geBody_Normal *S;
00318                                 geVec3d *D;
00319                                 // rotate all appropriate normals
00320                                 for (i=B->SkinNormalCount,S=B->SkinNormalArray,D=G->NormalArray;
00321                                          i>0; 
00322                                          i--,S++,D++)
00323                                         {
00324                                                 if ( S->LevelOfDetailMask && LevelOfDetailBit )
00325                                                         {
00326                                                                 geXForm3d_Rotate(&(BoneXFArray[S->BoneIndex]),
00327                                                                                            &(S->Normal),D);
00328                                                         }
00329                                         }
00330                         }
00331 
00332         }
00333 
00334 
00335         if (LevelOfDetail != BI->LastLevelOfDetail)
00336         {
00337                 // build face list to export
00338                 int i,j;
00339                 geBody_Index Count;
00340                 const geBody_Triangle *T;
00341                 geBody_Index *D;
00342                 Count = B->SkinFaces[LevelOfDetail].FaceCount;
00343 
00344                 for (i=0,T=B->SkinFaces[LevelOfDetail].FaceArray,D=G->FaceList;
00345                                 i<Count; 
00346                                 i++,T++,B++)
00347                         {
00348                                 *D = GE_BODYINST_FACE_TRIANGLE;
00349                                 D++;
00350                                 *D = T->MaterialIndex;
00351                                 D++;
00352                                 for (j=0; j<3; j++)
00353                                         {
00354                                                 *D = T->VtxIndex[j];
00355                                                 D++;
00356                                                 *D = T->NormalIndex[j];
00357                                                 D++;
00358                                         }
00359                         }
00360                 assert( ((uint32)D) - ((uint32)G->FaceList) == (uint32)(G->FaceListSize) );
00361                 G->FaceCount = Count;
00362                 ((geBodyInst *)BI)->LastLevelOfDetail = LevelOfDetail;
00363         }
00364 
00365 
00366 
00367         return G;
00368 }       
00369 

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