diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 4fc25dcc241224de7beab5eee8c964a031ae7db8..8612c463760fbb3e4129ddce6350a9e73949e8e5 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -34,6 +34,7 @@ set(cmake_SOURCE_FILES
     FindXmlRpcEpi.cmake
     FMOD.cmake
     FreeType.cmake
+    GLOD.cmake
     GStreamer010Plugin.cmake
     GooglePerfTools.cmake
     JPEG.cmake
@@ -41,6 +42,7 @@ set(cmake_SOURCE_FILES
     LLAudio.cmake
     LLCharacter.cmake
     LLCommon.cmake
+    LLConvexDecompInter.cmake
     LLCrashLogger.cmake
     LLDatabase.cmake
     LLImage.cmake
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index ebc43134cbe4ccc93b078c05880aa9a5cce19567..27d35e95ffc4c10550c69dcc757b795ee9afd2b3 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -114,10 +114,8 @@ class LL_COMMON_API LLAssetType
 
 		AT_LINK_FOLDER = 25,
 			// Inventory folder link
-#if LL_MESH_ENABLED
 		AT_MESH = 49,
 		    // Mesh data in our proprietary SLM format
-#endif
 
 		AT_COUNT = 50,
 
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index d2fc67ef6451d8ba55600dba1f5f5b5770974433..17ed3df951d32c237ab2e95a306aee6607869ccc 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -67,10 +67,7 @@ class LLInventoryType
 		IT_WEARABLE = 18,
 		IT_ANIMATION = 19,
 		IT_GESTURE = 20,
-
-#if LL_MESH_ENABLED
 		IT_MESH = 22,
-#endif
 		IT_COUNT = 23,
 
 		IT_NONE = -1
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index ac3ed5d63ea904ff40066773884828431a89b4ae..62e488452a32794462aae8ac9ab5ac2f68a373ac 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -5254,7 +5254,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
 			
 		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
 		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
-		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, vert_size);
+		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
 
 
 		if (src.mBinormals)
@@ -5355,9 +5355,9 @@ bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs
 		getNormal().equal3(rhs.getNormal());
 }
 
-bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector4a& a, const LLVector4a& b) const
+bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const
 {
-	return a.less3(b);			
+	return a < b;			
 }
 
 void LLVolumeFace::optimize(F32 angle_cutoff)
@@ -5375,7 +5375,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
 		getVertexData(index, cv);
 		
 		BOOL found = FALSE;
-		VertexMapData::PointMap::iterator point_iter = point_map.find(cv.getPosition());
+		VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32()));
 		if (point_iter != point_map.end())
 		{ //duplicate point might exist
 			for (U32 j = 0; j < point_iter->second.size(); ++j)
@@ -5407,7 +5407,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
 			}
 			else
 			{
-				point_map[d.getPosition()].push_back(d);
+				point_map[LLVector3(d.getPosition().getF32())].push_back(d);
 			}
 		}
 	}
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 078294407969f9bc05e48b7fdfaf7a2aa963b138..4aef3be97370f7d2d0a627e9b59bd9eff7a976a1 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -41,7 +41,7 @@ class LLVolumeParams;
 class LLProfile;
 class LLPath;
 
-#define LL_MESH_ENABLED 0
+#define LL_MESH_ENABLED 1
 
 template <class T> class LLOctreeNode;
 
@@ -873,10 +873,10 @@ class LLVolumeFace
 
 		struct ComparePosition
 		{
-			bool operator()(const LLVector4a& a, const LLVector4a& b) const;
+			bool operator()(const LLVector3& a, const LLVector3& b) const;
 		};
 
-		typedef std::map<LLVector4a, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
+		typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
 	};
 
 	void optimize(F32 angle_cutoff = 2.f);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e774d128836839dca20095d1f53a0c3c3d734230..f0b58b385c56c7ac745d2d0853ae7528dbd17c14 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -16,6 +16,7 @@ include(FindOpenGL)
 include(LLAudio)
 include(LLCharacter)
 include(LLCommon)
+include(LLConvexDecompInter)
 include(LLImage)
 include(LLImageJ2COJ)
 include(LLInventory)
