From bfe520387ed3061ba55ea2e58c565016e7a3159e Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 13 Feb 2014 17:03:36 -0600
Subject: MAINT-2876 Fix for freeze when editing certain rigged meshes at high
 altitude.

---
 indra/llmath/lloctree.h                 | 15 +++++++++++----
 indra/newview/app_settings/settings.xml | 12 ++++++++++++
 indra/newview/llspatialpartition.cpp    |  1 +
 indra/newview/llviewercontrol.cpp       |  1 +
 indra/newview/pipeline.cpp              |  1 +
 5 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index 7348904c61..f7d5f14ba3 100755
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -36,6 +36,8 @@
 
 
 extern U32 gOctreeMaxCapacity;
+extern float gOctreeMinSize;
+
 /*#define LL_OCTREE_PARANOIA_CHECK 0
 #if LL_DARWIN
 #define LL_OCTREE_MAX_CAPACITY 32
@@ -106,6 +108,7 @@ public:
 	:	mParent((oct_node*)parent), 
 		mOctant(octant) 
 	{ 
+		llassert(size[0] >= gOctreeMinSize*0.5f);
 		//always keep a NULL terminated list to avoid out of bounds exceptions in debug builds
 		mData.push_back(NULL);
 		mDataEnd = &mData[0];
@@ -213,7 +216,7 @@ public:
 		F32 size = mSize[0];
 		F32 p_size = size * 2.f;
 
-		return (radius <= 0.001f && size <= 0.001f) ||
+		return (radius <= gOctreeMinSize && size <= gOctreeMinSize) ||
 				(radius <= p_size && radius > size);
 	}
 
@@ -319,7 +322,7 @@ public:
 		//is it here?
 		if (isInside(data->getPositionGroup()))
 		{
-			if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
+			if (((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius()) ||
 				(data->getBinRadius() > getSize()[0] &&	parent && parent->getElementCount() >= gOctreeMaxCapacity))) 
 			{ //it belongs here
 				mData.push_back(NULL);
@@ -356,8 +359,9 @@ public:
 				LLVector4a val;
 				val.setSub(center, getCenter());
 				val.setAbs(val);
-								
-				S32 lt = val.lessThan(LLVector4a::getEpsilon()).getGatheredBits() & 0x7;
+				LLVector4a min_diff(gOctreeMinSize);
+
+				S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7;
 
 				if( lt == 0x7 )
 				{
@@ -389,6 +393,7 @@ public:
 				}
 #endif
 
+				llassert(size[0] >= gOctreeMinSize*0.5f);
 				//make the new kid
 				child = new LLOctreeNode<T>(center, size, this);
 				addChild(child);
@@ -796,6 +801,8 @@ public:
 				this->setSize(size2);
 				this->updateMinMax();
 
+				llassert(size[0] >= gOctreeMinSize);
+
 				//copy our children to a new branch
 				LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
 				
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 671b679d24..745434e85a 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7982,6 +7982,18 @@
     <integer>128</integer>
   </map>
 
+  <key>OctreeMinimumNodeSize</key>
+  <map>
+    <key>Comment</key>
+    <string>Minimum size of any octree node</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>0.01</real>
+  </map>
+
   <key>OctreeStaticObjectSizeFactor</key>
   <map>
     <key>Comment</key>
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 2c83f6d0b7..69ba51b10a 100755
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -78,6 +78,7 @@ U32 LLSpatialGroup::sNodeCount = 0;
 std::set<GLuint> LLSpatialGroup::sPendingQueries;
 
 U32 gOctreeMaxCapacity;
+F32 gOctreeMinSize;
 
 BOOL LLSpatialGroup::sNoDelete = FALSE;
 
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 744ec4de2b..002a337e04 100755
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -368,6 +368,7 @@ static bool handleRepartition(const LLSD&)
 	if (gPipeline.isInit())
 	{
 		gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+		gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
 		gObjectList.repartitionObjects();
 	}
 	return true;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 5da8a78b1b..ab6e5cc353 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -498,6 +498,7 @@ void LLPipeline::init()
 	refreshCachedSettings();
 
 	gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+	gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
 	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
 	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
 	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
-- 
cgit v1.2.3