/*=========================================================================== * * DFLandBuilder.CPP - Dave Humphrey (uesp@m0use.net), 6 November 2000 * *=========================================================================*/ /* Include Files */ #include "dflandbuilder.h" #include "dfmaps.h" #include "dfcommon.h" #include "math.h" #include "profile.h" #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::CDFLandBuilder()" /*=========================================================================== * * Class CDFLandBuilder Constructor * *=========================================================================*/ CDFLandBuilder::CDFLandBuilder(const boolean CreateBuilders) { PixelBuildersAllocated = FALSE; pOriginBuilder = NULL; OriginPosition.X = 0; OriginPosition.Y = 0; OriginPosition.Z = 0; OriginXPixel = -1; OriginYPixel = -1; LeftPixel = -1; TopPixel = -1; /* Create the array of pixel builders if required */ if (CreateBuilders) CreatePixelBuilders(); } /*=========================================================================== * End of Class CDFLandBuilder Constructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::Destroy()" /*=========================================================================== * * Class CDFLandBuilder Destructor * *=========================================================================*/ void CDFLandBuilder::Destroy (void) { DestroyPixelBuilders(); } /*=========================================================================== * End of Class CDFLandBuilder Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::ClearPixelBuilders()" /*=========================================================================== * * Class CDFLandBuilder Method - void ClearPixelBuilders (void); * * Initialize the pixel builder array by destroying any information it * contains but keeping the allocated objects. Protected class method. * *=========================================================================*/ void CDFLandBuilder::ClearPixelBuilders (void) { int XCounter; int YCounter; /* We don't want to initialize an unallocated array */ ASSERT(PixelBuildersAllocated == TRUE); /* Clear each pixel record */ for (YCounter = 0; YCounter < DFLAND_PIXELS_ARRAYSIZE; YCounter++) { for (XCounter = 0; XCounter < DFLAND_PIXELS_ARRAYSIZE; XCounter++) { pPixelBuilders[YCounter][XCounter]->Destroy(); } } } /*=========================================================================== * End of Class Method CDFLandBuilder::ClearPixelBuilders() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::CreatePixelBuilders()" /*=========================================================================== * * Class CDFLandBuilder Method - void CreatePixelBuilders (void); * * Allocate and initialize the pixel builder array. Protected class method. * *=========================================================================*/ void CDFLandBuilder::CreatePixelBuilders (void) { int XCounter; int YCounter; /* We don't want to recreate the array over again */ ASSERT(PixelBuildersAllocated != TRUE); /* Allocate each of the array elements */ for (YCounter = 0; YCounter < DFLAND_PIXELS_ARRAYSIZE; YCounter++) { for (XCounter = 0; XCounter < DFLAND_PIXELS_ARRAYSIZE; XCounter++) { CreatePointer(pPixelBuilders[YCounter][XCounter], CDFPixelBuilder); } } PixelBuildersAllocated = TRUE; pOriginBuilder = pPixelBuilders[DFLAND_PIXELS_ARRAYHALFSIZE][DFLAND_PIXELS_ARRAYHALFSIZE]; } /*=========================================================================== * End of Class Method CDFLandBuilder::CreatePixelBuilders() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::DestroyPixelBuilders()" /*=========================================================================== * * Class CDFLandBuilder Method - void DestroyPixelBuilders (void); * * Delete any allocated pixel builders. Protected class method. * *=========================================================================*/ void CDFLandBuilder::DestroyPixelBuilders (void) { int XCounter; int YCounter; /* Ensure there is something to delete */ if (!PixelBuildersAllocated) return; /* Unallocate all records in the array */ for (YCounter = 0; YCounter < DFLAND_PIXELS_ARRAYSIZE; YCounter++) { for (XCounter = 0; XCounter < DFLAND_PIXELS_ARRAYSIZE; XCounter++) { DestroyPointer(pPixelBuilders[YCounter][XCounter]); } } PixelBuildersAllocated = FALSE; pOriginBuilder = NULL; } /*=========================================================================== * End of Class Method CDFLandBuilder::DestroyPixelBuilders() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::GenerateLandPixel()" /*=========================================================================== * * Class CDFLandBuilder Method - boolean GenerateLandPixel (XIndex, YIndex); * * Creates the vertex/face arrays for the given pixel record. Returns FALSE * on any error. Protected class method. * *=========================================================================*/ boolean CDFLandBuilder::GenerateLandPixel (const int XIndex, const int YIndex) { int Result; /* Ensure valid indices and objects */ ASSERT(XIndex >= 0 && XIndex < DFLAND_PIXELS_ARRAYSIZE); ASSERT(YIndex >= 0 && YIndex < DFLAND_PIXELS_ARRAYSIZE); ASSERT(PixelBuildersAllocated == TRUE); /* Create the pixel builder data */ Result = pPixelBuilders[YIndex][XIndex]->CreateArrays(); return (Result); } /*=========================================================================== * End of Class Method CDFLandBuilder::GenerateLandPixel() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::LoadPixelRecords()" /*=========================================================================== * * Class CDFLandBuilder Method - boolean LoadPixelRecords (void); * * Load the required pixel records to generate the landscape at the current * position from the WOODS file. Returns FALSE on any error. * *=========================================================================*/ boolean CDFLandBuilder::LoadPixelRecords (void) { CDFPixelBuilder** ppPixelPtr; int Result; int XCounter; int YCounter; /* Do we have to do anything? */ if (!HasOriginPixelChanged()) return (TRUE); PROFILE_INC(); START_PROFILE(ShiftPixelBuilders); /* Do we need to load all pixel records, or can we shift some around? */ ShiftPixelBuilders(); END_PROFILE(ShiftPixelBuilders); START_PROFILE(OpenWoodsFile); /* Ensure the woods file is open */ Result = DFWoodsFile.Open(); if (!Result) return (FALSE); END_PROFILE(OpenWoodsFile); ppPixelPtr = &pPixelBuilders[0][0]; /* Load all the pixel records as required */ for (YCounter = 0; YCounter < DFLAND_PIXELS_ARRAYSIZE; YCounter++) { for (XCounter = 0; XCounter < DFLAND_PIXELS_ARRAYSIZE; XCounter++, ppPixelPtr++) { START_PROFILE(IsLoaded); /* Load the record only if required */ //if (pPixelBuilders[YCounter][XCounter]->IsLoaded()) continue; if ((*ppPixelPtr)->IsLoaded()) continue; END_PROFILE(IsLoaded); START_PROFILE(ReadPixelRecord); //Result = pPixelBuilders[YCounter][XCounter]->LoadPixelRecord(); //Result = (*ppPixelPtr)->LoadPixelRecord(); Result = DFWoodsFile.ReadPixelRecord((*ppPixelPtr)->GetXPixel(), (*ppPixelPtr)->GetYPixel(), **ppPixelPtr); END_PROFILE(ReadPixelRecord); START_PROFILE(CheckResult); if (!Result) { DFWoodsFile.Close(); return (FALSE); } END_PROFILE(CheckResult); } } START_PROFILE(WoodsClose); DFWoodsFile.Close(); END_PROFILE(WoodsClose); PROFILE_DEC(); return (TRUE); } /*=========================================================================== * End of Class Method CDFLandBuilder::LoadPixelRecords() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::SetBuilderReferences()" /*=========================================================================== * * Class CDFLandBuilder Method - void SetBuilderReferences (void) * * Sets the neighbour references in the builder array. * *=========================================================================*/ void CDFLandBuilder::SetBuilderReferences (void) { int XCounter; int YCounter; for (YCounter = 0; YCounter < DFWOODS_PIXEL_SIZE; YCounter++) { for (XCounter = 0; XCounter < DFWOODS_PIXEL_SIZE; XCounter++) { if (XCounter == 0) pPixelBuilders[YCounter][XCounter]->SetLeftPixel(NULL); else pPixelBuilders[YCounter][XCounter]->SetLeftPixel(pPixelBuilders[YCounter][XCounter-1]); if (XCounter == DFWOODS_PIXEL_SIZE - 1) pPixelBuilders[YCounter][XCounter]->SetRightPixel(NULL); else pPixelBuilders[YCounter][XCounter]->SetRightPixel(pPixelBuilders[YCounter][XCounter+1]); if (YCounter == 0) pPixelBuilders[YCounter][XCounter]->SetTopPixel(NULL); else pPixelBuilders[YCounter][XCounter]->SetTopPixel(pPixelBuilders[YCounter-1][XCounter]); if (YCounter == DFWOODS_PIXEL_SIZE - 1) pPixelBuilders[YCounter][XCounter]->SetBottomPixel(NULL); else pPixelBuilders[YCounter][XCounter]->SetBottomPixel(pPixelBuilders[YCounter+1][XCounter]); pPixelBuilders[YCounter][XCounter]->SetPosition(XCounter + LeftPixel, YCounter + TopPixel); } } } /*=========================================================================== * End of Class Method CDFLandBuilder::SetBuilderReferences() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::SetOriginPosition()" /*=========================================================================== * * Class CDFLandBuilder Method - void SetOriginPosition (X, Y, Z); * * Changes the origin of the landscape where the camera is located. Adjusts * all the required variables. * *=========================================================================*/ void CDFLandBuilder::SetOriginPosition (const float X, const float Y, const float Z) { OriginPosition.X = X; OriginPosition.Y = Y; OriginPosition.Z = Z; OriginXPixel = (int) ((X)/DFLAND_PIXEL_COORSIZE); OriginYPixel = (int) ((DFLAND_MAX_ZPOS - Z)/DFLAND_PIXEL_COORSIZE); LeftPixel = OriginXPixel - DFLAND_PIXELS_ARRAYHALFSIZE; TopPixel = OriginYPixel - DFLAND_PIXELS_ARRAYHALFSIZE; } /*=========================================================================== * End of Class Method CDFLandBuilder::SetOriginPosition() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFLandBuilder::ShiftPixelBuilders()" /*=========================================================================== * * Class CDFLandBuilder Method - void ShiftPixelBuilders (void); * * Attempt to shift records in the pixel builder array around to reuse * already loaded items. * *=========================================================================*/ void CDFLandBuilder::ShiftPixelBuilders (void) { CDFPixelBuilder* pCopyPixels[DFLAND_PIXELS_ARRAYSIZE][DFLAND_PIXELS_ARRAYSIZE]; int XPixelDiff; int YPixelDiff; int XCounter; int YCounter; int TargetX; int TargetY; float XFramePos; float ZFramePos; boolean ClearYRecord = FALSE; boolean ClearXRecord = FALSE; /* Must load all pixel records */ if (pOriginBuilder == NULL || !pOriginBuilder->IsLoaded()) { ClearPixelBuilders(); SetBuilderReferences(); return; } /* Check the previous/current pixel coordinates */ XPixelDiff = pOriginBuilder->GetXPixel() - OriginXPixel; YPixelDiff = pOriginBuilder->GetYPixel() - OriginYPixel; /* Do we have to load all new records? */ if (abs(XPixelDiff) >= DFLAND_PIXELS_ARRAYSIZE || abs(YPixelDiff) >= DFLAND_PIXELS_ARRAYSIZE) { ClearPixelBuilders(); SetBuilderReferences(); return; } /* Create a copy of the pixel record array */ memcpy(&pCopyPixels, &pPixelBuilders, sizeof(CDFPixelBuilder*) * DFLAND_PIXELS_ARRAYSIZE * DFLAND_PIXELS_ARRAYSIZE); /* Shift array row by row */ for (YCounter = 0, TargetY = YPixelDiff; YCounter < DFLAND_PIXELS_ARRAYSIZE; YCounter++, TargetY++) { /* Ensure the targety array index properly wraps */ if (TargetY < 0) { TargetY += DFLAND_PIXELS_ARRAYSIZE; ClearYRecord = (boolean) !ClearYRecord; } else if (TargetY >= DFLAND_PIXELS_ARRAYSIZE) { TargetY -= DFLAND_PIXELS_ARRAYSIZE; ClearYRecord = (boolean) !ClearYRecord; } /* Shift each column of array */ for (XCounter = 0, ClearXRecord = FALSE, TargetX = XPixelDiff; XCounter < DFLAND_PIXELS_ARRAYSIZE; XCounter++, TargetX++) { /* Ensure the targetX array index properly wraps */ if (TargetX < 0) { TargetX += DFLAND_PIXELS_ARRAYSIZE; ClearXRecord = (boolean) !ClearXRecord; } else if (TargetX >= DFLAND_PIXELS_ARRAYSIZE) { TargetX -= DFLAND_PIXELS_ARRAYSIZE; ClearXRecord = (boolean) !ClearXRecord; } /* Shift the pixel record */ pPixelBuilders[TargetY][TargetX] = pCopyPixels[YCounter][XCounter]; /* Clear the pixel builder if required */ if (ClearXRecord || ClearYRecord) { pPixelBuilders[TargetY][TargetX]->Destroy(); } /* Shift the position of the builder frame */ else { XFramePos = (float)(((float) (TargetX - DFLAND_PIXELS_ARRAYHALFSIZE)) * DFLAND_PIXEL_COORSIZE); ZFramePos = (float)(((float) (TargetY - DFLAND_PIXELS_ARRAYHALFSIZE)) * DFLAND_PIXEL_COORSIZE); pPixelBuilders[TargetY][TargetX]->SetFramePosition(XFramePos, 0, ZFramePos); } } } /* Reset the orgin pixel pointer and builder references */ pOriginBuilder = pPixelBuilders[DFLAND_PIXELS_ARRAYHALFSIZE][DFLAND_PIXELS_ARRAYHALFSIZE]; SetBuilderReferences(); } /*=========================================================================== * End of Class Method CDFLandBuilder::ShiftPixelBuilders() *=========================================================================*/