diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index d27b37d029fb524c404faa49a70d93754720b227..b80d87ef075d31ba87a08ffbdd76b644d0fe605e 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -905,37 +905,37 @@ void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
 
 void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep)
 {
-	if(mDead)
+	if(mDead || !entry)
 	{
 		return;
 	}
 
-	bool is_orphan = false;
-	LLVOCacheEntry* parent = NULL;
-	if(entry->getParentID() > 0) //is a child
+	//shift to the local regional space from agent space
+	if(drawablep != NULL && drawablep->getVObj().notNull())
 	{
-		parent = getCacheEntry(entry->getParentID());
-		if(!parent)
-		{
-			is_orphan = true;
-			mOrphanMap[entry->getParentID()].push_back(entry->getLocalID());
-		}
+		const LLVector3& pos = drawablep->getVObj()->getPositionRegion();
+		LLVector4a shift;
+		shift.load3(pos.mV);
+		shift.sub(entry->getPositionGroup());
+		entry->shift(shift);
 	}
-	
-	if(!is_orphan)//insert to vo cache tree.
+
+	if(entry->getParentID() > 0) //is a child
 	{
-		//shift to the local regional space from agent space
-		const LLVector3 pos = drawablep->getVObj()->getPositionRegion();
-		LLVector4a vec(pos[0], pos[1], pos[2]);
-		LLVector4a shift; 
-		shift.setSub(vec, entry->getPositionGroup());
-		entry->shift(shift);
-		
-		if(parent) //is a child
+		LLVOCacheEntry* parent = getCacheEntry(entry->getParentID());
+		if(parent)
 		{
-			entry->shift(parent->getPositionGroup());
 			parent->addChild(entry);
 		}
+		else //parent not in cache.
+		{
+			//this happens only when parent is not cacheable.
+			mOrphanMap[entry->getParentID()].push_back(entry->getLocalID());
+		}
+	}
+	else //insert to vo cache tree.
+	{		
+		entry->updateParentBoundingInfo();
 		addToVOCacheTree(entry);
 	}
 
@@ -970,6 +970,10 @@ void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
 	{
 		return;
 	}
+	if(entry->getParentID() > 0)
+	{
+		return; //no child prim in cache octree.
+	}
 
 	llassert(!entry->getEntry()->hasDrawable());
 
@@ -1103,8 +1107,7 @@ F32 LLViewerRegion::updateVisibleEntries(F32 max_time)
 
 				if(vo_entry->getParentID() > 0) //is a child
 				{
-					//child visibility depends on its parent, force its parent to be visible
-					addVisibleCacheEntry(getCacheEntry(vo_entry->getParentID()));
+					//child visibility depends on its parent.
 					continue;
 				}
 
@@ -1834,11 +1837,11 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 		//1, find the parent in cache
 		LLVOCacheEntry* parent = getCacheEntry(parent_id);
 		
-		//2, parent is not in the cache or not probed, put into the orphan list.
-		if(!parent || !parent->getEntry())
+		//2, parent is not in the cache, put into the orphan list.
+		if(!parent)
 		{
 			//check if parent is non-cacheable and already created
-			if(!parent && isNonCacheableObjectCreated(parent_id))
+			if(isNonCacheableObjectCreated(parent_id))
 			{
 				//parent is visible, so is the child.
 				addVisibleCacheEntry(entry);
@@ -1846,10 +1849,10 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 			else
 			{
 				entry->setBoundingInfo(pos, scale);
-			    mOrphanMap[parent_id].push_back(entry->getLocalID());
+				mOrphanMap[parent_id].push_back(entry->getLocalID());
 		    }
 		}
-		else //parent in cache octree or probed
+		else //parent in cache.
 		{
 			if(!parent->isState(LLVOCacheEntry::INACTIVE)) 
 			{
@@ -1859,8 +1862,6 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 			else
 			{
 				entry->setBoundingInfo(pos, scale);
-				entry->shift(parent->getPositionGroup());
-				addToVOCacheTree(entry);
 				parent->addChild(entry);
 			}
 		}
@@ -1890,8 +1891,6 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry)
 				LLVOCacheEntry* child = getCacheEntry((*orphans)[i]);
 				if(child)
 				{
-					child->shift(entry->getPositionGroup());
-					addToVOCacheTree(child);
 					entry->addChild(child);
 				}
 			}
@@ -2063,7 +2062,7 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
 		{
 			// Record a hit
 			entry->recordHit();
-		cache_miss_type = CACHE_MISS_TYPE_NONE;
+			cache_miss_type = CACHE_MISS_TYPE_NONE;
 			entry->setUpdateFlags(flags);
 			
 			if(entry->isState(LLVOCacheEntry::ACTIVE))
@@ -2072,7 +2071,11 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss
 				return true;
 			}
 
-			if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE))
+			if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE)) //already probed
+			{
+				return true;
+			}
+			if(entry->getParentID() > 0) //already probed
 			{
 				return true;
 			}
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 60d78890b5f59f2807155ecd296d83e01d634582..69c32db13e645a11e10d215f29428865d24ab567 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -253,6 +253,12 @@ void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
 	}
 
 	mChildrenList.push_back(entry);
