Cleanup and code that could be used to make clusters (whatever that means) spend a lot less time updating (if that wouldn't break anything).
git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@9545 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
a19eb86fda
commit
2c900bbc39
103
src/mapgrid.cpp
103
src/mapgrid.cpp
|
@ -35,14 +35,16 @@
|
|||
void **gridIterator;
|
||||
|
||||
PointTree *gridPointTree = NULL; // A quad-tree-like object.
|
||||
PointTree::Filter *gridFiltersSeen;
|
||||
PointTree::Filter *gridFiltersUnseen;
|
||||
PointTree::Filter *gridFiltersDroidsByPlayer;
|
||||
|
||||
// initialise the grid system
|
||||
BOOL gridInitialise(void)
|
||||
{
|
||||
ASSERT(gridPointTree == NULL, "gridInitialise already called, without calling gridShutDown.");
|
||||
gridPointTree = new PointTree;
|
||||
gridFiltersSeen = new PointTree::Filter[MAX_PLAYERS];
|
||||
gridFiltersUnseen = new PointTree::Filter[MAX_PLAYERS];
|
||||
gridFiltersDroidsByPlayer = new PointTree::Filter[MAX_PLAYERS];
|
||||
|
||||
return true; // Yay, nothing failed!
|
||||
}
|
||||
|
@ -76,7 +78,8 @@ void gridReset(void)
|
|||
|
||||
for (unsigned player = 0; player < MAX_PLAYERS; ++player)
|
||||
{
|
||||
gridFiltersSeen[player].reset(*gridPointTree);
|
||||
gridFiltersUnseen[player].reset(*gridPointTree);
|
||||
gridFiltersDroidsByPlayer[player].reset(*gridPointTree);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,8 +88,10 @@ void gridShutDown(void)
|
|||
{
|
||||
delete gridPointTree;
|
||||
gridPointTree = NULL;
|
||||
delete[] gridFiltersSeen;
|
||||
gridFiltersSeen = NULL;
|
||||
delete[] gridFiltersUnseen;
|
||||
gridFiltersUnseen = NULL;
|
||||
delete[] gridFiltersDroidsByPlayer;
|
||||
gridFiltersDroidsByPlayer = NULL;
|
||||
}
|
||||
|
||||
static bool isInRadius(int32_t x, int32_t y, uint32_t radius)
|
||||
|
@ -96,39 +101,24 @@ static bool isInRadius(int32_t x, int32_t y, uint32_t radius)
|
|||
|
||||
// initialise the grid system to start iterating through units that
|
||||
// could affect a location (x,y in world coords)
|
||||
void gridStartIterate(int32_t x, int32_t y, uint32_t radius)
|
||||
template<class Condition>
|
||||
void gridStartIterateFiltered(int32_t x, int32_t y, uint32_t radius, PointTree::Filter *filter, Condition const &condition)
|
||||
{
|
||||
gridPointTree->query(x, y, radius);
|
||||
PointTree::ResultVector::iterator w = gridPointTree->lastQueryResults.begin(), i;
|
||||
for (i = w; i != gridPointTree->lastQueryResults.end(); ++i)
|
||||
if (filter == NULL)
|
||||
{
|
||||
BASE_OBJECT *obj = static_cast<BASE_OBJECT *>(*i);
|
||||
if (isInRadius(obj->pos.x - x, obj->pos.y - y, radius)) // Check that search result is less than radius (since they can be up to a factor of sqrt(2) more).
|
||||
{
|
||||
*w = *i;
|
||||
++w;
|
||||
}
|
||||
gridPointTree->query(x, y, radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridPointTree->query(*filter, x, y, radius);
|
||||
}
|
||||
gridPointTree->lastQueryResults.erase(w, i); // Erase all points that were a bit too far.
|
||||
gridPointTree->lastQueryResults.push_back(NULL); // NULL-terminate the result.
|
||||
gridIterator = &gridPointTree->lastQueryResults[0];
|
||||
/*
|
||||
// In case you are curious.
|
||||
debug(LOG_WARNING, "gridStartIterate(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size() - 1);
|
||||
*/
|
||||
}
|
||||
|
||||
// Sorry for the duplicate code.
|
||||
void gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player)
|
||||
{
|
||||
gridPointTree->query(gridFiltersSeen[player], x, y, radius);
|
||||
PointTree::ResultVector::iterator w = gridPointTree->lastQueryResults.begin(), i;
|
||||
for (i = w; i != gridPointTree->lastQueryResults.end(); ++i)
|
||||
{
|
||||
BASE_OBJECT *obj = static_cast<BASE_OBJECT *>(*i);
|
||||
if (obj->seenThisTick[player] == 255) // Check if we should skip this object.
|
||||
if (!condition.test(obj)) // Check if we should skip this object.
|
||||
{
|
||||
gridFiltersSeen[player].erase(gridPointTree->lastFilteredQueryIndices[i - gridPointTree->lastQueryResults.begin()]); // Stop the object from appearing in future searches.
|
||||
filter->erase(gridPointTree->lastFilteredQueryIndices[i - gridPointTree->lastQueryResults.begin()]); // Stop the object from appearing in future searches.
|
||||
}
|
||||
else if (isInRadius(obj->pos.x - x, obj->pos.y - y, radius)) // Check that search result is less than radius (since they can be up to a factor of sqrt(2) more).
|
||||
{
|
||||
|
@ -141,6 +131,57 @@ void gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player)
|
|||
gridIterator = &gridPointTree->lastQueryResults[0];
|
||||
/*
|
||||
// In case you are curious.
|
||||
debug(LOG_WARNING, "gridStartIterateUnseen(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size() - 1);
|
||||
debug(LOG_WARNING, "gridStartIterateFiltered(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size() - 1);
|
||||
*/
|
||||
}
|
||||
|
||||
struct ConditionTrue
|
||||
{
|
||||
bool test(BASE_OBJECT *obj) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void gridStartIterate(int32_t x, int32_t y, uint32_t radius)
|
||||
{
|
||||
gridStartIterateFiltered(x, y, radius, NULL, ConditionTrue());
|
||||
}
|
||||
|
||||
struct ConditionDroidsByPlayer
|
||||
{
|
||||
ConditionDroidsByPlayer(int32_t player_) : player(player_) {}
|
||||
bool test(BASE_OBJECT *obj) const
|
||||
{
|
||||
return obj->type == OBJ_DROID && obj->player == player;
|
||||
}
|
||||
int player;
|
||||
};
|
||||
|
||||
void gridStartIterateDroidsByPlayer(int32_t x, int32_t y, uint32_t radius, int player)
|
||||
{
|
||||
gridStartIterateFiltered(x, y, radius, &gridFiltersDroidsByPlayer[player], ConditionDroidsByPlayer(player));
|
||||
}
|
||||
|
||||
struct ConditionUnseen
|
||||
{
|
||||
ConditionUnseen(int32_t player_) : player(player_) {}
|
||||
bool test(BASE_OBJECT *obj) const
|
||||
{
|
||||
return obj->seenThisTick[player] < UBYTE_MAX;
|
||||
}
|
||||
int player;
|
||||
};
|
||||
|
||||
void gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player)
|
||||
{
|
||||
gridStartIterateFiltered(x, y, radius, &gridFiltersUnseen[player], ConditionUnseen(player));
|
||||
}
|
||||
|
||||
BASE_OBJECT **gridIterateDup(void)
|
||||
{
|
||||
size_t bytes = gridPointTree->lastQueryResults.size()*sizeof(void *);
|
||||
BASE_OBJECT **ret = (BASE_OBJECT **)malloc(bytes);
|
||||
memcpy(ret, &gridPointTree->lastQueryResults[0], bytes);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@ extern void gridReset(void);
|
|||
/// Find all objects within radius. Call gridIterate() to get the search results.
|
||||
extern void gridStartIterate(int32_t x, int32_t y, uint32_t radius);
|
||||
|
||||
// Isn't, but could be used by some cluster system. Don't really understand what cluster.c is for.
|
||||
/// Find all objects within radius where object->type == OBJ_DROID && object->player == player. Call gridIterate() to get the search results.
|
||||
extern void gridStartIterateDroidsByPlayer(int32_t x, int32_t y, uint32_t radius, int player);
|
||||
|
||||
// Used for visibility.
|
||||
/// Find all objects within radius where object->seenThisTick[player] != 255. Call gridIterate() to get the search results.
|
||||
extern void gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player);
|
||||
|
||||
|
@ -55,6 +60,10 @@ static inline BASE_OBJECT *gridIterate(void)
|
|||
return (BASE_OBJECT *)*gridIterator++;
|
||||
}
|
||||
|
||||
// Isn't, but could be used by some weird recursive calls in cluster.c.
|
||||
/// Make a copy of the list. Free with free().
|
||||
BASE_OBJECT **gridIterateDup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif //__cplusplus
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
class Filter ///< Filters are invalidated when modifying the PointTree.
|
||||
{
|
||||
public:
|
||||
Filter() {} ///< Must be reset before use.
|
||||
Filter() : data(1) {} ///< Must be reset before use.
|
||||
Filter(PointTree const &pointTree) : data(pointTree.points.size() + 1) {}
|
||||
void reset(PointTree const &pointTree) { data.assign(pointTree.points.size() + 1, 0); }
|
||||
void erase(unsigned index) { data[index] = std::max(data[index], 1u); } ///< Erases the point from query results using the filter.
|
||||
|
|
Loading…
Reference in New Issue