@@ -49,6 +50,7 @@ include_directories(
     ${LLAUDIO_INCLUDE_DIRS}
     ${LLCHARACTER_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
+    ${LLCONVEXDECOMPINTER_INCLUDE_DIRS}
     ${LLIMAGE_INCLUDE_DIRS}
     ${LLINVENTORY_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
@@ -1680,6 +1682,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${CRYPTO_LIBRARIES}
     ${LLLOGIN_LIBRARIES}
     ${GOOGLE_PERFTOOLS_LIBRARIES}
+    ${LLCONVEXDECOMPINTER_LIBRARIES}
     )
 
 build_version(viewer)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 50adf562459b7f74dc668ee369e7ba78567b8756..42fd688f4f25a1ac08d20be160c77f6f5fe0bdff 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4919,7 +4919,7 @@
     <key>Type</key>
     <string>Boolean</string>
     <key>Value</key>
-    <real>0</real>
+    <real>1</real>
   </map>
   <key>MigrateCacheDirectory</key>
     <map>
@@ -5584,6 +5584,66 @@
       <key>Value</key>
       <real>0.0</real>
     </map>
+  <key>ObjectCostHighThreshold</key>
+  <map>
+    <key>Comment</key>
+    <string>Threshold at which object cost is considered high (displayed in red).</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>F32</string>
+    <key>Value</key>
+    <real>50.0</real>
+  </map>
+  <key>ObjectCostLowColor</key>
+  <map>
+    <key>Comment</key>
+    <string>Color for object with a low object cost.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Color4</string>
+    <key>Value</key>
+    <array>
+      <real>0.0</real>
+      <real>0.5</real>
+      <real>1.0</real>
+      <real>0.5</real>
+    </array>
+  </map>
+  <key>ObjectCostMidColor</key>
+  <map>
+    <key>Comment</key>
+    <string>Color for object with a medium object cost.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Color4</string>
+    <key>Value</key>
+    <array>
+      <real>1.0</real>
+      <real>0.75</real>
+      <real>0.0</real>
+      <real>0.65</real>
+    </array>
+  </map>
+  <key>ObjectCostHighColor</key>
+  <map>
+    <key>Comment</key>
+    <string>Color for object a high object cost.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Color4</string>
+    <key>Value</key>
+    <array>
+      <real>1.0</real>
+      <real>0.0</real>
+      <real>0.0</real>
+      <real>0.75</real>
+    </array>
+  </map>
+  
     <key>ParcelMediaAutoPlayEnable</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index 9abaccfde094bc995973d17d761c269bc39d0656..5890fbbc0889721204a73b3887be4b0639c7600d 100644
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -34,6 +34,7 @@
 #define LL_LLASSETUPLOADRESPONDER_H
 
 #include "llhttpclient.h"
+#include "llvolume.h" //for LL_MESH_ENABLED
 
 // Abstract class for supporting asset upload
 // via capabilities
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 46ffc42f040dea5da06b76a4365e8d928b1e477c..b01394534b31cfc157c20f7f671bbd935629d358 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -34,6 +34,7 @@
 #define LL_LLDRAWPOOLAVATAR_H
 
 #include "lldrawpool.h"
+#include "llvolume.h" // for LL_MESH_ENABLED
 
 class LLVOAvatar;
 class LLGLSLShader;
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 9f942c041bdec44a950eaae858147d3a89ad4776..67fa546870852eeeea32f7d55314bf30fc735354 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -421,12 +421,12 @@ void LLFloaterTools::refresh()
 
 	// Refresh object and prim count labels
 	LLLocale locale(LLLocale::USER_LOCALE);
-	std::string obj_count_string;
-	LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount());
-	childSetTextArg("obj_count",  "[COUNT]", obj_count_string);	
-	std::string prim_count_string;
-	LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount(TRUE));
-	childSetTextArg("prim_count", "[COUNT]", prim_count_string);
+	
+	F32 obj_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost();
+	F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedLinksetCost();
+
+	childSetTextArg("obj_count",  "[COUNT]", llformat("%.1f", obj_cost));	
+	childSetTextArg("prim_count", "[COUNT]", llformat("%.1f", link_cost));
 
 	// calculate selection rendering cost
 	if (sShowObjectCost)
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index a7d48806646609ef8939a2389c0bc4b992c440c8..7859c2b30db04ea4eeeb327f56697645ebfc0fbc 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4807,7 +4807,7 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 
 LLUIImagePtr LLMeshBridge::getIcon() const
 {
-	return get_item_icon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
+	return LLInventoryIcon::getIcon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
 }
 
 void LLMeshBridge::openItem()
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3287f310c37edbf01075864ce90ab2383963fdc9..132f7a7fc72f53b043a82f013f413d732f8cc4aa 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -40,6 +40,7 @@
 #include "llinventoryobserver.h"
 #include "llviewercontrol.h"
 #include "llwearable.h"
