Ticket #2022: cleanedupTerr.patch
File cleanedupTerr.patch, 11.4 KB (added by , 10 years ago) |
---|
-
components/CCmpTerritoryManager.cpp
88 88 // connected flag in bit 6 (TERRITORY_CONNECTED_MASK); 89 89 // processed flag in bit 7 (TERRITORY_PROCESSED_MASK) 90 90 Grid<u8>* m_Territories; 91 Grid<u8>* m_InfluenceGrid; 92 93 // wraitii: Defining these as part of the object allows to avoid a few temporaries 94 // wraitii: at least Kuranes says so. 95 std::vector<std::pair<player_id_t, Grid<u32>* > > playerGrids; 96 97 std::map<player_id_t, std::vector<entity_id_t> > influenceEntities; 98 std::vector<entity_id_t> rootInfluenceEntities; 99 100 std::vector<std::pair<u16, u16> > tileStack; 101 102 // this is regularly used as a gridu32 103 std::deque<Grid<u32>* > grid32Pool; 91 104 92 105 // Set to true when territories change; will send a TerritoriesChanged message 93 106 // during the Update phase … … 113 126 virtual void Init(const CParamNode& UNUSED(paramNode)) 114 127 { 115 128 m_Territories = NULL; 129 m_InfluenceGrid = NULL; 116 130 m_DebugOverlay = NULL; 117 131 // m_DebugOverlay = new TerritoryOverlay(*this); 118 132 m_BoundaryLinesDirty = true; … … 135 149 virtual void Deinit() 136 150 { 137 151 SAFE_DELETE(m_Territories); 152 SAFE_DELETE(m_InfluenceGrid); 138 153 SAFE_DELETE(m_DebugOverlay); 154 for(std::deque<Grid<u32>* >::iterator it = grid32Pool.begin(); it != grid32Pool.end(); ++it ) 155 delete *it; 139 156 } 140 157 141 158 virtual void Serialize(ISerializer& UNUSED(serialize)) … … 345 362 346 363 u16 tilesW = cmpTerrain->GetTilesPerSide(); 347 364 u16 tilesH = cmpTerrain->GetTilesPerSide(); 348 349 m_Territories = new Grid<u8>(tilesW, tilesH); 365 366 if (!m_Territories) 367 m_Territories = new Grid<u8>(tilesW, tilesH); 368 else 369 m_Territories->reset(); 350 370 351 371 // Compute terrain-passability-dependent costs per tile 352 Grid<u8> influenceGrid(tilesW, tilesH); 372 if (!m_InfluenceGrid) 373 m_InfluenceGrid = new Grid<u8>(tilesW, tilesH); 374 else 375 m_InfluenceGrid->reset(); 353 376 354 377 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); 355 378 ICmpPathfinder::pass_class_t passClassDefault = cmpPathfinder->GetPassabilityClass("default"); 356 379 ICmpPathfinder::pass_class_t passClassUnrestricted = cmpPathfinder->GetPassabilityClass("unrestricted"); 357 380 381 358 382 const Grid<u16>& passGrid = cmpPathfinder->GetPassabilityGrid(); 383 384 // wraitii: locality changes, perhaps unecessary 385 u16* passGridData = passGrid.m_Data; 386 u8* influenceGridData = m_InfluenceGrid->m_Data; 387 u32 gridSize = tilesH * tilesW; 388 359 389 for (u16 j = 0; j < tilesH; ++j) 360 390 { 361 391 for (u16 i = 0; i < tilesW; ++i) … … 368 398 cost = m_ImpassableCost; 369 399 else 370 400 cost = 1; 371 influenceGrid.set(i, j, cost);401 m_InfluenceGrid->set(i, j, cost); 372 402 } 373 403 } 374 404 … … 376 406 CComponentManager::InterfaceList influences = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerritoryInfluence); 377 407 378 408 // Allow influence entities to override the terrain costs 379 RasteriseInfluences(influences, influenceGrid);409 RasteriseInfluences(influences, *m_InfluenceGrid); 380 410 381 411 // Split influence entities into per-player lists, ignoring any with invalid properties 382 std::map<player_id_t, std::vector<entity_id_t> > influenceEntities; 383 std::vector<entity_id_t> rootInfluenceEntities; 384 for (CComponentManager::InterfaceList::iterator it = influences.begin(); it != influences.end(); ++it) 412 influenceEntities.clear(); 413 rootInfluenceEntities.clear(); 414 const CComponentManager::InterfaceList::const_iterator itiEnd = influences.end(); 415 for (CComponentManager::InterfaceList::const_iterator it = influences.begin(); it != itiEnd; ++it) 385 416 { 386 417 // Ignore any with no weight or radius (to avoid divide-by-zero later) 387 418 ICmpTerritoryInfluence* cmpTerritoryInfluence = static_cast<ICmpTerritoryInfluence*>(it->second); … … 413 444 } 414 445 415 446 // For each player, store the sum of influences on each tile 416 std::vector<std::pair<player_id_t, Grid<u32> > > playerGrids; 447 playerGrids.clear(); // start by resetting. 448 417 449 // TODO: this is a large waste of memory; we don't really need to store 418 450 // all the intermediate grids 419 451 420 for (std::map<player_id_t, std::vector<entity_id_t> >::iterator it = influenceEntities.begin(); it != influenceEntities.end(); ++it) 452 OpenQueue openTiles; 453 Grid<u32>* entityGrid = new Grid<u32>(tilesW, tilesH); 454 455 const std::map<player_id_t, std::vector<entity_id_t> >::iterator itieEnd = influenceEntities.end(); 456 for (std::map<player_id_t, std::vector<entity_id_t> >::iterator it = influenceEntities.begin(); it != itieEnd; ++it) 421 457 { 422 Grid<u32> playerGrid(tilesW, tilesH);458 Grid<u32>* playerGrid = new Grid<u32>(tilesW, tilesH); 423 459 424 std::vector<entity_id_t>& ents = it->second; 425 for (std::vector<entity_id_t>::iterator eit = ents.begin(); eit != ents.end(); ++eit) 460 std::vector<entity_id_t> &ents = it->second; 461 std::vector<entity_id_t>::const_iterator eitEnd = ents.end(); 462 for (std::vector<entity_id_t>::const_iterator eit = ents.begin(); eit != eitEnd; ++eit) 426 463 { 427 464 // Compute the influence map of the current entity, then add it to the player grid 428 429 Grid<u32> entityGrid(tilesW, tilesH); 465 entityGrid->reset(); 430 466 431 467 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), *eit); 432 468 CFixedVector2D pos = cmpPosition->GetPosition2D(); … … 442 478 // when doing all the sums 443 479 444 480 // Initialise the tile under the entity 445 entityGrid.set(i, j, weight); 446 OpenQueue openTiles; 447 OpenQueue::Item tile = { std::make_pair((u16)i, (i16)j), weight }; 481 entityGrid->set(i, j, weight); 482 OpenQueue::Item tile = { std::make_pair(i, j), weight }; 448 483 openTiles.push(tile); 449 484 450 485 // Expand influences outwards 451 FloodFill( entityGrid, influenceGrid, openTiles, falloff);486 FloodFill(*entityGrid, *m_InfluenceGrid, openTiles, falloff); 452 487 453 488 // TODO: we should do a sparse grid and only add the non-zero regions, for performance 454 for (u16 j = 0; j < entityGrid .m_H; ++j)455 for (u16 i = 0; i < entityGrid .m_W; ++i)456 playerGrid .set(i, j, playerGrid.get(i, j) + entityGrid.get(i, j));489 for (u16 j = 0; j < entityGrid->m_H; ++j) 490 for (u16 i = 0; i < entityGrid->m_W; ++i) 491 playerGrid->set(i, j, playerGrid->get(i, j) + entityGrid->get(i, j)); 457 492 } 458 493 459 494 playerGrids.push_back(std::make_pair(it->first, playerGrid)); … … 467 502 u32 bestWeight = 0; 468 503 for (size_t k = 0; k < playerGrids.size(); ++k) 469 504 { 470 u32 w = playerGrids[k].second .get(i, j);505 u32 w = playerGrids[k].second->get(i, j); 471 506 if (w > bestWeight) 472 507 { 473 508 player_id_t id = playerGrids[k].first; … … 479 514 } 480 515 481 516 // Detect territories connected to a 'root' influence (typically a civ center) 482 // belonging to their player, and mark them with the connected flag 483 for (std::vector<entity_id_t>::iterator it = rootInfluenceEntities.begin(); it != rootInfluenceEntities.end(); ++it) 517 // belonging to their player, and mark them with the connected flag, 518 519 // wraitii: those two things moved ouy of the loop. 520 // probably useless obfuscation if the vector is small enough. 521 Grid<u8>& grid = *m_Territories; 522 u16 maxi = (u16)(grid.m_W-1); 523 u16 maxj = (u16)(grid.m_H-1); 524 std::vector<entity_id_t>::const_iterator itrEnd = rootInfluenceEntities.end(); 525 for (std::vector<entity_id_t>::const_iterator it = rootInfluenceEntities.begin(); it != itrEnd; ++it) 484 526 { 485 527 // (These components must be valid else the entities wouldn't be added to this list) 486 528 CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), *it); … … 492 534 493 535 u8 owner = (u8)cmpOwnership->GetOwner(); 494 536 495 if ( m_Territories->get(i, j) != owner)537 if (grid.get(i, j) != owner) 496 538 continue; 497 539 498 540 // TODO: would be nice to refactor some of the many flood fill 499 541 // algorithms in this component 500 501 Grid<u8>& grid = *m_Territories;502 503 u16 maxi = (u16)(grid.m_W-1);504 u16 maxj = (u16)(grid.m_H-1);505 506 std::vector<std::pair<u16, u16> > tileStack;507 508 542 #define MARK_AND_PUSH(i, j) STMT(grid.set(i, j, owner | TERRITORY_CONNECTED_MASK); tileStack.push_back(std::make_pair(i, j)); ) 509 543 510 544 MARK_AND_PUSH(i, j); … … 560 594 561 595 void CCmpTerritoryManager::RasteriseInfluences(CComponentManager::InterfaceList& infls, Grid<u8>& grid) 562 596 { 563 for (CComponentManager::InterfaceList::iterator it = infls.begin(); it != infls.end(); ++it) 597 598 CComponentManager::InterfaceList::const_iterator itEnd = infls.end(); 599 for (CComponentManager::InterfaceList::const_iterator it = infls.begin(); it != itEnd; ++it) 564 600 { 565 601 ICmpTerritoryInfluence* cmpTerritoryInfluence = static_cast<ICmpTerritoryInfluence*>(it->second); 566 602 … … 691 727 m_BoundaryLinesDirty = false; 692 728 } 693 729 730 // wraitii: this has been moved out of the loop, probably with reason. 731 float alpha = 0.2f + 0.8f * fabsf((float)cos(m_AnimTime * M_PI));// TODO: should let artists tweak this 694 732 for (size_t i = 0; i < m_BoundaryLines.size(); ++i) 695 733 { 696 734 if (!m_BoundaryLines[i].connected) 697 735 { 698 736 CColor c = m_BoundaryLines[i].color; 699 c.a *= 0.2f + 0.8f * fabsf((float)cos(m_AnimTime * M_PI)); // TODO: should let artists tweak this737 c.a *= alpha; 700 738 m_BoundaryLines[i].overlay.m_Color = c; 701 739 } 702 740 } … … 714 752 715 753 player_id_t CCmpTerritoryManager::GetOwner(entity_pos_t x, entity_pos_t z) 716 754 { 717 u16 i, j;718 755 CalculateTerritories(); 719 756 if (!m_Territories) 720 757 return 0; 721 758 759 // wraitii: this was moved to be closer to where it's used. OK. 760 u16 i, j; 722 761 NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H); 723 762 return m_Territories->get(i, j) & TERRITORY_PLAYER_MASK; 724 763 } 725 764 726 765 bool CCmpTerritoryManager::IsConnected(entity_pos_t x, entity_pos_t z) 727 766 { 728 u16 i, j;729 767 CalculateTerritories(); 730 768 if (!m_Territories) 731 769 return false; 732 770 771 // wraitii: this was moved to be closer to where it's used. OK. 772 u16 i, j; 733 773 NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H); 734 774 return (m_Territories->get(i, j) & TERRITORY_CONNECTED_MASK) != 0; 735 775 } … … 762 802 case 6: RenderTile(CColor(1, 0, 1, a), false); break; 763 803 default: RenderTile(CColor(1, 1, 1, a), false); break; 764 804 } 765 } 805 } 806 No newline at end of file -
helpers/Grid.h
76 76 delete[] m_Data; 77 77 } 78 78 79 void reset()79 inline void reset() 80 80 { 81 81 if (m_Data) 82 82 memset(m_Data, 0, m_W*m_H*sizeof(T)); 83 83 } 84 84 85 void set(int i, int j, const T& value)85 inline void set(int i, int j, const T& value) 86 86 { 87 87 #if GRID_BOUNDS_DEBUG 88 88 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); 89 89 #endif 90 90 m_Data[j*m_W + i] = value; 91 91 } 92 93 inline void add(int i, int j, T val) 94 { 95 #if GRID_BOUNDS_DEBUG 96 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); 97 #endif 98 m_Data[j*m_W + i] += val; 99 } 100 inline void getPtr(int i, int j) 101 { 102 #if GRID_BOUNDS_DEBUG 103 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); 104 #endif 105 return m_Data[j*m_W + i]; 106 } 92 107 93 T&get(int i, int j) const108 inline T& get(int i, int j) const 94 109 { 95 110 #if GRID_BOUNDS_DEBUG 96 111 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); … … 144 159 delete[] m_Data; 145 160 } 146 161 147 void reset()162 inline void reset() 148 163 { 149 164 for (size_t i = 0; i < (size_t)(m_BW*m_BH); ++i) 150 165 delete[] m_Data[i]; … … 152 167 memset(m_Data, 0, m_BW*m_BH*sizeof(T*)); 153 168 } 154 169 155 void set(int i, int j, const T& value)170 inline void set(int i, int j, const T& value) 156 171 { 157 172 #if GRID_BOUNDS_DEBUG 158 173 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); … … 160 175 GetBucket(i, j)[(j % BucketSize)*BucketSize + (i % BucketSize)] = value; 161 176 } 162 177 163 T& get(int i, int j)178 inline T& get(int i, int j) 164 179 { 165 180 #if GRID_BOUNDS_DEBUG 166 181 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H);