diff options
Diffstat (limited to 'src/object.c')
| -rw-r--r-- | src/object.c | 613 |
1 files changed, 613 insertions, 0 deletions
diff --git a/src/object.c b/src/object.c new file mode 100644 index 0000000..de494a3 --- /dev/null +++ b/src/object.c @@ -0,0 +1,613 @@ + +#include "3dc.h" +#include "module.h" + +#include "stratdef.h" +#include "sfx.h" + +#define UseLocalAssert Yes +#include "ourasert.h" + + +/* globals for export */ + +int NumActiveBlocks; +DISPLAYBLOCK *ActiveBlockList[maxobjects]; + + + + +/* + Object Block Lists et al +*/ + +static int NumFreeBlocks; +static DISPLAYBLOCK *FreeBlockList[maxobjects]; +static DISPLAYBLOCK **FreeBlockListPtr = &FreeBlockList[maxobjects-1]; +static DISPLAYBLOCK FreeBlockData[maxobjects]; +static DISPLAYBLOCK **ActiveBlockListPtr = &ActiveBlockList[0]; + + +/* + Texture Animation Block Extensions +*/ + +static int NumFreeTxAnimBlocks; +static TXACTRLBLK *FreeTxAnimBlockList[maxTxAnimblocks]; +static TXACTRLBLK **FreeTxAnimBlockListPtr = &FreeTxAnimBlockList[maxTxAnimblocks-1]; +static TXACTRLBLK FreeTxAnimBlockData[maxTxAnimblocks]; + + + +/* + Light Block Extensions +*/ + +static int NumFreeLightBlocks; +static LIGHTBLOCK *FreeLightBlockList[maxlightblocks]; +static LIGHTBLOCK **FreeLightBlockListPtr = &FreeLightBlockList[maxlightblocks-1]; +static LIGHTBLOCK FreeLightBlockData[maxlightblocks]; + + + +/* + + To create the free block list, pointers to "FreeBlockData[]" must be copied + to "FreeBlockList[]". + + Also: + + "NumFreeBlocks" must be updated as "FreeBlockList[]" is created. + "NumActiveBlocks" must be initialised to zero. + +*/ +void InitialiseObjectBlocks(void) +{ + + DISPLAYBLOCK *FreeBlkPtr = &FreeBlockData[0]; + + NumActiveBlocks = 0; + + FreeBlockListPtr = &FreeBlockList[maxobjects-1]; + ActiveBlockListPtr = &ActiveBlockList[0]; + + for(NumFreeBlocks = 0; NumFreeBlocks<maxobjects; NumFreeBlocks++) { + + FreeBlockList[NumFreeBlocks] = FreeBlkPtr; + + FreeBlkPtr++; + + } +} + + +/* + + "AllocateObjectBlock()" is identical to the routine "GetBlock" + +*/ + +DISPLAYBLOCK* AllocateObjectBlock(void) +{ + + DISPLAYBLOCK *FreeBlkPtr = 0; /* Default to null ptr */ + int *sptr; + int i; + + + if(NumFreeBlocks) { + + FreeBlkPtr = *FreeBlockListPtr--; + + NumFreeBlocks--; /* One less free block */ + + /* Clear the block */ + + sptr = (int *)FreeBlkPtr; + for(i = sizeof(DISPLAYBLOCK)/4; i!=0; i--) + *sptr++ = 0; + } + + return(FreeBlkPtr); +} + + +/* + + "DeallocateObjectBlock()" is identical to the routine "ReturnBlock" + +*/ + +void DeallocateObjectBlock(DISPLAYBLOCK *dblockptr) +{ + /* Deallocate the Display Block */ + + FreeBlockListPtr++; + *FreeBlockListPtr = dblockptr; + + NumFreeBlocks++; /* One more free block */ +} + + +/* + "CreateActiveObject()" calls "AllocateObjectBlock()". An active object is + passed into the view and strategy routines unless flagged otherwise + + WARNING! + + An active object must ALWAYS be deallocated by "DestroyActiveObject()". +*/ + +DISPLAYBLOCK* CreateActiveObject(void) +{ + + DISPLAYBLOCK *dblockptr; + + + dblockptr = AllocateObjectBlock(); + + if(dblockptr) { + + *ActiveBlockListPtr++ = dblockptr; + + NumActiveBlocks++; + + + } + + return dblockptr; +} + + +/* + + DestroyActiveObject() + + Remove the block from "ActiveBlockList". + Use the array model because it's clearer. + + This function returns 0 if successful, -1 if not + +*/ + + +int DestroyActiveObject(DISPLAYBLOCK *dblockptr) +{ + int i, light; + TXACTRLBLK *taptr; + + /* If the block ptr is OK, search the Active Blocks List */ + if(dblockptr) { + + for(i = 0; i < NumActiveBlocks; i++) { + + if(ActiveBlockList[i] == dblockptr) { + + ActiveBlockList[i] = ActiveBlockList[NumActiveBlocks-1]; + NumActiveBlocks--; + ActiveBlockListPtr--; + + DestroyActiveVDB(dblockptr->ObVDBPtr); /* Checks for null */ + + if(dblockptr->ObNumLights) { + for(light = dblockptr->ObNumLights - 1; light != -1; light--) + DeleteLightBlock(dblockptr->ObLights[light], dblockptr); + } + + /* If no SB, deallocate any Texture Animation Blocks */ + + if(dblockptr->ObStrategyBlock == 0) { + + if(dblockptr->ObTxAnimCtrlBlks) { + + taptr = dblockptr->ObTxAnimCtrlBlks; + + while(taptr) { + + DeallocateTxAnimBlock(taptr); + + taptr = taptr->tac_next; + + } + + } + + } + + + /* Deallocate the Lazy Morphed Points Array Pointer */ + + #if (SupportMorphing && LazyEvaluationForMorphing) + if(dblockptr->ObMorphedPts) { + DeallocateMem(dblockptr->ObMorphedPts); + dblockptr->ObMorphedPts = 0; + } + #endif + + /* KJL 16:52:43 06/01/98 - dealloc sfx block if one exists */ + if(dblockptr->SfxPtr) + { + DeallocateSfxBlock(dblockptr->SfxPtr); + } + + DeallocateObjectBlock(dblockptr); /* Back to Free List */ + + /* If this is the current landscape, clear the pointer */ + + return 0; + } + } + } + + return -1; +} + + + + +/* + + Support Functions for Texture Animation Blocks + +*/ + +void InitialiseTxAnimBlocks(void) + +{ + + TXACTRLBLK *FreeBlkPtr = &FreeTxAnimBlockData[0]; + + + FreeTxAnimBlockListPtr = &FreeTxAnimBlockList[maxTxAnimblocks-1]; + + for(NumFreeTxAnimBlocks=0; NumFreeTxAnimBlocks < maxTxAnimblocks; NumFreeTxAnimBlocks++) { + + FreeTxAnimBlockList[NumFreeTxAnimBlocks] = FreeBlkPtr; + + FreeBlkPtr++; + + } + +} + + +/* + + Allocate a Texture Animation Block + +*/ + +TXACTRLBLK* AllocateTxAnimBlock(void) + +{ + + TXACTRLBLK *FreeBlkPtr = 0; /* Default to null ptr */ + int *sptr; + int i; + + + if(NumFreeTxAnimBlocks) { + + FreeBlkPtr = *FreeTxAnimBlockListPtr--; + + NumFreeTxAnimBlocks--; /* One less free block */ + + /* Clear the block */ + + sptr = (int *)FreeBlkPtr; + for(i = sizeof(TXACTRLBLK)/4; i!=0; i--) + *sptr++ = 0; + + } + + return FreeBlkPtr; + +} + + +/* + + Deallocate a Texture Animation Block + +*/ + +void DeallocateTxAnimBlock(TXACTRLBLK *TxAnimblockptr) + +{ + + FreeTxAnimBlockListPtr++; + + *FreeTxAnimBlockListPtr = TxAnimblockptr; + + NumFreeTxAnimBlocks++; /* One more free block */ + +} + + +/* + + Add a Texture Animation Block to a Display Block + +*/ + +void AddTxAnimBlock(DISPLAYBLOCK *dptr, TXACTRLBLK *taptr) + +{ + + TXACTRLBLK *taptr_tmp; + + + if(dptr->ObTxAnimCtrlBlks) { + + taptr_tmp = dptr->ObTxAnimCtrlBlks; + + while(taptr_tmp->tac_next) + taptr_tmp = taptr_tmp->tac_next; + + taptr_tmp->tac_next = taptr; + + } + + else dptr->ObTxAnimCtrlBlks = taptr; + +} + + + + + +/* + + Support functions for Light Blocks + +*/ + +void InitialiseLightBlocks(void) + +{ + + LIGHTBLOCK *FreeBlkPtr = &FreeLightBlockData[0]; + + + FreeLightBlockListPtr = &FreeLightBlockList[maxlightblocks-1]; + + for(NumFreeLightBlocks=0; NumFreeLightBlocks < maxlightblocks; NumFreeLightBlocks++) { + + FreeLightBlockList[NumFreeLightBlocks] = FreeBlkPtr; + + FreeBlkPtr++; + + } + +} + + +LIGHTBLOCK* AllocateLightBlock(void) + +{ + + LIGHTBLOCK *FreeBlkPtr = 0; /* Default to null ptr */ + int *lptr; + int i; + + + if(NumFreeLightBlocks) { + + FreeBlkPtr = *FreeLightBlockListPtr--; + + NumFreeLightBlocks--; /* One less free block */ + + /* Clear the block */ + + lptr = (int *)FreeBlkPtr; + for(i = sizeof(LIGHTBLOCK)/4; i!=0; i--) + *lptr++ = 0; + + } + + return(FreeBlkPtr); + +} + + +void DeallocateLightBlock(LIGHTBLOCK *lptr) + +{ + + /* Not all lights come from the free light list */ + + if(lptr->LightFlags & LFlag_WasNotAllocated) return; + + + /* Make sure that this light IS from the free light list */ + + GLOBALASSERT( + (lptr >= FreeLightBlockData) && + (lptr < &FreeLightBlockData[maxlightblocks]) + ); + + + /* Ok to return the light */ + + FreeLightBlockListPtr++; + + *FreeLightBlockListPtr = lptr; + + NumFreeLightBlocks++; /* One more free block */ + +} + + +/* + + See if there are any free slots in the dptr light block array. + If there are, allocate a light block, place it in the list and return + the pointer to the caller. + + A late addition is the passing of a light block (from somewhere, it does + not matter where). This light block is then added rather than one being + allocated from the free light block list. + +*/ + +LIGHTBLOCK* AddLightBlock(DISPLAYBLOCK *dptr, LIGHTBLOCK *lptr_to_add) + +{ + + LIGHTBLOCK **larrayptr; + LIGHTBLOCK **freelarrayptr; + LIGHTBLOCK *lptr = 0; + int i, lfree; + + + /* Are there any free slots? */ + + lfree = No; + + larrayptr = &dptr->ObLights[0]; + + for(i = MaxObjectLights; i!=0 && lfree == No; i--) { + + if(*larrayptr == 0) { + + freelarrayptr = larrayptr; + lfree = Yes; + + } + + larrayptr++; + + } + + if(lfree) { + + if(lptr_to_add) { + + lptr = lptr_to_add; + + } + + else { + + lptr = AllocateLightBlock(); + + } + + if(lptr) + { + *freelarrayptr = lptr; + dptr->ObNumLights++; + } + + } + + return lptr; + +} + + +/* + + To delete a light block, copy the end block to the new free slot and + reduce the count by one. Make sure the end block array entry is cleared. + +*/ + +void DeleteLightBlock(LIGHTBLOCK *lptr, DISPLAYBLOCK *dptr) +{ + + int i, larrayi; + + DeallocateLightBlock(lptr); + + /* What is lptr's array index? */ + + larrayi = -1; /* null value */ + + for(i = 0; i < dptr->ObNumLights; i++) + if(dptr->ObLights[i] == lptr) larrayi = i; + + + + /* Proceed only if lptr has been found in the array */ + + if(larrayi != -1) { + + /* Copy the end block to that of lptr */ + + dptr->ObLights[larrayi] = dptr->ObLights[dptr->ObNumLights - 1]; + + /* Clear the end block array entry */ + + dptr->ObLights[dptr->ObNumLights - 1] = 0; + + /* One less light in the dptr list */ + + dptr->ObNumLights--; + + } +} + + + + +/* + + When running the parallel strategies, display and light block deallocation + must only be done at the end of the frame, AFTER processor synchronisation + and BEFORE the shadow copy. + +*/ + +int DisplayAndLightBlockDeallocation(void) +{ + + DISPLAYBLOCK **activeblocksptr; + DISPLAYBLOCK *dptr; + int i, j; + LIGHTBLOCK *lptr; + + if(NumActiveBlocks) { + + activeblocksptr = &ActiveBlockList[NumActiveBlocks - 1]; + + for(i = NumActiveBlocks; i!=0; i--) { + + dptr = *activeblocksptr--; + + /* Deallocate Object? */ + + if(dptr->ObFlags2 & ObFlag2_Deallocate) { + + DestroyActiveObject(dptr); + + } + + + /* Deallocate any Lights? */ + + else { + + if(dptr->ObNumLights) { + + for(j = dptr->ObNumLights - 1; j > -1; j--) { + + lptr = dptr->ObLights[j]; + + if(lptr->LightFlags & LFlag_Deallocate) { + + DeleteLightBlock(dptr->ObLights[j], dptr); + + } + + } + + } + + } + + } + + } + return 0; +} |
