This commit is contained in:
Shyotl
2012-07-18 00:54:52 -05:00
parent cc5ffafd7c
commit a56ad597d4
13 changed files with 208 additions and 96 deletions

View File

@@ -89,9 +89,9 @@ public:
typedef LLOctreeTraveler<T> oct_traveler;
typedef LLTreeTraveler<T> tree_traveler;
typedef typename std::set<LLPointer<T> > element_list;
typedef typename element_list::iterator element_iter;
typedef typename element_list::const_iterator const_element_iter;
typedef LLPointer<T>* element_list;
typedef LLPointer<T>* element_iter;
typedef const LLPointer<T>* const_element_iter;
typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
typedef typename std::vector<LLOctreeNode<T>* > child_list;
typedef LLTreeNode<T> BaseType;
@@ -115,6 +115,9 @@ public:
: mParent((oct_node*)parent),
mOctant(octant)
{
mData = NULL;
mDataEnd = NULL;
mCenter = center;
mSize = size;
@@ -133,6 +136,16 @@ public:
{
BaseType::destroyListeners();
for (U32 i = 0; i < mElementCount; ++i)
{
mData[i]->setBinIndex(-1);
mData[i] = NULL;
}
free(mData);
mData = NULL;
mDataEnd = NULL;
for (U32 i = 0; i < getChildCount(); i++)
{
delete getChild(i);
@@ -232,9 +245,14 @@ public:
virtual bool isLeaf() const { return mChild.empty(); }
U32 getElementCount() const { return mElementCount; }
bool isEmpty() const { return mElementCount == 0; }
element_list& getData() { return mData; }
const element_list& getData() const { return mData; }
element_iter getDataBegin() { return mData; }
element_iter getDataEnd() { return mDataEnd; }
const_element_iter getDataBegin() const { return mData; }
const_element_iter getDataEnd() const { return mDataEnd; }
U32 getChildCount() const { return mChildCount; }
oct_node* getChild(U32 index) { return mChild[index]; }
const oct_node* getChild(U32 index) const { return mChild[index]; }
@@ -299,7 +317,7 @@ public:
virtual bool insert(T* data)
{
if (data == NULL)
if (data == NULL || data->getBinIndex() != -1)
{
OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
return false;
@@ -309,22 +327,19 @@ public:
//is it here?
if (isInside(data->getPositionGroup()))
{
if (((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius())) ||
if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
#if LL_OCTREE_PARANOIA_CHECK
//if this is a redundant insertion, error out (should never happen)
if (mData.find(data) != mData.end())
{
llwarns << "Redundant octree insertion detected. " << data << llendl;
return false;
}
#endif
mElementCount++;
mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
mData.insert(data);
//avoid unref on uninitialized memory
memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>));
mData[mElementCount-1] = data;
mDataEnd = mData + mElementCount;
data->setBinIndex(mElementCount-1);
BaseType::insert(data);
mElementCount = mData.size();
return true;
}
else
@@ -358,10 +373,16 @@ public:
if( lt == 0x7 )
{
mData.insert(data);
BaseType::insert(data);
mElementCount++;
mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
mElementCount = mData.size();
//avoid unref on uninitialized memory
memset(mData+mElementCount-1, 0, sizeof(LLPointer<T>));
mData[mElementCount-1] = data;
mDataEnd = mData + mElementCount;
data->setBinIndex(mElementCount-1);
BaseType::insert(data);
return true;
}
@@ -410,23 +431,59 @@ public:
return false;
}
void _remove(T* data, S32 i)
{ //precondition -- mElementCount > 0, idx is in range [0, mElementCount)
mElementCount--;
data->setBinIndex(-1);
if (mElementCount > 0)
{
if (mElementCount != i)
{
mData[i] = mData[mElementCount]; //might unref data, do not access data after this point
mData[i]->setBinIndex(i);
}
mData[mElementCount] = NULL; //needed for unref
mData = (element_list) realloc(mData, sizeof(LLPointer<T>)*mElementCount);
mDataEnd = mData+mElementCount;
}
else
{
mData[0] = NULL; //needed for unref
free(mData);
mData = NULL;
mDataEnd = NULL;
}
notifyRemoval(data);
checkAlive();
}
bool remove(T* data)
{
if (mData.find(data) != mData.end())
{ //we have data
mData.erase(data);
mElementCount = mData.size();
this->notifyRemoval(data);
checkAlive();
return true;
S32 i = data->getBinIndex();
if (i >= 0 && i < (S32)mElementCount)
{
if (mData[i] == data)
{ //found it
_remove(data, i);
llassert(data->getBinIndex() == -1);
return true;
}
}
else if (isInside(data))
if (isInside(data))
{
oct_node* dest = getNodeAt(data);
if (dest != this)
{
return dest->remove(data);
bool ret = dest->remove(data);
llassert(data->getBinIndex() == -1);
return ret;
}
}
@@ -445,19 +502,20 @@ public:
//node is now root
llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl;
node->removeByAddress(data);
llassert(data->getBinIndex() == -1);
return true;
}
void removeByAddress(T* data)
{
if (mData.find(data) != mData.end())
for (U32 i = 0; i < mElementCount; ++i)
{
mData.erase(data);
mElementCount = mData.size();
this->notifyRemoval(data);
llwarns << "FOUND!" << llendl;
checkAlive();
return;
if (mData[i] == data)
{ //we have data
_remove(data, i);
llwarns << "FOUND!" << llendl;
return;
}
}
for (U32 i = 0; i < getChildCount(); i++)
@@ -624,6 +682,7 @@ protected:
U32 mChildCount;
element_list mData;
element_iter mDataEnd;
U32 mElementCount;
};