+#include "llvolume.h"  //for LL_MESH_ENABLED
 
 class LLInventoryPanel;
 class LLInventoryModel;
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 0ce7ffb0776d71e9fed5bb6d59847062f2fc99e3..559c802f51e982fc9fc857d23355862366209174 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -6191,6 +6191,53 @@ S32 LLObjectSelection::getObjectCount(BOOL mesh_adjust)
 	return count;
 }
 
+F32 LLObjectSelection::getSelectedObjectCost()
+{
+	cleanupNodes();
+	F32 cost = 0.f;
+
+	for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* object = node->getObject();
+		
+		if (object)
+		{
+			cost += object->getObjectCost();
+		}
+	}
+
+	return cost;
+}
+
+F32 LLObjectSelection::getSelectedLinksetCost()
+{
+	cleanupNodes();
+	F32 cost = 0.f;
+
+	std::set<LLViewerObject*> me_roots;
+
+	for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* object = node->getObject();
+		
+		if (object)
+		{
+			LLViewerObject* root = static_cast<LLViewerObject*>(object->getRoot());
+			if (root)
+			{
+				if (me_roots.find(root) == me_roots.end())
+				{
+					me_roots.insert(root);
+					cost += root->getLinksetCost();
+				}
+			}
+		}
+	}
+
+	return cost;
+}
 
 //-----------------------------------------------------------------------------
 // getTECount()
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 34f2082b825dd78328ded47218d6f919712a2516..5302cfae683d51f92cd03de91d44d21c3ef09c64 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -292,6 +292,9 @@ class LLObjectSelection : public LLRefCount
 
 	// count members
 	S32 getObjectCount(BOOL mesh_adjust = FALSE);
+	F32 getSelectedObjectCost();
+	F32 getSelectedLinksetCost();
+
 	S32 getTECount();
 	S32 getRootObjectCount();
 
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index bda59f49d1f0f2833d1b4a71083011d916b33f47..dc193dc600291c1ac720c3c78103214bc9d30b41 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -45,6 +45,7 @@
 #include "llviewerregion.h"
 #include "llcamera.h"
 #include "pipeline.h"
+#include "llmeshrepository.h"
 #include "llrender.h"
 #include "lloctree.h"
 #include "llvoavatar.h"
@@ -2331,6 +2332,14 @@ void pushVerts(LLFace* face, U32 mask)
 	}
 }
 
+void pushVerts(LLDrawable* drawable, U32 mask)
+{
+	for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+	{
+		pushVerts(drawable->getFace(i), mask);
+	}
+}
+
 void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
 {
 	if (buffer)
@@ -2756,6 +2765,79 @@ void renderNormals(LLDrawable* drawablep)
 	}
 }
 
