MF_API void MFCollision_BuildField(MFCollisionItem *pField) { MFCollisionField *pFieldData = (MFCollisionField*)pField->pTemplate; int numItems = pFieldData->itemList.GetLength(); if(numItems <= 0) { MFDebug_Warn(4, "EmptyField can not be generated."); return; } // find the min and max range of the objects MFVector fieldMin = MakeVector(10e+30f), fieldMax = MakeVector(-10e+30f); MFCollisionItem **ppI = pFieldData->itemList.Begin(); while(*ppI) { MFCollisionItem *pI = *ppI; MFCollisionTemplate *pT = pI->pTemplate; MFVector tMin = ApplyMatrixH(pT->boundingVolume.min, pI->worldPos); MFVector tMax = ApplyMatrixH(pT->boundingVolume.max, pI->worldPos); fieldMin = MFMin(fieldMin, tMin); fieldMax = MFMax(fieldMax, tMax); ppI++; } pFieldData->fieldMin = fieldMin; pFieldData->fieldMax = fieldMin; MFVector numCells; MFVector fieldRange = fieldMax - fieldMin; numCells.Rcp3(pFieldData->cellSize); numCells.Mul3(fieldRange, numCells); pFieldData->width = (int)MFCeil(numCells.x); pFieldData->height = (int)MFCeil(numCells.y); pFieldData->depth = (int)MFCeil(numCells.z); // this is TOTALLY broken!! .. if a big object lies in many cell's, it could easilly overflow the array. int totalCells = pFieldData->width * pFieldData->height * pFieldData->depth; int numPointers = totalCells * 2 + numItems * 16; MFCollisionItem **ppItems = (MFCollisionItem**)MFHeap_Alloc(sizeof(MFCollisionItem*) * numPointers); pFieldData->pppItems = (MFCollisionItem***)ppItems; ppItems += totalCells; for(int z=0; z<pFieldData->depth; z++) { for(int y=0; y<pFieldData->height; y++) { for(int x=0; x<pFieldData->width; x++) { pFieldData->pppItems[z*pFieldData->height*pFieldData->width + y*pFieldData->width + x] = ppItems; MFVector thisCell = fieldMin + pFieldData->cellSize * MakeVector((float)x, (float)y, (float)z); MFVector thisCellEnd = thisCell + pFieldData->cellSize; MFCollisionItem **ppI = pFieldData->itemList.Begin(); while(*ppI) { MFCollisionItem *pI = *ppI; MFCollisionTemplate *pT = pI->pTemplate; // if this item fits in this cell, insert it into this cells list. MFVector tMin = ApplyMatrixH(pT->boundingVolume.min, pI->worldPos); MFVector tMax = ApplyMatrixH(pT->boundingVolume.max, pI->worldPos); // test of bounding boxes overlap if(MFCollision_TestAABB(tMin, tMax, thisCell, thisCellEnd)) { *ppItems = pI; ++ppItems; } ppI++; } *ppItems = NULL; ++ppItems; } } } MFHeap_ValidateMemory(pFieldData->pppItems); }
void dBFrame::Draw() { if(!pMat) { MFPrimitive_DrawUntexturedQuad(rect.x-10, rect.y-10, rect.width+20, rect.height+20, colours[0]); } else { // draw background float x, y, xRemaining, yRemaining; // calculate number of tiles (including edges) int h = (int)MFCeil(rect.width / borderWidth); int w = (int)MFCeil(rect.height / borderWidth); int numTiles = (h + 2) * (w + 2); // begin immediate renderer MFMaterial_SetMaterial(pMat); MFPrimitive(PT_QuadList); MFBegin(numTiles*2); MFSetColourV(colours[0]); // render tiled background yRemaining = rect.height; for(y = 0.0f; y < rect.height; y += borderWidth) { xRemaining = rect.width; for(x = 0.0f; x < rect.width; x += borderWidth) { float xuv = xRemaining < borderWidth ? 0.25f * (xRemaining / borderWidth) : 0.25f; float yuv = yRemaining < borderWidth ? 0.25f * (yRemaining / borderWidth) : 0.25f; MFSetTexCoord1(0.25f, 0.25f); MFSetPosition(rect.x + x, rect.y + y, 0); MFSetTexCoord1(0.25f + xuv, 0.25f + yuv); MFSetPosition(rect.x + x + MFMin(borderWidth, xRemaining), rect.y + y + MFMin(borderWidth, yRemaining), 0); xRemaining -= borderWidth; } yRemaining -= borderWidth; } // draw frame // draw corners MFSetTexCoord1(0.0f, 0.0f); MFSetPosition(rect.x - borderWidth, rect.y - borderWidth, 0.0f); MFSetTexCoord1(0.25f, 0.25f); MFSetPosition(rect.x, rect.y, 0.0f); MFSetTexCoord1(0.5f, 0.0f); MFSetPosition(rect.x + rect.width, rect.y - borderWidth, 0.0f); MFSetTexCoord1(0.75f, 0.25f); MFSetPosition(rect.x + rect.width + borderWidth, rect.y, 0.0f); MFSetTexCoord1(0.0f, 0.50f); MFSetPosition(rect.x - borderWidth, rect.y + rect.height, 0.0f); MFSetTexCoord1(0.25f, 0.75f); MFSetPosition(rect.x, rect.y + rect.height + borderWidth, 0.0f); MFSetTexCoord1(0.5f, 0.5f); MFSetPosition(rect.x + rect.width, rect.y + rect.height, 0.0f); MFSetTexCoord1(0.75f, 0.75f); MFSetPosition(rect.x + rect.width + borderWidth, rect.y + rect.height + borderWidth, 0.0f); // draw vertical edges yRemaining = rect.height; for(y = 0.0f; y < rect.height; y += borderWidth) { float yuv = yRemaining < borderWidth ? 0.25f * (yRemaining / borderWidth) : 0.25f; MFSetTexCoord1(0.0f, 0.25f); MFSetPosition(rect.x - borderWidth, rect.y + y, 0.0f); MFSetTexCoord1(0.25f, 0.25f + yuv); MFSetPosition(rect.x, rect.y + y + MFMin(borderWidth, yRemaining), 0.0f); MFSetTexCoord1(0.5f, 0.25f); MFSetPosition(rect.x + rect.width, rect.y + y, 0.0f); MFSetTexCoord1(0.75f, 0.25f + yuv); MFSetPosition(rect.x + rect.width + borderWidth, rect.y + y + MFMin(borderWidth, yRemaining), 0.0f); yRemaining -= borderWidth; } // draw horizontal edges xRemaining = rect.width; for(x = 0.0f; x < rect.width; x += borderWidth) { float xuv = xRemaining < borderWidth ? 0.25f * (xRemaining / borderWidth) : 0.25f; MFSetTexCoord1(0.25f, 0.0f); MFSetPosition(rect.x + x, rect.y - borderWidth, 0.0f); MFSetTexCoord1(0.25f + xuv, 0.25f); MFSetPosition(rect.x + x + MFMin(borderWidth, xRemaining), rect.y, 0.0f); MFSetTexCoord1(0.25f, 0.5f); MFSetPosition(rect.x + x, rect.y + rect.height, 0.0f); MFSetTexCoord1(0.25f + xuv, 0.75f); MFSetPosition(rect.x + x + MFMin(borderWidth, xRemaining), rect.y + rect.height + borderWidth, 0.0f); xRemaining -= borderWidth; } MFEnd(); } }