+
+	//update parent bbox
+	if(getEntry() != NULL && isState(INACTIVE))
+	{
+		updateParentBoundingInfo(entry);
+	}
 }
 	
 LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc)
@@ -367,9 +373,69 @@ void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scal
 	
 	setPositionGroup(center);
 	setSpatialExtents(newMin, newMax);
-	setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f));
+
+	if(getNumOfChildren() > 0) //has children
+	{
+		updateParentBoundingInfo();
+	}
+	else
+	{
+		setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f));
+	}
+}
+
+//make the parent bounding box to include all children
+void LLVOCacheEntry::updateParentBoundingInfo()
+{
+	if(mChildrenList.empty())
+	{
+		return;
+	}
+
+	for(S32 i = 0; i < mChildrenList.size(); i++)
+	{
+		updateParentBoundingInfo(mChildrenList[i]);
+	}
 }
 
+//make the parent bounding box to include this child
+void LLVOCacheEntry::updateParentBoundingInfo(const LLVOCacheEntry* child)
+{
+	const LLVector4a* child_exts = child->getSpatialExtents();
+	LLVector4a newMin, newMax;
+	newMin = child_exts[0];
+	newMax = child_exts[1];
+	
+	//move to regional space.
+	{
+		const LLVector4a& parent_pos = getPositionGroup();
+		newMin.add(parent_pos);
+		newMax.add(parent_pos);
+	}
+
+	//update parent's bbox(min, max)
+	const LLVector4a* parent_exts = getSpatialExtents();
+	update_min_max(newMin, newMax, parent_exts[0]);
+	update_min_max(newMin, newMax, parent_exts[1]);
+	for(S32 i = 0; i < 4; i++)
+	{
+		llclamp(newMin[i], 0.f, 256.f);
+		llclamp(newMax[i], 0.f, 256.f);
+	}
+	setSpatialExtents(newMin, newMax);
+
+	//update parent's bbox center
+	LLVector4a center;
+	center.setAdd(newMin, newMax);
+	center.mul(0.5f);
+	setPositionGroup(center);	
+
+	//update parent's bbox size vector
+	LLVector4a size;
+	size.setSub(newMax, newMin);
+	size.mul(0.5f);
+	setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f));
+}
 //-------------------------------------------------------------------
 //LLVOCachePartition
 //-------------------------------------------------------------------
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index c42374e154b2b5b1abcabef11e42fb0b12a1662c..0248298eb57bd74f1ed9704fea4c646cb9cd5b48 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -110,10 +110,10 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 	LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];}
 	S32  getNumOfChildren()         {return mChildrenList.size();}
 	void clearChildrenList()        {mChildrenList.clear();}
-
-	//called from processing object update message
-	void setBoundingInfo(const LLVector3& pos, const LLVector3& scale);
 	
+	void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message	
+	void updateParentBoundingInfo();
+
 	void setTouched(BOOL touched = TRUE) {mTouched = touched;}
 	BOOL isTouched() const {return mTouched;}
 
@@ -123,6 +123,8 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 private:
 	static U32  getInvisibleObjectsLiveTime();
 
+	void updateParentBoundingInfo(const LLVOCacheEntry* child);	
+
 public:
 	typedef std::map<U32, LLPointer<LLVOCacheEntry> >	   vocache_entry_map_t;
 	typedef std::set<LLVOCacheEntry*>                      vocache_entry_set_t;