+void renderPhysicsShape(LLDrawable* drawable)
+{
+	LLVOVolume* volume = drawable->getVOVolume();
+	if (volume)
+	{
+		F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold");
+		F32 cost = volume->getObjectCost();
+
+		LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor");
+		LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor");
+		LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor");
+
+		F32 normalizedCost = 1.f - exp( -(cost / threshold) );
+
+		LLColor4 color;
+		if ( normalizedCost <= 0.5f )
+		{
+			color = lerp( low, mid, 2.f * normalizedCost );
+		}
+		else
+		{
+			color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) );
+		}
+
+		U32 data_mask = LLVertexBuffer::MAP_VERTEX;
+
+		if (volume->isMesh())
+		{			
+			LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
+			const LLMeshDecomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
+			if (decomp)
+			{
+				gGL.pushMatrix();
+				glMultMatrixf((F32*) volume->getRelativeXform().mMatrix);
+				
+				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+				for (U32 i = 0; i < decomp->mHull.size(); ++i)
+				{		
+					LLVertexBuffer* buff = decomp->mMesh[i];
+
+					buff->setBuffer(data_mask);
+
+					glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+					glColor3fv(color.mV);
+					buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
+					glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+					{
+						LLGLEnable blend(GL_BLEND);
+						gGL.setSceneBlendType(LLRender::BT_ALPHA);
+						LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+						glColor4fv(color.mV);
+						buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts());
+					}
+				}
+
+				gGL.popMatrix();
+
+				return;
+			}
+		}
+
+		//push faces
+		glColor3fv(color.mV);
+		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+		pushVerts(drawable, data_mask);
+		glColor4fv(color.mV);
+		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+		pushVerts(drawable, data_mask);
+	}
+}
+
 void renderTexturePriority(LLDrawable* drawable)
 {
 	for (int face=0; face<drawable->getNumFaces(); ++face)
@@ -3136,6 +3218,11 @@ class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
 				renderNormals(drawable);
 			}
 			
+			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+			{
+				renderPhysicsShape(drawable);
+			}
+
 			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE))
 			{
 				if (drawable->isState(LLDrawable::IN_REBUILD_Q2))
@@ -3342,7 +3429,8 @@ void LLSpatialPartition::renderDebug()
 									  LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
 									  LLPipeline::RENDER_DEBUG_AGENT_TARGET |
 									  LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
-									  LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) 
+									  LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
+									  LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) 
 	{
 		return;
 	}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index d679ccd3d8db137f09f4e904fb9e6d7da3f9f1a5..c4ecba1aa205869679eb62acd6581e12d716cd90 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1037,7 +1037,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
 	hit_obj->sendTEUpdate();
 }
 
-#if LL_MESH_EANBLED
+#if LL_MESH_ENABLED
 void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
 								 LLInventoryItem* item,
 								 LLToolDragAndDrop::ESource source,
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index ceeaa8c82095c0f6c1a890a0ba78bc06887261c2..09da4c29554c7143241c7d610c4fd78c90c4d45c 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -43,6 +43,7 @@
 #include "llpermissions.h"
 #include "llwindow.h"
 #include "llviewerinventory.h"
+#include "llvolume.h" //for LL_MESH_ENABLED
 
 class LLToolDragAndDrop;
 class LLViewerRegion;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b4a10d709eb1ab0d8f5f21e87ddbd717e9e77b38..d7f268eff2cdb01c26e14930b09b8d9450f25dcb 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -873,6 +873,10 @@ U32 info_display_from_string(std::string info_display)
 	{
 		return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA;
 	}
+	else if ("physics shapes" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES;
+	}
 	else if ("occlusion" == info_display)
 	{
 		return LLPipeline::RENDER_DEBUG_OCCLUSION;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1e226ebb65cf3889d5ab48ad0ab50e1ad0970a21..03e524268daf90fdb7ff5c0d30ac51865919a2b3 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -232,6 +232,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
 	mState(0),
 	mMedia(NULL),
 	mClickAction(0),
+	mObjectCost(0.f),
+	mLinksetCost(0.f),
+	mCostStale(true),
 	mAttachmentItemID(LLUUID::null)
 {
 	if (!is_global)
@@ -828,6 +831,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 #ifdef DEBUG_UPDATE_TYPE
 				llinfos << "Full:" << getID() << llendl;
 #endif
+				//clear cost and linkset cost
+				mCostStale = true;
+
 				LLUUID audio_uuid;
 				LLUUID owner_id;	// only valid if audio_uuid or particle system is not null
 				F32    gain;
@@ -1393,6 +1399,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 #ifdef DEBUG_UPDATE_TYPE
 				llinfos << "CompFull:" << getID() << llendl;
 #endif
+				mCostStale = true;
+
 				dp->unpackU32(crc, "CRC");
 				mTotalCRC = crc;
 				dp->unpackU8(material, "Material");
@@ -2863,6 +2871,41 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
 	}
 }
 
