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-861f7616d084
master
Cyp 2010-01-28 14:57:53 +00:00 committed by Git SVN Gateway
parent a19eb86fda
commit 2c900bbc39
3 changed files with 82 additions and 32 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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.