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) { resize_impl(size, NULL); }
void resize(rcSizeType size, const T& value) { resize_impl(size, &value); } 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 push_back(const T& value);
void pop_back() { rcAssert(m_size > 0); back().~T(); m_size--; } void pop_back() { rcAssert(m_size > 0); back().~T(); m_size--; }
void clear() { resize(0); }
rcSizeType size() const { return m_size; } rcSizeType size() const { return m_size; }
rcSizeType capacity() const { return m_cap; } rcSizeType capacity() const { return m_cap; }
bool empty() const { return size() == 0; } bool empty() const { return size() == 0; }

View File

@ -343,6 +343,14 @@ static bool floodRegion(int x, int y, int i,
return count > 0; 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, static void expandRegions(int maxIter, unsigned short level,
rcCompactHeightfield& chf, rcCompactHeightfield& chf,
unsigned short* srcReg, unsigned short* srcDist, 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; int iter = 0;
while (stack.size() > 0) while (stack.size() > 0)
{ {
int failed = 0; int failed = 0;
dirtyEntries.resize(0); dirtyEntries.clear();
for (int j = 0; j < stack.size(); j += 3) for (int j = 0; j < stack.size(); j += 3)
{ {
@ -425,9 +433,7 @@ static void expandRegions(int maxIter, unsigned short level,
if (r) if (r)
{ {
stack[j+2] = -1; // mark as used stack[j+2] = -1; // mark as used
dirtyEntries.push(i); dirtyEntries.push_back(DirtyEntry(i, r, d2));
dirtyEntries.push(r);
dirtyEntries.push(d2);
} }
else 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. // Copy entries that differ between src and dst to keep them in sync.
for (int i = 0; i < dirtyEntries.size(); i+=3) { for (int i = 0; i < dirtyEntries.size(); i++) {
int idx = dirtyEntries[i]; int idx = dirtyEntries[i].index;
srcReg[idx] = (unsigned short)dirtyEntries[i+1]; srcReg[idx] = dirtyEntries[i].region;
srcDist[idx] = (unsigned short)dirtyEntries[i+2]; srcDist[idx] = dirtyEntries[i].distance2;
} }
if (failed*3 == stack.size()) if (failed*3 == stack.size())

View File

@ -892,6 +892,10 @@ struct Copier {
const int Copier::kAlive = 0x1f; const int Copier::kAlive = 0x1f;
const int Copier::kDead = 0xde; const int Copier::kDead = 0xde;
struct NotDefaultConstructible {
NotDefaultConstructible(int) {}
};
TEST_CASE("rcVector") TEST_CASE("rcVector")
{ {
SECTION("Vector basics.") SECTION("Vector basics.")
@ -1068,6 +1072,17 @@ TEST_CASE("rcVector")
REQUIRE(Incrementor::destructions == 0); REQUIRE(Incrementor::destructions == 0);
REQUIRE(Incrementor::copies == 10); 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. // TODO: Implement benchmarking for platforms other than posix.