+void LLViewerObject::setObjectCost(F32 cost)
+{
+	mObjectCost = cost;
+	mCostStale = false;
+}
+
+void LLViewerObject::setLinksetCost(F32 cost)
+{
+	mLinksetCost = cost;
+	mCostStale = false;
+}
+
+
+F32 LLViewerObject::getObjectCost()
+{
+	if (mCostStale)
+	{
+		gObjectList.updateObjectCost(this);
+	}
+	
+	return mObjectCost;
+}
+
+F32 LLViewerObject::getLinksetCost()
+{
+	if (mCostStale)
+	{
+		gObjectList.updateObjectCost(this);
+	}
+
+	return mLinksetCost;
+}
+
+
+
 void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
 {
 	LLVector4a center;
@@ -4983,7 +5026,7 @@ void LLViewerObject::updateFlags()
 
 	if (getPhysicsShapeType() != 0)
 	{
-		llwarns << "sent non default physics rep" << llendl;
+		llwarns << "sent non default physics rep " << (S32) getPhysicsShapeType() << llendl;
 	}
 }
 
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 6ebd1cbe212ade436032b69456c0be9c976f2035..092d8fdc82d689a2c8ff57566a4ede79aa168d01 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -334,6 +334,12 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate
 	
 	virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE);
 
+	void setObjectCost(F32 cost);
+	F32 getObjectCost();
+	void setLinksetCost(F32 cost);
+	F32 getLinksetCost();
+	
+
 	void sendShapeUpdate();
 
 	U8 getState()							{ return mState; }
@@ -668,6 +674,9 @@ class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate
 	U8				mState;	// legacy
 	LLViewerObjectMedia* mMedia;	// NULL if no media associated
 	U8 mClickAction;
+	F32 mObjectCost; //resource cost of this object or -1 if unknown
+	F32 mLinksetCost;
+	bool mCostStale;
 
 	static			U32			sNumZombieObjects;			// Objects which are dead, but not deleted
 
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 7ba28fef32a07c407e98fbb23da3236b6adf28f6..9d41e2a530d4d7df86976aec5552104428219e18 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -60,6 +60,7 @@
 #include "llviewercamera.h"
 #include "llselectmgr.h"
 #include "llresmgr.h"
+#include "llsdutil.h"
 #include "llviewerregion.h"
 #include "llviewerstats.h"
 #include "llvoavatarself.h"
@@ -656,6 +657,21 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 	LLVOAvatar::cullAvatarsByPixelArea();
 }
 
+class LLObjectCostResponder : public LLCurl::Responder
+{
+public:
+	void result(const LLSD& content)
+	{
+		for (LLSD::map_const_iterator iter = content.beginMap(); iter != content.endMap(); ++iter)
+		{
+			LLUUID object_id = LLUUID(iter->first);
+			F32 link_cost = iter->second["LinksetResourceCost"].asReal();
+			F32 prim_cost = iter->second["PrimResourceCost"].asReal();
+
+			gObjectList.updateObjectCost(object_id, prim_cost, link_cost);
+		}
+	}
+};
 
 void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
 {
@@ -753,6 +769,43 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
 		}
 	}
 
+	//issue http request for stale object physics costs
+	if (!mStaleObjectCost.empty())
+	{
+		LLViewerRegion* regionp = gAgent.getRegion();
+
+		if (regionp)
+		{
+			std::string url = regionp->getCapability("GetObjectCost");
+
+			if (!url.empty())
+			{
+				LLSD id_list;
+				U32 idx = 0;
+				for (std::set<LLUUID>::iterator iter = mStaleObjectCost.begin(); iter != mStaleObjectCost.end(); ++iter)
+				{
+					if (mPendingObjectCost.find(*iter) == mPendingObjectCost.end())
+					{
+						mPendingObjectCost.insert(*iter);
+						id_list[idx++] = *iter;
+					}
+				}
+				mPendingObjectCost = mStaleObjectCost;
+				mStaleObjectCost.clear();
+
+				if (id_list.size() > 0)
+				{
+					LLHTTPClient::post(url, id_list, new LLObjectCostResponder());
+				}
+			}
+			else
+			{
+				mStaleObjectCost.clear();
+				mPendingObjectCost.clear();
+			}
+		}
+	}
+
 	mNumSizeCulled = 0;
 	mNumVisCulled = 0;
 
