Switch expandRegions to using a rcTempVector of structs rather than a blob of ints.

Also updates rcVector::clear() to not require the contained type to be default-constructible.
This commit is contained in:
Maciej Babinski 2018-05-15 07:59:19 -05:00 committed by Jakob Botsch Nielsen
parent 689cf00bd9
commit bec073c947
3 changed files with 33 additions and 10 deletions

View File

@ -123,10 +123,12 @@ class rcVectorBase {
void resize(rcSizeType size) { resize_impl(size, NULL); }
void resize(rcSizeType size, const T& value) { resize_impl(size, &value); }
// Not implemented as resize(0) because resize requires T to be default-constructible.
void clear() { destroy_range(0, m_size); m_size = 0; }
void push_back(const T& value);
void pop_back() { rcAssert(m_size > 0); back().~T(); m_size--; }
void clear() { resize(0); }
rcSizeType size() const { return m_size; }
rcSizeType capacity() const { return m_cap; }
bool empty() const { return size() == 0; }

View File

@ -343,6 +343,14 @@ static bool floodRegion(int x, int y, int i,
return count > 0;
}
// Struct to keep track of entries in the region table that have been changed.
struct DirtyEntry {
DirtyEntry(int index_, unsigned short region_, unsigned short distance2_)
: index(index_), region(region_), distance2(distance2_) {}
int index;
unsigned short region;
unsigned short distance2;
};
static void expandRegions(int maxIter, unsigned short level,
rcCompactHeightfield& chf,
unsigned short* srcReg, unsigned short* srcDist,
@ -384,12 +392,12 @@ static void expandRegions(int maxIter, unsigned short level,
}
}
rcIntArray dirtyEntries;
rcTempVector<DirtyEntry> dirtyEntries;
int iter = 0;
while (stack.size() > 0)
{
int failed = 0;
dirtyEntries.resize(0);
dirtyEntries.clear();
for (int j = 0; j < stack.size(); j += 3)
{
@ -425,9 +433,7 @@ static void expandRegions(int maxIter, unsigned short level,
if (r)
{
stack[j+2] = -1; // mark as used
dirtyEntries.push(i);
dirtyEntries.push(r);
dirtyEntries.push(d2);
dirtyEntries.push_back(DirtyEntry(i, r, d2));
}
else
{
@ -436,10 +442,10 @@ static void expandRegions(int maxIter, unsigned short level,
}
// Copy entries that differ between src and dst to keep them in sync.
for (int i = 0; i < dirtyEntries.size(); i+=3) {
int idx = dirtyEntries[i];
srcReg[idx] = (unsigned short)dirtyEntries[i+1];
srcDist[idx] = (unsigned short)dirtyEntries[i+2];
for (int i = 0; i < dirtyEntries.size(); i++) {
int idx = dirtyEntries[i].index;
srcReg[idx] = dirtyEntries[i].region;
srcDist[idx] = dirtyEntries[i].distance2;
}
if (failed*3 == stack.size())

View File

@ -892,6 +892,10 @@ struct Copier {
const int Copier::kAlive = 0x1f;
const int Copier::kDead = 0xde;
struct NotDefaultConstructible {
NotDefaultConstructible(int) {}
};
TEST_CASE("rcVector")
{
SECTION("Vector basics.")
@ -1068,6 +1072,17 @@ TEST_CASE("rcVector")
REQUIRE(Incrementor::destructions == 0);
REQUIRE(Incrementor::copies == 10);
}
SECTION("Type Requirements")
{
// This section verifies that we don't enforce unnecessary
// requirements on the types we hold.
// Implementing clear as resize(0) will cause this to fail
// as resize(0) requires T to be default constructible.
rcTempVector<NotDefaultConstructible> v;
v.clear();
}
}
// TODO: Implement benchmarking for platforms other than posix.