diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index ad3df55ef1e3aa04bcb6385590d25d7df295f749..a480eed2e760e8aafb2a4c76f4e119f2ff36b5ff 100755
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1058,12 +1058,8 @@ bool LLDrawable::isRecentlyVisible() const
 
 	if(!vis)
 	{
-		LLviewerOctreeGroup* group = getGroup();
-		if (group && group->isRecentlyVisible())
-		{
-			LLViewerOctreeEntryData::setVisible();
-			vis = TRUE ;
-		}
+		const U32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
+		vis = (sCurVisible - getVisible() < MIN_VIS_FRAME_RANGE);
 	}
 
 	return vis ;
@@ -1140,14 +1136,6 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
 	return retval;
 }
 
-//virtual
-U32 LLDrawable::getMinFrameRange() const
-{
-	const U32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
-
-	return MIN_VIS_FRAME_RANGE ;
-}
-
 //=======================================
 // Spatial Partition Bridging Drawable
 //=======================================
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index efb3e1d89d6cdd1468b0726fe5efdb9cbdc31ab2..b94f663f21ec8aa4743c6cd24dcf65f8ecb9e891 100755
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -194,7 +194,6 @@ class LLDrawable
 
 	LLSpatialPartition* getSpatialPartition();
 	
-	virtual U32 getMinFrameRange()const;
 	void removeFromOctree();
 
 	void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index 637505a826e5b866841793106486141f4c022092..481befdb44bf1921a590f1d12d864303e7c928a2 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -409,7 +409,7 @@ bool LLViewerOctreeEntryData::isRecentlyVisible() const
 		return true;
 	}
 
-	return (sCurVisible - mEntry->mVisible < getMinFrameRange());
+	return false;
 }
 
 void LLViewerOctreeEntryData::setVisible() const
diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h
index 7fdb5661d8d11d308f494e1a9de9c385a71f9f2d..e610db96eb9395aa430fd6c32854eeac7a6d513f 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -149,8 +149,6 @@ class LLViewerOctreeEntryData : public LLRefCount
 	
 	virtual void setOctreeEntry(LLViewerOctreeEntry* entry);
 
-	virtual U32  getMinFrameRange()const = 0;
-
 	F32                  getBinRadius() const   {return mEntry->getBinRadius();}
 	const LLVector4a*    getSpatialExtents() const;
 	LLviewerOctreeGroup* getGroup()const;
@@ -327,6 +325,7 @@ class LLOcclusionCullingGroup : public LLviewerOctreeGroup
 
 	//virtual
 	BOOL isRecentlyVisible() const;
+	LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;}
 
 	static U32 getNewOcclusionQueryObjectName();
 	static void releaseOcclusionQueryObjectName(U32 name);
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 838ac353d1cdb307460a8ab339927040307908bb..dc7b907a3514284c49d07b1df725c2bc26bec4fa 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -238,12 +238,6 @@ void LLVOCacheEntry::setState(U32 state)
 	}
 }
 
-//virtual 
-U32  LLVOCacheEntry::getMinFrameRange()const
-{
-	return mMinFrameRange;
-}
-
 void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
 {
 	llassert(entry != NULL);
@@ -261,6 +255,12 @@ void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
 	if(getEntry() != NULL && isState(INACTIVE))
 	{
 		updateParentBoundingInfo(entry);
+		if(getGroup())
+		{
+			LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)getGroup();
+			group->unbound();
+			((LLVOCachePartition*)group->getSpatialPartition())->setDirty();
+		}
 	}
 }
 	
@@ -365,6 +365,27 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
 	return success ;
 }
 
+bool LLVOCacheEntry::isRecentlyVisible() const
+{
+	bool vis = LLViewerOctreeEntryData::isRecentlyVisible();
+
+	if(!vis)
+	{
+		vis = (sCurVisible - getVisible() < mMinFrameRange);
+	}
+
+	//combination of projected area and squared distance
+	if(!vis && !mParentID && mSceneContrib > 0.0311f) //projection angle > 10 (degree)
+	{
+		//squared distance
+		const F32 SQUARED_CUT_OFF_DIST = 256.0; //16m
+		F32 rad = getBinRadius();
+		vis = (rad * rad / mSceneContrib < SQUARED_CUT_OFF_DIST);
+	}
+
+	return vis;
+}
+
 void LLVOCacheEntry::calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update)
 {
 	if(!needs_update && getVisible() >= last_update)
@@ -381,8 +402,11 @@ void LLVOCacheEntry::calcSceneContribution(const LLVector3& camera_origin, bool
 	lookAt.setSub(center, origin);
 	F32 squared_dist = lookAt.dot3(lookAt).getF32();
 
-	F32 rad = getBinRadius();
-	mSceneContrib = rad * rad / squared_dist;
+	if(squared_dist > 0.f)
+	{
+		F32 rad = getBinRadius();
+		mSceneContrib = rad * rad / squared_dist;
+	}
 
 	setVisible();
 }
@@ -479,12 +503,17 @@ LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp)
 	new LLOcclusionCullingGroup(mOctree, this);
 }
 
+void LLVOCachePartition::setDirty()
+{
+	mDirty = TRUE;
+}
+
 void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry)
 {
 	llassert(entry->hasVOCacheEntry());
 
 	mOctree->insert(entry);
-	mDirty = TRUE;
+	setDirty();
 }
 	
 void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry)
@@ -609,13 +638,13 @@ S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion)
 	}
 	mCulledTime[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame();
 
-	if(!mDirty && !mCullHistory[LLViewerCamera::sCurCameraID] && LLViewerRegion::isViewerCameraStatic())
-	{
-		return 0; //nothing changed, skip culling
-	}
+	//if(!mDirty && !mCullHistory[LLViewerCamera::sCurCameraID] && LLViewerRegion::isViewerCameraStatic())
+	//{
+	//	return 0; //nothing changed, skip culling
+	//}
 
 	((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound();
-	mCullHistory[LLViewerCamera::sCurCameraID] <<= 2;
+	mCullHistory[LLViewerCamera::sCurCameraID] <<= 1;
 
 	//localize the camera
 	LLVector3 region_agent = mRegionp->getOriginAgent();
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index c448b97b80671c4758a45098a8c298afa635fdd7..4eca08344519d2e050e8b69acdc6992f2bb9d6b0 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -83,12 +83,14 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 	bool hasState(U32 state)   {return mState & state;}
 	U32  getState() const      {return mState;}
 	
+	//virtual
+	bool isRecentlyVisible() const;
+
 	U32 getLocalID() const			{ return mLocalID; }
 	U32 getCRC() const				{ return mCRC; }
 	S32 getHitCount() const			{ return mHitCount; }
 	S32 getCRCChangeCount() const	{ return mCRCChangeCount; }
-	U32 getMinFrameRange()const;	
-
+	
 	void calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update);
 	void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;}
 	F32 getSceneContribution() const             { return mSceneContrib;}
@@ -162,14 +164,13 @@ class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTr
 	/*virtual*/ S32 cull(LLCamera &camera, bool do_occlusion);
 	void addOccluders(LLviewerOctreeGroup* gp);
 	void resetOccluders();
-
-	static	LLTrace::MemStatHandle	sMemStat;
-
-public:	
 	void processOccluders(LLCamera* camera);
+	
+	void setDirty();
 
 public:
 	static BOOL sNeedsOcclusionCheck;
+	static	LLTrace::MemStatHandle	sMemStat;
 
 private:
 	BOOL  mDirty;