@@ -1041,7 +1094,22 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp)
 	}
 }
 
+void LLViewerObjectList::updateObjectCost(LLViewerObject* object)
+{
+	mStaleObjectCost.insert(object->getID());
+}
+
+void LLViewerObjectList::updateObjectCost(LLUUID object_id, F32 prim_cost, F32 link_cost)
+{
+	mPendingObjectCost.erase(object_id);
 
+	LLViewerObject* object = findObject(object_id);
+	if (object)
+	{
+		object->setObjectCost(prim_cost);
+		object->setLinksetCost(link_cost);
+	}
+}
 
 void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
 {
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 706966deaefc2eeff06fa91a730644ee7ecbfe27..4064a68eb21004fb17b5b7a516a9f3c5bb54deb2 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -91,6 +91,9 @@ class LLViewerObjectList
 	void updateApparentAngles(LLAgent &agent);
 	void update(LLAgent &agent, LLWorld &world);
 
+	void updateObjectCost(LLViewerObject* object);
+	void updateObjectCost(LLUUID object_id, F32 prim_cost, F32 link_cost);
+
 	void shiftObjects(const LLVector3 &offset);
 
 	void renderObjectsForMap(LLNetMap &netmap);
@@ -192,6 +195,10 @@ class LLViewerObjectList
 
 	std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
 
+	//set of objects that need to update their cost
+	std::set<LLUUID> mStaleObjectCost;
+	std::set<LLUUID> mPendingObjectCost;
+
 	std::vector<LLDebugBeacon> mDebugBeacons;
 
 	S32 mCurLazyUpdateIndex;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 38e54342eadbf137755db060f578dcd5eaff52bb..bda629795d7a15473b0ba166080e3b9cfccc280a 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1594,7 +1594,7 @@ void LLVOVolume::updateFaceSize(S32 idx)
 	LLFace* facep = mDrawable->getFace(idx);
 	if (idx >= getVolume()->getNumVolumeFaces())
 	{
-		facep->setSize(0,0);
+		facep->setSize(0,0, true);
 	}
 	else
 	{
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 95f951b393e7d1fe21e002052eec4325f7d76200..fb68c1d668e650a8a15286924d1903ef17e2508f 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -444,7 +444,8 @@ class LLPipeline
 		RENDER_DEBUG_AVATAR_VOLUME      = 0x0100000,
 		RENDER_DEBUG_BUILD_QUEUE		= 0x0200000,
 		RENDER_DEBUG_AGENT_TARGET       = 0x0400000,
-		RENDER_DEBUG_NORMALS	        = 0x0800000,
+		RENDER_DEBUG_PHYSICS_SHAPES     = 0x0800000,
+		RENDER_DEBUG_NORMALS	        = 0x1000000,
 	};
 
 public:
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 294a68255d845e866c0bcb877eabb19b53c730ce..860cff6664f7ecd4795a15c852100161aa218aba 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -160,10 +160,12 @@ xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
 zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
 google-perftools Copyright (c) 2005, Google Inc.
 
+Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details.
+
 All rights reserved.  See licenses.txt for details.
 
 Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-      </text_editor>
+        </text_editor>
       </panel>
     </tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index d512293305f8b058b89bd17ea96fa828c606b7d2..0aa46608640b4b2aa38d4ec9000281a170d6dc43 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2022,6 +2022,16 @@
            function="Advanced.ToggleInfoDisplay"
            parameter="shadow frusta" />
         </menu_item_check>
+        <menu_item_check
+         label="Physics Shapes"
+         name="Physics Shapes">
+          <menu_item_check.on_check
+           function="Advanced.CheckInfoDisplay"
+           parameter="physics shapes" />
+          <menu_item_check.on_click
+           function="Advanced.ToggleInfoDisplay"
+           parameter="physics shapes" />
+        </menu_item_check>
         <menu_item_check
          label="Occlusion"
          name="Occlusion">