diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 054afd3e95909fbd32338baa5415aaa23f29d4fd..6a1e3804be3da99b2ceb4ad01100298157262782 100755
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -161,6 +161,22 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)
 
 // ---------------- test methods  ---------------- 
 
+bool LLCamera::isChanged()
+{
+	bool changed = false;
+	for (U32 i = 0; i < mPlaneCount; i++)
+	{
+		U8 mask = mPlaneMask[i];
+		if (mask != 0xff && !changed)
+		{
+			changed = !mAgentPlanes[i].equal(mLastAgentPlanes[i]);
+		}
+		mLastAgentPlanes[i].set(mAgentPlanes[i]);
+	}
+
+	return changed;
+}
+
 S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius, const LLPlane* planes) 
 {
 	static const LLVector4a scaler[] = {
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 898d73ed7ee05e7a6d8730281b91dfc4460befbc..a7cdcff4acaa415d196050cfd5f2511863dcdb38 100755
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -110,6 +110,7 @@ class LLCamera
 private:
 	LL_ALIGN_16(LLPlane mAgentPlanes[7]);  //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
 	LL_ALIGN_16(LLPlane mRegionPlanes[7]);  //frustum planes in a local region space, derived from mAgentPlanes
+	LL_ALIGN_16(LLPlane mLastAgentPlanes[7]);
 	U8 mPlaneMask[8];         // 8 for alignment	
 	
 	F32 mView;					// angle between top and bottom frustum planes in radians.
@@ -138,6 +139,7 @@ class LLCamera
 	LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
 	virtual ~LLCamera();
 	
+	bool isChanged(); //check if mAgentPlanes changed since last frame.
 
 	void setUserClipPlane(LLPlane& plane);
 	void disableUserClipPlane();
diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h
index 3c32441b11875f9503c7de564ccb7f85e346a081..64a3eed0e53eac073bacac36907ca12101ca22ce 100755
--- a/indra/llmath/llplane.h
+++ b/indra/llmath/llplane.h
@@ -93,7 +93,13 @@ class LLPlane
 	{ 
 		return mV.greaterEqual(LLVector4a::getZero()).getGatheredBits() & LLVector4Logical::MASK_XYZ;
 	}
-		
+	
+	//check if two planes are nearly same
+	bool equal(const LLPlane& p) const
+	{
+		return mV.equals4(p.mV);
+	}
+
 private:
 	LLVector4a mV;
 } LL_ALIGN_POSTFIX(16);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b80d87ef075d31ba87a08ffbdd76b644d0fe605e..cd8466d948cec6f7062b391a4b8eab53039b38bc 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -87,6 +87,7 @@ const F32 CAP_REQUEST_TIMEOUT = 18;
 const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
 
 BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE;
+S32  LLViewerRegion::sLastCameraUpdated = 0;
 
 typedef std::map<std::string, std::string> CapabilityMap;
 
@@ -992,6 +993,7 @@ void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
 	}
 
 	mImpl->mVOCachePartition->removeEntry(entry->getEntry());
+	entry->mLastCameraUpdated = sLastCameraUpdated;
 }
 
 //add the visible entries
@@ -1219,7 +1221,7 @@ F32 LLViewerRegion::killInvisibleObjects(F32 max_time)
 			iter = mImpl->mActiveSet.begin();
 		}
 
-		if(!(*iter)->isRecentlyVisible())
+		if(!(*iter)->isRecentlyVisible() && (*iter)->mLastCameraUpdated != sLastCameraUpdated)
 		{
 			killObject((*iter), delete_list);
 		}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 29483662e87b6b8a0ce8cb2de2881cffa334d53c..2ac934d19c6af9041cc45c22b40c033fc4e84000 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -411,6 +411,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	LLDynamicArray<LLUUID> mMapAvatarIDs;
 
 	static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not.
+	static S32  sLastCameraUpdated;
 private:
 	LLViewerRegionImpl * mImpl;
 	LLFrameTimer         mRegionTimer;
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 69c32db13e645a11e10d215f29428865d24ab567..6e0243e985077dc1d91e7f1f982422cceb7d3a86 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -219,18 +219,14 @@ void LLVOCacheEntry::setState(U32 state)
 
 	if(getState() == ACTIVE)
 	{
-		const S32 MIN_REAVTIVE_INTERVAL = 32;
+		const S32 MIN_REAVTIVE_INTERVAL = 128;
 		U32 last_visible = getVisible();
 		
 		setVisible();
 
-		if(getVisible() - last_visible < MIN_REAVTIVE_INTERVAL + mMinFrameRange)
+		if(getVisible() - last_visible > MIN_REAVTIVE_INTERVAL + mMinFrameRange)
 		{
-			mMinFrameRange = llmin(mMinFrameRange * 2, getInvisibleObjectsLiveTime() * 32);
-		}
-		else
-		{
-			mMinFrameRange = getInvisibleObjectsLiveTime(); //reset
+			mLastCameraUpdated = 0; //reset
 		}
 	}
 }
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index 0248298eb57bd74f1ed9704fea4c646cb9cd5b48..816ef88dc4207bd3054dbe272cec42093775f64e 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -130,6 +130,7 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 	typedef std::set<LLVOCacheEntry*>                      vocache_entry_set_t;
 	typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t;	
 
+	S32                         mLastCameraUpdated;
 protected:
 	U32							mLocalID;
 	U32                         mParentID;
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 3dfe4c5e5f96d9ddfd58d015a74047fcbcd785b9..ea0e38824bdf0f5da118bab8f0408bdfc17a2798 100755
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -666,6 +666,11 @@ void LLWorld::updateRegions(F32 max_update_time)
 	LLTimer update_timer;
 	BOOL did_one = FALSE;
 	
+	if(LLViewerCamera::getInstance()->isChanged())
+	{
+		LLViewerRegion::sLastCameraUpdated = LLViewerOctreeEntryData::getCurrentFrame();
+	}
+
 	// Perform idle time updates for the regions (and associated surfaces)
 	for (region_list_t::iterator iter = mRegionList.begin();
 		 iter != mRegionList.end(); ++iter)