Too many units, too large a world:
This will likely cause you to have to split up the world into a quad tree for fast collision detection.
Creating a quad-tree from world data is very very simple. It's even more simple if it's 2D since the bounding checks are just simple comparisons. Also if you provide links to left, top, right, and bottom neighbors whenever a unit breaches one of the current node's boundaries you just place it into the appropriate node's list. If you set these references at startup time then crossing quad-tree boundaries is a snap.
Code:
if (object.pos.x > right)
{
removeFromList(object);
addToList(right,object);
}
...
...
One way to traverse a quad tree.
Code:
void CTerrain::TraverseQTree(TerrainPatch *pNode)
{
if (pNode->isLeaf)
{
float patch_world_width2 = m_PatchExtents.patch_width_world * 0.5f;
D3DXVECTOR3 vecPatchPos = getPatchPos(pNode->patchID);
vecPatchPos.x -= fmodf(vecPatchPos.x,patch_world_width2);
vecPatchPos.z -= fmodf(vecPatchPos.z,patch_world_width2);
D3DXVECTOR3 camPos = m_pCamera->GetPosition();
pNode->distToCamera = D3DXVec3Length(&(camPos - vecPatchPos));
m_RenderList.push_back(pNode);
}
else
{
if (m_pFrustum->IsVisibleFast(pNode->Bounds.GetMin(),
pNode->Bounds.GetMax()))
{
TraverseQTree(pNode->NW);
TraverseQTree(pNode->NE);
TraverseQTree(pNode->SW);
TraverseQTree(pNode->SE);
}
}
}
And a way to build a quad tree. Ignore the creation of vertices section. This is from a terrain renderer but it should illustrate the general concept.
Code:
void CTerrain::BuildQuadTree(TerrainPatch *pNode,
float Width,
float wx,
float wz,
float wx2,
float wz2)
{
HRESULT hr = 0;
float patch_width = (wx2 - wx);
D3DXVECTOR3 vecPatchPos;
vecPatchPos.x = (wx + wx2) * 0.5f;
vecPatchPos.y = 0.0f;
vecPatchPos.z = (wz + wz2) * 0.5f;
pNode->patchID = addPatchPos(vecPatchPos,pNode);
D3DXVECTOR3 min = D3DXVECTOR3(vecPatchPos.x - (patch_width * 0.8f),
-(patch_width * 0.8f),
vecPatchPos.z - (patch_width * 0.8f));
D3DXVECTOR3 max = D3DXVECTOR3(vecPatchPos.x + (patch_width * 0.8f),
(patch_width * 0.8f),
vecPatchPos.z + (patch_width * 0.8f));
pNode->Bounds.SetBounds(min,max);
m_num_nodes++;
if (patch_width == Width)
{
CreateVertexBuffer(pNode,wx,wz);
CreateIndexBuffer(pNode,m_PatchExtents.NumRows,m_PatchExtents.NumCols);
pNode->pTreeMgr = new CTreeMgr();
pNode->pTreeMgr->Create(this,m_RNG.RandomRange(MIN_TREES,MAX_TREES),pNode->patchID,m_PatchExtents);
pNode->pTreeMgr->SetTexture("..\\Textures\\tree2.dds");
pNode->isLeaf = true;
m_num_patches++;
return;
}
pNode->isLeaf = false;
float midwx = (wx2 + wx) * 0.5f;
float midwz = (wz2 + wz) * 0.5f;
pNode->NW = new TerrainPatch();
pNode->NW->patch_direction = NORTH_WEST;
pNode->NW->Parent = pNode;
BuildQuadTree(pNode->NW,Width,wx,wz,midwx,midwz);
pNode->NE = new TerrainPatch();
pNode->NE->Parent = pNode;
pNode->NE->patch_direction = NORTH_EAST;
BuildQuadTree(pNode->NE,Width,midwx,wz,wx2,midwz);
pNode->SW = new TerrainPatch();
pNode->SW->Parent = pNode;
pNode->SW->patch_direction = SOUTH_WEST;
BuildQuadTree(pNode->SW,Width,wx,midwz,midwx,wz2);
pNode->SE = new TerrainPatch();
pNode->SE->Parent = pNode;
pNode->SE->patch_direction = SOUTH_EAST;
BuildQuadTree(pNode->SE,Width,midwx,midwz,wx2,wz2);
pNode->NW->E_id = pNode->NE->patchID;
pNode->NW->S_id = pNode->SW->patchID;
pNode->NE->W_id = pNode->NW->patchID;
pNode->NE->S_id = pNode->SE->patchID;
pNode->SW->N_id = pNode->NW->patchID;
pNode->SW->E_id = pNode->SE->patchID;
pNode->SE->W_id = pNode->SW->patchID;
pNode->SE->N_id = pNode->NE->patchID;
}