Ticket #2913: clever_dirty_visibility.patch
File clever_dirty_visibility.patch, 9.1 KB (added by , 9 years ago) |
---|
-
source/simulation2/components/CCmpRangeManager.cpp
98 98 } 99 99 100 100 /** 101 * Computes the 2-bit visibility for one player, given the total 32-bit visibilities 102 */ 101 * Returns shared 1-bit mask for given list of players. 102 */ 103 static u32 CalcSharedDirtyVisibilityMask(std::vector<player_id_t> players) 104 { 105 u16 playerMask = 0; 106 for (size_t i = 0; i < players.size(); i++) 107 { 108 if (players[i] > 0 && players[i] <= 16) 109 playerMask |= (0x1 << (players[i] - 1)); 110 } 111 112 return playerMask; 113 } 114 115 /** 116 * Computes the 2-bit visibility for one player, given the total 32-bit visibilities 117 */ 103 118 static inline u8 GetPlayerVisibility(u32 visibilities, player_id_t player) 104 119 { 105 120 if (player > 0 && player <= 16) … … 108 123 } 109 124 110 125 /** 126 * Test whether the visibility is dirty for a given LoS tile and a given player 127 */ 128 static inline bool IsVisibilityDirty(u16 dirty, player_id_t player) 129 { 130 if (player > 0 && player <= 16) 131 return (dirty >> (player - 1)) & 0x1; 132 return false; 133 } 134 135 /** 111 136 * Checks whether v is in a parabolic range of (0,0,0) 112 137 * The highest point of the paraboloid is (0,range/2,0) 113 138 * and the circle of distance 'range' around (0,0,0) on height y=0 is part of the paraboloid … … 302 327 // Cache for visibility tracking (not serialized) 303 328 i32 m_LosTilesPerSide; 304 329 bool m_GlobalVisibilityUpdate; 305 std::vector<u 8> m_DirtyVisibility;330 std::vector<u16> m_DirtyVisibility; 306 331 std::vector<std::set<entity_id_t> > m_LosTiles; 307 332 // List of entities that must be updated, regardless of the status of their tile 308 333 std::vector<entity_id_t> m_ModifiedEntities; … … 323 348 324 349 // Shared LOS masks, one per player. 325 350 std::vector<u32> m_SharedLosMasks; 351 // Shared dirty visibility masks, one per player. 352 std::vector<u16> m_SharedDirtyVisibilityMasks; 326 353 327 354 // Cache explored vertices per player (not serialized) 328 355 u32 m_TotalInworldVertices; … … 351 378 m_LosRevealAll.resize(MAX_LOS_PLAYER_ID+2,false); 352 379 m_LosRevealAll[0] = true; 353 380 m_SharedLosMasks.resize(MAX_LOS_PLAYER_ID+2,0); 381 m_SharedDirtyVisibilityMasks.resize(MAX_LOS_PLAYER_ID + 2, 0); 354 382 355 383 m_LosCircular = false; 356 384 m_TerrainVerticesPerSide = 0; … … 384 412 385 413 SerializeVector<SerializeU32_Unbounded>()(serialize, "los state", m_LosState); 386 414 SerializeVector<SerializeU32_Unbounded>()(serialize, "shared los masks", m_SharedLosMasks); 415 SerializeVector<SerializeU16_Unbounded>()(serialize, "shared dirty visibility masks", m_SharedDirtyVisibilityMasks); 387 416 } 388 417 389 418 virtual void Serialize(ISerializer& serialize) … … 1489 1518 if (player <= 0) 1490 1519 return ComputeLosVisibility(ent, player); 1491 1520 1492 if ( m_DirtyVisibility[n])1521 if (IsVisibilityDirty(m_DirtyVisibility[n], player)) 1493 1522 return ComputeLosVisibility(ent, player); 1494 1523 1495 1524 if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), entId) != m_ModifiedEntities.end()) … … 1546 1575 1547 1576 for (i32 n = 0; n < m_LosTilesPerSide*m_LosTilesPerSide; ++n) 1548 1577 { 1549 if (m_DirtyVisibility[n] == 1 || m_GlobalVisibilityUpdate)1578 for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID + 1; ++player) 1550 1579 { 1551 for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin(); 1552 it != m_LosTiles[n].end(); 1553 ++it) 1580 if (IsVisibilityDirty(m_DirtyVisibility[n], player) || m_GlobalVisibilityUpdate) 1554 1581 { 1555 UpdateVisibility(*it); 1582 for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin(); 1583 it != m_LosTiles[n].end(); 1584 ++it) 1585 { 1586 UpdateVisibility(*it, player); 1587 } 1556 1588 } 1557 m_DirtyVisibility[n] = 0;1558 1589 } 1590 m_DirtyVisibility[n] = 0; 1559 1591 } 1560 1592 1561 for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it) 1593 // Don't bother updating modified entities if the update was global 1594 if (!m_GlobalVisibilityUpdate) 1562 1595 { 1563 // Don't bother updating if we already did it in a global update 1564 if (!m_GlobalVisibilityUpdate) 1596 for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it) 1565 1597 UpdateVisibility(*it); 1566 1598 } 1599 1567 1600 m_ModifiedEntities.clear(); 1568 1569 1601 m_GlobalVisibilityUpdate = false; 1570 1602 } 1571 1603 … … 1575 1607 m_ModifiedEntities.push_back(ent); 1576 1608 } 1577 1609 1578 void UpdateVisibility(entity_id_t ent )1610 void UpdateVisibility(entity_id_t ent, player_id_t player) 1579 1611 { 1580 // Warning: Code related to fogging (like posting VisibilityChanged messages)1581 // shouldn't be invoked while keeping an iterator to an element of m_EntityData.1582 // Otherwise, by deleting mirage entities and so on,1583 // that code will change the indexes in the map, leading to segfaults.1584 1612 EntityMap<EntityData>::iterator itEnts = m_EntityData.find(ent); 1585 1613 if (itEnts == m_EntityData.end()) 1586 1614 return; 1587 1615 1588 // So we just remember what visibilities to update and do that later. 1589 std::vector<u8> oldVisibilities; 1590 std::vector<u8> newVisibilities; 1616 u8 oldVis = GetPlayerVisibility(itEnts->second.visibilities, player); 1617 u8 newVis = ComputeLosVisibility(itEnts->first, player); 1618 1619 if (oldVis == newVis) 1620 return; 1591 1621 1592 for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID+1; ++player) 1593 { 1594 u8 oldVis = GetPlayerVisibility(itEnts->second.visibilities, player); 1595 u8 newVis = ComputeLosVisibility(itEnts->first, player); 1596 1597 oldVisibilities.push_back(oldVis); 1598 newVisibilities.push_back(newVis); 1622 itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2 * (player - 1))) | (newVis << 2 * (player - 1)); 1599 1623 1600 if (oldVis != newVis)1601 itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2*(player-1))) | (newVis << 2*(player-1));1602 1624 CMessageVisibilityChanged msg(player, ent, oldVis, newVis); 1625 GetSimContext().GetComponentManager().PostMessage(ent, msg); 1626 } 1603 1627 1604 for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID+1; ++player) 1605 { 1606 if (oldVisibilities[player-1] == newVisibilities[player-1]) 1607 continue; 1608 1609 CMessageVisibilityChanged msg(player, ent, oldVisibilities[player-1], newVisibilities[player-1]); 1610 GetSimContext().GetComponentManager().PostMessage(ent, msg); 1611 } 1628 void UpdateVisibility(entity_id_t ent) 1629 { 1630 for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID + 1; ++player) 1631 UpdateVisibility(ent, player); 1612 1632 } 1613 1633 1614 1634 virtual void SetLosRevealAll(player_id_t player, bool enabled) … … 1653 1673 virtual void SetSharedLos(player_id_t player, std::vector<player_id_t> players) 1654 1674 { 1655 1675 m_SharedLosMasks[player] = CalcSharedLosMask(players); 1676 m_SharedDirtyVisibilityMasks[player] = CalcSharedDirtyVisibilityMask(players); 1656 1677 } 1657 1678 1658 1679 virtual u32 GetSharedLosMask(player_id_t player) … … 1814 1835 int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO; 1815 1836 1816 1837 if (j > 0 && i > 0) 1817 m_DirtyVisibility[n1] = 1;1838 m_DirtyVisibility[n1] |= m_SharedDirtyVisibilityMasks[owner]; 1818 1839 if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide) 1819 m_DirtyVisibility[n2] = 1;1840 m_DirtyVisibility[n2] |= m_SharedDirtyVisibilityMasks[owner]; 1820 1841 if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0) 1821 m_DirtyVisibility[n3] = 1;1842 m_DirtyVisibility[n3] |= m_SharedDirtyVisibilityMasks[owner]; 1822 1843 if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide) 1823 m_DirtyVisibility[n4] = 1;1844 m_DirtyVisibility[n4] |= m_SharedDirtyVisibilityMasks[owner]; 1824 1845 } 1825 1846 1826 1847 ASSERT(counts[idx] < 65535); … … 1859 1880 int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO; 1860 1881 1861 1882 if (j > 0 && i > 0) 1862 m_DirtyVisibility[n1] = 1;1883 m_DirtyVisibility[n1] |= m_SharedDirtyVisibilityMasks[owner]; 1863 1884 if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide) 1864 m_DirtyVisibility[n2] = 1;1885 m_DirtyVisibility[n2] |= m_SharedDirtyVisibilityMasks[owner]; 1865 1886 if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0) 1866 m_DirtyVisibility[n3] = 1;1887 m_DirtyVisibility[n3] |= m_SharedDirtyVisibilityMasks[owner]; 1867 1888 if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide) 1868 m_DirtyVisibility[n4] = 1;1889 m_DirtyVisibility[n4] |= m_SharedDirtyVisibilityMasks[owner]; 1869 1890 } 1870 1891 } 1871 1892 } -
source/simulation2/serialization/SerializeTemplates.h
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 151 151 } 152 152 }; 153 153 154 struct SerializeU16_Unbounded 155 { 156 void operator()(ISerializer& serialize, const char* name, u16 value) 157 { 158 serialize.NumberU16_Unbounded(name, value); 159 } 160 161 void operator()(IDeserializer& deserialize, const char* name, u16& value) 162 { 163 deserialize.NumberU16_Unbounded(name, value); 164 } 165 }; 166 154 167 struct SerializeU32_Unbounded 155 168 { 156 169 void operator()(ISerializer& serialize, const char* name, u32 value)