diff --git a/doc/contributions.txt b/doc/contributions.txt
index 82f0b19be1fb299602d2e0bf5a6711fd618887db..e355dcababca4dffec6a73a41b72824035da3892 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -412,6 +412,7 @@ Jonathan Yap
 	VWR-17801
 	VWR-24347
 	STORM-975
+	STORM-990
 	STORM-1019
 	STORM-844
 	STORM-643
@@ -796,7 +797,9 @@ Thraxis Epsilon
 tiamat bingyi
 	CT-246
 Tofu Buzzard
+	CTS-411
 	STORM-546
+	VWR-24509
 TraductoresAnonimos Alter
 	CT-324
 Tue Torok
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 25b29ac1a825a86a1e40e681075473c4564d1a67..eea7c977fb9595222965fece31f14d586cd87829 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -29,6 +29,7 @@
 
 #include <cmath>
 #include <cstdlib>
+#include <vector>
 #include "lldefs.h"
 //#include "llstl.h" // *TODO: Remove when LLString is gone
 //#include "llstring.h" // *TODO: Remove when LLString is gone
@@ -497,6 +498,44 @@ inline F32 llgaussian(F32 x, F32 o)
 	return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o));
 }
 
+//helper function for removing outliers
+template <class VEC_TYPE>
+inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
+{
+	if (data.size() < 100)
+	{ //not enough samples
+		return;
+	}
+
+	VEC_TYPE Q1 = data[data.size()/4];
+	VEC_TYPE Q3 = data[data.size()-data.size()/4-1];
+
+	VEC_TYPE min = (VEC_TYPE) ((F32) Q1-k * (F32) (Q3-Q1));
+	VEC_TYPE max = (VEC_TYPE) ((F32) Q3+k * (F32) (Q3-Q1));
+
+	U32 i = 0;
+	while (i < data.size() && data[i] < min)
+	{
+		i++;
+	}
+
+	S32 j = data.size()-1;
+	while (j > 0 && data[j] > max)
+	{
+		j--;
+	}
+
+	if (j < data.size()-1)
+	{
+		data.erase(data.begin()+j, data.end());
+	}
+
+	if (i > 0)
+	{
+		data.erase(data.begin(), data.begin()+i);
+	}
+}
+
 // Include simd math header
 #include "llsimdmath.h"
 
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 03b893de2991c549e598d7c0118ec1a89eb2c34e..5af1122451fe1da818510d5c69c25d8fe145b86b 100755
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -2067,7 +2067,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 			std::set<U64> valid;
 
 			//must have at least 4 points
-			llassert(count > 3);
+			//llassert(count > 3);
 
 			for (U32 j = 0; j < count; ++j)
 			{
@@ -2085,7 +2085,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
 			}
 
 			//each hull must contain at least 4 unique points
-			llassert(valid.size() > 3);
+			//llassert(valid.size() > 3);
 		}
 	}
 
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index d5f0b81830853da7d314e73a78fab55b6c7a8f46..b508705759ec08fff37f1b125c367bd1698c3d64 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1858,12 +1858,17 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
 	}
 }
 
-LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection)
+LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply)
 {
-	mModelview = modelview;
-	mProjection = projection;
+	mApply = apply;
 
-	setPlane(p[0], p[1], p[2], p[3]);
+	if (mApply)
+	{
+		mModelview = modelview;
+		mProjection = projection;
+
+		setPlane(p[0], p[1], p[2], p[3]);
+	}
 }
 
 void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
@@ -1894,9 +1899,12 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
 
 LLGLUserClipPlane::~LLGLUserClipPlane()
 {
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
+	if (mApply)
+	{
+		glMatrixMode(GL_PROJECTION);
+		glPopMatrix();
+		glMatrixMode(GL_MODELVIEW);
+	}
 }
 
 LLGLNamePool::LLGLNamePool()
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 0d7ba15b1268eae4c140071710db9542fadae0cf..43992d51cb0a5de1fc40fbac5368ae7bac4c1e04 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -301,12 +301,14 @@ class LLGLUserClipPlane
 {
 public:
 	
-	LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection);
+	LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true);
 	~LLGLUserClipPlane();
 
 	void setPlane(F32 a, F32 b, F32 c, F32 d);
 
 private:
+	bool mApply;
+
 	glh::matrix4f mProjection;
 	glh::matrix4f mModelview;
 };
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 6c0895512ea1e6347c9c9cebc5cde3f8ba9eb4ed..a9f22193f87a4601aa25b94da85ad4fdb7ded85b 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -56,13 +56,17 @@ protected:
 	virtual GLuint allocateName()
 	{
 		GLuint name;
+		stop_glerror();
 		glGenBuffersARB(1, &name);
+		stop_glerror();
 		return name;
 	}
 
 	virtual void releaseName(GLuint name)
 	{
+		stop_glerror();
 		glDeleteBuffersARB(1, &name);
+		stop_glerror();
 	}
 };
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 24bd3299f1e6dd1b6caa548513e2200ece33ec94..3740b1a7426eab1cfe3420b0b47dae99fdd7eeea 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -410,6 +410,7 @@ set(viewer_SOURCE_FILES
     llremoteparcelrequest.cpp
     llsavedsettingsglue.cpp
     llsaveoutfitcombobtn.cpp
+    llsceneview.cpp
     llscreenchannel.cpp
     llscriptfloater.cpp
     llscrollingpanelparam.cpp
@@ -953,6 +954,7 @@ set(viewer_HEADER_FILES
     llrootview.h
     llsavedsettingsglue.h
     llsaveoutfitcombobtn.h
+    llsceneview.h
     llscreenchannel.h
     llscriptfloater.h
     llscrollingpanelparam.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 73f63458a3156054c716820c7ec9c66a14e80e2c..f41f4b73822fd85d88e349bff1c386ae6bd9c066 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7329,7 +7329,7 @@
     <string>Vector3</string>
     <key>Value</key>
     <array>
-      <real>0.40</real>
+      <real>0.80</real>
       <real>1.00</real>
       <real>0.00</real>
     </array>
@@ -7750,6 +7750,18 @@
     <key>Value</key>
     <real>0</real>
   </map>
+
+  <key>RenderDepthOfField</key>
+  <map>
+    <key>Comment</key>
+    <string>Whether to use depth of field effect when lighting and shadows are enabled</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
   
   <key>RenderSpotLightsInNondeferred</key>
   <map>
@@ -8086,7 +8098,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>0.1</real>
+    <real>0</real>
   </map>
 
   <key>RenderGIAmbiance</key>
@@ -8306,9 +8318,9 @@
       <string>Vector3</string>
       <key>Value</key>
       <array>
-        <real>0.299</real>
-        <real>0.587</real>
-        <real>0.114</real>
+        <real>1</real>
+        <real>0</real>
+        <real>0</real>
       </array>
     </map>
     <key>RenderGlowMaxExtractAlpha</key>
@@ -8320,7 +8332,7 @@
       <key>Type</key>
       <string>F32</string>
       <key>Value</key>
-      <real>0.065</real>
+      <real>0.25</real>
     </map>
     <key>RenderGlowMinLuminance</key>
     <map>
@@ -8331,7 +8343,7 @@
       <key>Type</key>
       <string>F32</string>
       <key>Value</key>
-      <real>2.5</real>
+      <real>9999</real>
     </map>
     <key>RenderGlowResolutionPow</key>
     <map>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index b08c5dd295ab3630ecdd03a3b2a1a6d77f0264fb..28a38d43901b4a67c36744e5b9b056ac36104fde 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -10,7 +10,6 @@
 #extension GL_ARB_texture_rectangle : enable
 
 uniform sampler2D diffuseMap;
-uniform sampler2D noiseMap;
 uniform sampler2DRect depthMap;
 
 uniform mat4 shadow_matrix[6];
@@ -45,8 +44,6 @@ void main()
 	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
 	frag *= screen_res;
 	
-	vec3 samp_pos = getPosition(frag).xyz;
-	
 	vec4 pos = vec4(vary_position, 1.0);
 	
 	vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index ea2df4b51a19ad0573afb84a78bad5c7fb0d6318..d9f021b114f4919327c70f62c967750f98887d22 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -39,44 +39,49 @@ vec4 getPosition(vec2 pos_screen)
 
 void main() 
 {
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+        vec2 tc = vary_fragcoord.xy;
+	vec3 norm = texture2DRect(normalMap, tc).xyz;
 	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
-	vec3 pos = getPosition(vary_fragcoord.xy).xyz;
-	vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
+	vec3 pos = getPosition(tc).xyz;
+	vec4 ccol = texture2DRect(lightMap, tc).rgba;
 	
 	vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
-	
 	dlt /= max(-pos.z*dist_factor, 1.0);
 	
 	vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
 	vec4 col = defined_weight.xyxx * ccol;
-	
+
+	// relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
+	float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
+
+	// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
+	tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 );
+
 	for (int i = 1; i < 4; i++)
 	{
-		vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
-	        vec3 samppos = getPosition(tc).xyz; 
+		vec2 samptc = tc + kern[i].z*dlt;
+	        vec3 samppos = getPosition(samptc).xyz; 
 		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		if (d*d <= 0.003)
+		if (d*d <= pointplanedist_tolerance_pow2)
 		{
-			col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
 			defined_weight += kern[i].xy;
 		}
 	}
 	for (int i = 1; i < 4; i++)
 	{
-		vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
-	        vec3 samppos = getPosition(tc).xyz; 
+		vec2 samptc = tc - kern[i].z*dlt;
+	        vec3 samppos = getPosition(samptc).xyz; 
 		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		if (d*d <= 0.003)
+		if (d*d <= pointplanedist_tolerance_pow2)
 		{
-			col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
 			defined_weight += kern[i].xy;
 		}
 	}
 
-
-
 	col /= defined_weight.xyxx;
+	col.y *= col.y;
 	
 	gl_FragColor = col;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 7a6b40006b1382c2058cb3d99292625cb2887562..f377685045acc8d27401bac7a9c91ecb2e77423c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -36,86 +36,97 @@ float getDepth(vec2 pos_screen)
 	return p.z/p.w;
 }
 
-void dofSample(inout vec4 diff, inout float w, float fd, float x, float y)
+float calc_cof(float depth)
+{
+	float sc = abs(depth-focal_distance)/-depth*blur_constant;
+		
+	sc /= magnification;
+	
+	// tan_pixel_angle = pixel_length/-depth;
+	float pixel_length =  tan_pixel_angle*-focal_distance;
+	
+	sc = sc/pixel_length;
+	sc *= 1.414;
+	
+	return sc;
+}
+
+void dofSampleNear(inout vec4 diff, inout float w, float cur_sc, vec2 tc)
 {
-	vec2 tc = vary_fragcoord.xy+vec2(x,y);
 	float d = getDepth(tc);
 	
+	float sc = calc_cof(d);
+	
 	float wg = 1.0;
-	//if (d < fd)
-	//{
-	//	diff += texture2DRect(diffuseRect, tc);
-	//	w = 1.0;
-	//}
-	if (d > fd)
-	{
-		wg = max(d/fd, 0.1);
-	}
+		
+	vec4 s = texture2DRect(diffuseRect, tc);
+	// de-weight dull areas to make highlights 'pop'
+	wg *= s.r+s.g+s.b;
+	
+	diff += wg*s;
 	
-	diff += texture2DRect(diffuseRect, tc+vec2(0.5,0.5))*wg*0.25;
-	diff += texture2DRect(diffuseRect, tc+vec2(-0.5,0.5))*wg*0.25;
-	diff += texture2DRect(diffuseRect, tc+vec2(0.5,-0.5))*wg*0.25;
-	diff += texture2DRect(diffuseRect, tc+vec2(-0.5,-0.5))*wg*0.25;
 	w += wg;
 }
 
-void dofSampleNear(inout vec4 diff, inout float w, float x, float y)
+void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, vec2 tc)
 {
-	vec2 tc = vary_fragcoord.xy+vec2(x,y);
+	float d = getDepth(tc);
+	
+	float sc = calc_cof(d);
+	
+	if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius
+	   || d < cur_depth) //sampled pixel is further away than current pixel
+	{
+		float wg = 1.0;
 		
-	diff += texture2DRect(diffuseRect, tc);
-	w += 1.0;
+		vec4 s = texture2DRect(diffuseRect, tc);
+		// de-weight dull areas to make highlights 'pop'
+		wg *= s.r+s.g+s.b;
+	
+		diff += wg*s;
+		
+		w += wg;
+	}
 }
 
+
 void main() 
 {
 	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
 	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
-	
-	
+		
 	vec2 tc = vary_fragcoord.xy;
 	
-	float sc = 0.75;
+	float depth = getDepth(tc);
 	
-	float depth;
-	depth = getDepth(tc);
-		
 	vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
 	
-	{ //pixel is behind far focal plane
+	{ 
 		float w = 1.0;
 		
-		sc = (abs(depth-focal_distance)/-depth)*blur_constant;
-		
-		sc /= magnification;
-		
-		// tan_pixel_angle = pixel_length/-depth;
-		float pixel_length =  tan_pixel_angle*-focal_distance;
-		
-		sc = sc/pixel_length;
-		
-		//diff.r = sc;
-		
-		sc = min(abs(sc), 8.0);
-		
-		//sc = 4.0;
+		float sc = calc_cof(depth);
+		sc = min(abs(sc), 10.0);
 		
 		float fd = depth*0.5f;
 		
-		while (sc > 0.5)
+		float PI = 3.14159265358979323846264;
+
+		// sample quite uniformly spaced points within a circle, for a circular 'bokeh'		
+		//if (depth < focal_distance)
 		{
-			dofSample(diff,w, fd, sc,sc);
-			dofSample(diff,w, fd, -sc,sc);
-			dofSample(diff,w, fd, sc,-sc);
-			dofSample(diff,w, fd, -sc,-sc);
-			
-			sc -= 0.5;
-			float sc2 = sc*1.414;
-			dofSample(diff,w, fd, 0,sc2);
-			dofSample(diff,w, fd, 0,-sc2);
-			dofSample(diff,w, fd, -sc2,0);
-			dofSample(diff,w, fd, sc2,0);
-			sc -= 0.5;
+			while (sc > 0.5)
+			{
+				int its = int(max(1.0,(sc*3.7)));
+				for (int i=0; i<its; ++i)
+				{
+					float ang = sc+i*2*PI/its; // sc is added for rotary perturbance
+					float samp_x = sc*sin(ang);
+					float samp_y = sc*cos(ang);
+					// you could test sample coords against an interesting non-circular aperture shape here, if desired.
+					dofSample(diff, w, sc, depth, vary_fragcoord.xy + vec2(samp_x,samp_y));
+				}
+				sc -= 1.0;
+			}
 		}
 		
 		diff /= w;
@@ -123,5 +134,4 @@ void main()
 		
 	vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
 	gl_FragColor = diff + bloom;
-	
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 1e0693d19f1143856d72e3093716a8620440bf4f..25ff958107f1368af1a248d798987ca33655d26e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -53,57 +53,49 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
 {
 	float ret = 1.0;
 	
-	float dist = dot(pos.xyz,pos.xyz);
-	
-	if (dist < 64.0*64.0)
-	{
-		vec2 kern[8];
-		// exponentially (^2) distant occlusion samples spread around origin
-		kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
-		kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
-		kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
-		kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
-		kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
-		kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
-		kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
-		kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+	vec2 kern[8];
+	// exponentially (^2) distant occlusion samples spread around origin
+	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
 
-		vec2 pos_screen = vary_fragcoord.xy;
-		vec3 pos_world = pos.xyz;
-		vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+	vec2 pos_screen = vary_fragcoord.xy;
+	vec3 pos_world = pos.xyz;
+	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
 		
-		float angle_hidden = 0.0;
-		int points = 0;
+	float angle_hidden = 0.0;
+	int points = 0;
 		
-		float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
 		
-		// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
-		for (int i = 0; i < 8; i++)
-		{
-			vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
-			vec3 samppos_world = getPosition(samppos_screen).xyz; 
+	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?)
+	for (int i = 0; i < 8; i++)
+	{
+		vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
+		vec3 samppos_world = getPosition(samppos_screen).xyz; 
 			
-			vec3 diff = pos_world - samppos_world;
-			float dist2 = dot(diff, diff);
+		vec3 diff = pos_world - samppos_world;
+		float dist2 = dot(diff, diff);
 			
-			// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
-			// --> solid angle shrinking by the square of distance
-			//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
-			//(k should vary inversely with # of samples, but this is taken care of later)
+		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+		// --> solid angle shrinking by the square of distance
+		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+		//(k should vary inversely with # of samples, but this is taken care of later)
 			
-			//if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0)  // -0.05*norm to shift sample point back slightly for flat surfaces
-			//	angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional.  max of 1.0 (= ssao_factor_inv * ssao_factor)
-			angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
 			
-			// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
-			points = points + int(diff.z > -1.0);
-		}
+		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
+		points = points + int(diff.z > -1.0);
+	}
 		
-		angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
 		
-		ret = (1.0 - (float(points != 0) * angle_hidden));
-		ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
-	}
+	ret = (1.0 - (float(points != 0) * angle_hidden));
 	
 	return min(ret, 1.0);
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index 32aab152a32251f2cbc77aedff865f97d9a3203f..1dd29bfc70e7374fbef40c86f5186e9694525b29 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -14,7 +14,6 @@ uniform sampler2DRectShadow shadowMap0;
 uniform sampler2DRectShadow shadowMap1;
 uniform sampler2DRectShadow shadowMap2;
 uniform sampler2DRectShadow shadowMap3;
-uniform sampler2D noiseMap;
 uniform sampler2DRect depthMap;
 
 uniform mat4 shadow_matrix[6];
@@ -70,8 +69,6 @@ void main()
 	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
 	frag *= screen_res;
 	
-	vec3 samp_pos = getPosition(frag).xyz;
-	
 	float shadow = 1.0;
 	vec4 pos = vec4(vary_position, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
deleted file mode 100644
index ea2df4b51a19ad0573afb84a78bad5c7fb0d6318..0000000000000000000000000000000000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
+++ /dev/null
@@ -1,83 +0,0 @@
-/** 
- * @file blurLightF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
- 
-#version 120
-
-#extension GL_ARB_texture_rectangle : enable
-
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
-
-uniform float dist_factor;
-uniform float blur_size;
-uniform vec2 delta;
-uniform vec3 kern[4];
-uniform float kern_scale;
-
-varying vec2 vary_fragcoord;
-
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-void main() 
-{
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
-	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
-	vec3 pos = getPosition(vary_fragcoord.xy).xyz;
-	vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
-	
-	vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
-	
-	dlt /= max(-pos.z*dist_factor, 1.0);
-	
-	vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
-	vec4 col = defined_weight.xyxx * ccol;
-	
-	for (int i = 1; i < 4; i++)
-	{
-		vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
-	        vec3 samppos = getPosition(tc).xyz; 
-		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		if (d*d <= 0.003)
-		{
-			col += texture2DRect(lightMap, tc)*kern[i].xyxx;
-			defined_weight += kern[i].xy;
-		}
-	}
-	for (int i = 1; i < 4; i++)
-	{
-		vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
-	        vec3 samppos = getPosition(tc).xyz; 
-		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		if (d*d <= 0.003)
-		{
-			col += texture2DRect(lightMap, tc)*kern[i].xyxx;
-			defined_weight += kern[i].xy;
-		}
-	}
-
-
-
-	col /= defined_weight.xyxx;
-	
-	gl_FragColor = col;
-}
-
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
deleted file mode 100644
index c2d05c601a8cf9b760c5c0d4bdbc302619000055..0000000000000000000000000000000000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
+++ /dev/null
@@ -1,19 +0,0 @@
-/** 
- * @file blurLightF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
- 
-#version 120
-
-varying vec2 vary_fragcoord;
-uniform vec2 screen_res;
-
-void main()
-{
-	//transform vertex
-	gl_Position = ftransform(); 
-	vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
-	vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index cc921f23d79f9ce934b29532c6652df503562a38..08b16d787fdf70b6a8c40e9427ae5fe598c66f66 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -62,58 +62,50 @@ vec4 getPosition(vec2 pos_screen)
 float calcAmbientOcclusion(vec4 pos, vec3 norm)
 {
 	float ret = 1.0;
-	
-	float dist = dot(pos.xyz,pos.xyz);
-	
-	if (dist < 64.0*64.0)
-	{
-		vec2 kern[8];
-		// exponentially (^2) distant occlusion samples spread around origin
-		kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
-		kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
-		kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
-		kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
-		kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
-		kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
-		kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
-		kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
 
-		vec2 pos_screen = vary_fragcoord.xy;
-		vec3 pos_world = pos.xyz;
-		vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+	vec2 kern[8];
+	// exponentially (^2) distant occlusion samples spread around origin
+	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+	vec2 pos_screen = vary_fragcoord.xy;
+	vec3 pos_world = pos.xyz;
+	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
 		
-		float angle_hidden = 0.0;
-		int points = 0;
+	float angle_hidden = 0.0;
+	int points = 0;
 		
-		float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
 		
-		// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
-		for (int i = 0; i < 8; i++)
-		{
-			vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
-			vec3 samppos_world = getPosition(samppos_screen).xyz; 
+	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+	for (int i = 0; i < 8; i++)
+	{
+		vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
+		vec3 samppos_world = getPosition(samppos_screen).xyz; 
 			
-			vec3 diff = pos_world - samppos_world;
-			float dist2 = dot(diff, diff);
+		vec3 diff = pos_world - samppos_world;
+		float dist2 = dot(diff, diff);
 			
-			// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
-			// --> solid angle shrinking by the square of distance
-			//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
-			//(k should vary inversely with # of samples, but this is taken care of later)
+		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+		// --> solid angle shrinking by the square of distance
+		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+		//(k should vary inversely with # of samples, but this is taken care of later)
 			
-			//if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0)  // -0.05*norm to shift sample point back slightly for flat surfaces
-			//	angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional.  max of 1.0 (= ssao_factor_inv * ssao_factor)
-			angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
 			
-			// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
-			points = points + int(diff.z > -1.0);
-		}
+		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
+		points = points + int(diff.z > -1.0);
+	}
 		
-		angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
 		
-		ret = (1.0 - (float(points != 0) * angle_hidden));
-		ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
-	}
+	ret = (1.0 - (float(points != 0) * angle_hidden));
 	
 	return min(ret, 1.0);
 }
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index 0876c3fd99632712001a80df247d6c9240374612..b6d67899f8caab23f7a69923558bbbce6d1de24c 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -39,7 +39,9 @@
 #include "llviewerwindow.h"
 #include "llappviewer.h"
 #include "llmemoryview.h"
+#include "llsceneview.h"
 #include "llviewertexture.h"
+
 //
 // Globals
 //
@@ -83,6 +85,13 @@ void LLDebugView::init()
 	addChild(mFastTimerView);
 	mFastTimerView->setRect(rect);
 
+	gSceneView = new LLSceneView(r);
+	gSceneView->setFollowsTop();
+	gSceneView->setFollowsLeft();
+	gSceneView->setVisible(FALSE);
+	addChild(gSceneView);
+	gSceneView->setRect(rect);
+	
 	r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f), 
 									 (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
 	LLMemoryView::Params mp;
@@ -103,6 +112,9 @@ void LLDebugView::init()
 	addChild(gTextureView);
 	//gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE);
 
+	
+
+
 	if(gAuditTexture)
 	{
 		r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100);
@@ -133,6 +145,7 @@ LLDebugView::~LLDebugView()
 	// These have already been deleted.  Fix the globals appropriately.
 	gDebugView = NULL;
 	gTextureView = NULL;
+	gSceneView = NULL;
 	gTextureSizeView = NULL;
 	gTextureCategoryView = NULL;
 }
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 6e78ea6bbea2f414784bc8ff12a59881d323858e..35712163ebd78ebf20f129671d046c9a6d1b7edd 100755
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -1040,43 +1040,6 @@ void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch
 	result->save(out_file);
 }
 
-template <class VEC_TYPE>
-void removeOutliers(std::vector<VEC_TYPE>& data, F32 k)
-{
-	if (data.size() < 100)
-	{ //not enough samples
-		return;
-	}
-
-	VEC_TYPE Q1 = data[data.size()/4];
-	VEC_TYPE Q3 = data[data.size()-data.size()/4-1];
-
-	VEC_TYPE min = Q1-k*(Q3-Q1);
-	VEC_TYPE max = Q3+k*(Q3-Q1);
-
-	U32 i = 0;
-	while (i < data.size() && data[i] < min)
-	{
-		i++;
-	}
-
-	S32 j = data.size()-1;
-	while (j > 0 && data[j] > max)
-	{
-		j--;
-	}
-
-	if (j < data.size()-1)
-	{
-		data.erase(data.begin()+j, data.end());
-	}
-
-	if (i > 0)
-	{
-		data.erase(data.begin(), data.begin()+i);
-	}
-}
-
 //static
 void LLFastTimerView::exportCharts(const std::string& base, const std::string& target)
 {
@@ -1206,22 +1169,22 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t
 		const U32 OUTLIER_CUTOFF = 512;
 		if (base_times.size() > OUTLIER_CUTOFF)
 		{ 
-			removeOutliers(base_times, 1.f);
+			ll_remove_outliers(base_times, 1.f);
 		}
 
 		if (base_execution.size() > OUTLIER_CUTOFF)
 		{ 
-			removeOutliers(base_execution, 1.f);
+			ll_remove_outliers(base_execution, 1.f);
 		}
 
 		if (cur_times.size() > OUTLIER_CUTOFF)
 		{ 
-			removeOutliers(cur_times, 1.f);
+			ll_remove_outliers(cur_times, 1.f);
 		}
 
 		if (cur_execution.size() > OUTLIER_CUTOFF)
 		{ 
-			removeOutliers(cur_execution, 1.f);
+			ll_remove_outliers(cur_execution, 1.f);
 		}
 
 
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index a808cc47a2b90ed77305191a3fe6ebdef54047a5..cdd2bcf8e3a1192b1fbf6deb65c47459ede152e1 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -340,7 +340,7 @@ BOOL LLFloaterModelPreview::postBuild()
 
 	mPreviewRect = preview_panel->getRect();
 
-	mModelPreview = new LLModelPreview(512, 512, this);
+	mModelPreview = new LLModelPreview(512, 512, this );
 	mModelPreview->setPreviewTarget(16.f);
 	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
 
@@ -383,7 +383,7 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
 	sInstance = NULL;
 	
 	if ( mModelPreview && mModelPreview->getResetJointFlag() )
-	{
+	{		
 		gAgentAvatarp->resetJointPositions();
 	}
 
@@ -994,8 +994,11 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
 //-----------------------------------------------------------------------------
 // LLModelLoader
 //-----------------------------------------------------------------------------
-LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview)
-: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE)
+LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, 
+							  std::deque<std::string>& jointsFromNodes )
+: mJointList( jointMap )
+, mJointsFromNode( jointsFromNodes )
+, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE)
 {
 	mJointMap["mPelvis"] = "mPelvis";
 	mJointMap["mTorso"] = "mTorso";
@@ -1073,27 +1076,6 @@ LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* prev
 	mJointMap["lShin"] = "mKneeLeft";
 	mJointMap["lFoot"] = "mFootLeft";
 
-	//move into joint mapper class
-	mMasterJointList.push_front("mPelvis");
-	mMasterJointList.push_front("mTorso");
-	mMasterJointList.push_front("mChest");
-	mMasterJointList.push_front("mNeck");
-	mMasterJointList.push_front("mHead");
-	mMasterJointList.push_front("mCollarLeft");
-	mMasterJointList.push_front("mShoulderLeft");
-	mMasterJointList.push_front("mElbowLeft");
-	mMasterJointList.push_front("mWristLeft");
-	mMasterJointList.push_front("mCollarRight");
-	mMasterJointList.push_front("mShoulderRight");
-	mMasterJointList.push_front("mElbowRight");
-	mMasterJointList.push_front("mWristRight");
-	mMasterJointList.push_front("mHipRight");
-	mMasterJointList.push_front("mKneeRight");
-	mMasterJointList.push_front("mFootRight");
-	mMasterJointList.push_front("mHipLeft");
-	mMasterJointList.push_front("mKneeLeft");
-	mMasterJointList.push_front("mFootLeft");
-
 	if (mPreview)
 	{
 		//only try to load from slm if viewer is configured to do so and this is the 
@@ -1356,12 +1338,8 @@ bool LLModelLoader::doLoadModel()
 							skin_info.mBindShapeMatrix = trans;
 							
 						}
-						
-						
-						//The joint transfom map that we'll populate below
-						std::map<std::string,LLMatrix4> jointTransforms;
-						jointTransforms.clear();
-						
+										
+											
 						//Some collada setup for accessing the skeleton
 						daeElement* pElement = 0;
 						dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
@@ -1410,7 +1388,7 @@ bool LLModelLoader::doLoadModel()
 									domNode* pNode = daeSafeCast<domNode>(children[i]);
 									if ( isNodeAJoint( pNode ) )
 									{
-										processJointNode( pNode, jointTransforms );
+										processJointNode( pNode, mJointList );
 									}
 								}
 							}
@@ -1468,7 +1446,7 @@ bool LLModelLoader::doLoadModel()
 										}
 										
 										//Store the joint transform w/respect to it's name.
-										jointTransforms[(*jointIt).second.c_str()] = workingTransform;
+										mJointList[(*jointIt).second.c_str()] = workingTransform;
                                     }
 								}
 								
@@ -1571,13 +1549,10 @@ bool LLModelLoader::doLoadModel()
 						//Now that we've parsed the joint array, let's determine if we have a full rig
 						//(which means we have all the joints that are required for an avatar versus
 						//a skinned asset attached to a node in a file that contains an entire skeleton,
-						//but does not use the skeleton).
-						mPreview->setRigValid( doesJointArrayContainACompleteRig( model->mSkinInfo.mJointNames ) );
-						if ( !skeletonWithNoRootNode && !model->mSkinInfo.mJointNames.empty() && mPreview->isRigValid() ) 
-						{
-							mPreview->setResetJointFlag( true );
-						}
+						//but does not use the skeleton).						
 						
+						mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames );
+										
 						if ( !missingSkeletonOrScene )
 						{
 							//Set the joint translations on the avatar - if it's a full mapping
@@ -1590,10 +1565,10 @@ bool LLModelLoader::doLoadModel()
 								{
 									std::string lookingForJoint = (*masterJointIt).first.c_str();
 									
-									if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
+									if ( mJointList.find( lookingForJoint ) != mJointList.end() )
 									{
 										//llinfos<<"joint "<<lookingForJoint.c_str()<<llendl;
-										LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+										LLMatrix4 jointTransform = mJointList[lookingForJoint];
 										LLJoint* pJoint = gAgentAvatarp->getJoint( lookingForJoint );
 										if ( pJoint )
 										{   
@@ -1609,6 +1584,7 @@ bool LLModelLoader::doLoadModel()
 							}
 						} //missingSkeletonOrScene
 						
+						
 						//We need to construct the alternate bind matrix (which contains the new joint positions)
 						//in the same order as they were stored in the joint buffer. The joints associated
 						//with the skeleton are not stored in the same order as they are in the exported joint buffer.
@@ -1620,11 +1596,11 @@ bool LLModelLoader::doLoadModel()
 							std::string lookingForJoint = (*jointIt).c_str();
 							//Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
 							//and store it in the alternate bind matrix
-							if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
+							if ( mJointList.find( lookingForJoint ) != mJointList.end() )
 							{
-								LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+								LLMatrix4 jointTransform = mJointList[lookingForJoint];
 								LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
-								newInverse.setTranslation( jointTransforms[lookingForJoint].getTranslation() );
+								newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
 								model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
 							}
 							else
@@ -1787,7 +1763,11 @@ bool LLModelLoader::doLoadModel()
 	processElement(scene);
 	
 	handlePivotPoint( root );
+
+	buildJointToNodeMappingFromScene( root );
 	
+	mPreview->critiqueJointToNodeMappingFromScene();
+
 	return true;
 }
 
@@ -1836,8 +1816,9 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
 				model[lod].push_back(loaded_model);
 
 				if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty())
-				{ //check to see if rig is valid
-					mPreview->setRigValid( doesJointArrayContainACompleteRig( loaded_model->mSkinInfo.mJointNames ) );
+				{ 
+					//check to see if rig is valid					
+					mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );					
 				}
 			}
 			else
@@ -1911,7 +1892,52 @@ void LLModelLoader::loadModelCallback()
 
 	delete this;
 }
-
+//-----------------------------------------------------------------------------
+// buildJointToNodeMappingFromScene()
+//-----------------------------------------------------------------------------
+void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot )
+{
+	daeElement* pScene = pRoot->getDescendant("visual_scene");
+	if ( pScene )
+	{
+		daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
+		S32 childCount = children.getCount();
+		for (S32 i = 0; i < childCount; ++i)
+		{
+			domNode* pNode = daeSafeCast<domNode>(children[i]);
+			processJointToNodeMapping( pNode );			
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// processJointToNodeMapping()
+//-----------------------------------------------------------------------------
+void LLModelLoader::processJointToNodeMapping( domNode* pNode )
+{
+	if ( isNodeAJoint( pNode ) )
+	{
+		//1.Store the parent
+		std::string nodeName = pNode->getName();
+		if ( !nodeName.empty() )
+		{
+			mJointsFromNode.push_front( pNode->getName() );
+		}
+		//2. Handle the kiddo's
+		daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
+		S32 childOfChildCount = childOfChild.getCount();
+		for (S32 i = 0; i < childOfChildCount; ++i)
+		{
+			domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
+			if ( pChildNode )
+			{
+				processJointToNodeMapping( pChildNode );
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// handlePivotPoint()
+//-----------------------------------------------------------------------------
 void LLModelLoader::handlePivotPoint( daeElement* pRoot )
 {
 	//Import an optional pivot point - a pivot point is just a node in the visual scene named "AssetPivot"
@@ -1953,37 +1979,157 @@ void LLModelLoader::handlePivotPoint( daeElement* pRoot )
 	} 
 }
 
-bool LLModelLoader::doesJointArrayContainACompleteRig( const std::vector<std::string> &jointListFromModel )
+//-----------------------------------------------------------------------------
+// critiqueRigForUploadApplicability()
+//-----------------------------------------------------------------------------
+void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
+{
+	//Determines the following use cases for a rig:
+	//1. It is suitable for upload with skin weights & joint positions, or
+	//2. It is suitable for upload as standard av with just skin weights
+	
+	bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
+	bool isRigLegacyOK			 = isRigLegacy( jointListFromAsset );
+
+	//It's OK that both could end up being true, both default to false
+	if ( isJointPositionUploadOK )
+	{
+		setRigValidForJointPositionUpload( true );
+	}
+
+	if ( isRigLegacyOK )
+	{
+		setLegacyRigValid( true );
+	}
+
+	if ( isJointPositionUploadOK )
+	{
+		setResetJointFlag( true );
+	}
+}
+//-----------------------------------------------------------------------------
+// critiqueJointToNodeMappingFromScene()
+//-----------------------------------------------------------------------------
+void LLModelPreview::critiqueJointToNodeMappingFromScene( void  )
+{
+	//Do the actual nodes back the joint listing from the dae?
+	//if yes then this is a fully rigged asset, otherwise it's just a partial rig
+	
+	std::deque<std::string>::iterator jointsFromNodeIt = mJointsFromNode.begin();
+	std::deque<std::string>::iterator jointsFromNodeEndIt = mJointsFromNode.end();
+	bool result = true;
+
+	if ( !mJointsFromNode.empty() )
+	{
+		for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
+		{
+			std::string name = *jointsFromNodeIt;
+			if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
+			{
+				continue;
+			}
+			else
+			{
+				llinfos<<"critiqueJointToNodeMappingFromScene is missing a: "<<name<<llendl;
+				result = false;				
+			}
+		}
+	}
+	else
+	{
+		result = false;
+	}
+
+	//Determines the following use cases for a rig:
+	//1. Full av rig  w/1-1 mapping from the scene and joint array
+	//2. Partial rig but w/o parity between the scene and joint array
+	if ( result )
+	{		
+		setResetJointFlag( true );
+		//llinfos<<"Full"<<llendl;
+	}
+	else
+	{
+		setResetJointFlag( false );
+		//llinfos<<"Partial"<<llendl;
+	}	
+}
+//-----------------------------------------------------------------------------
+// isRigLegacy()
+//-----------------------------------------------------------------------------
+bool LLModelPreview::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
+{
+	//No joints in asset
+	if ( jointListFromAsset.size() == 0 )
+	{
+		return false;
+	}
+
+	bool result = false;
+
+	std::deque<std::string> :: const_iterator masterJointIt = mMasterLegacyJointList.begin();	
+	std::deque<std::string> :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
+	
+	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	
+	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
+	
+	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
+	{
+		result = false;
+		modelJointIt = jointListFromAsset.begin();
+
+		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
+		{
+			if ( *masterJointIt == *modelJointIt )
+			{
+				result = true;
+				break;
+			}			
+		}		
+		if ( !result )
+		{
+			llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl;
+			break;
+		}
+	}	
+	return result;
+}
+//-----------------------------------------------------------------------------
+// isRigSuitableForJointPositionUpload()
+//-----------------------------------------------------------------------------
+bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
 {
+	bool result = false;
+
 	std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin();	
 	std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end();
 	
-	std::vector<std::string> :: const_iterator modelJointIt = jointListFromModel.begin();	
-	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromModel.end();
+	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	
+	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
 	
-	bool found = false;
 	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
 	{
-		found = false;
-		modelJointIt = jointListFromModel.begin();
+		result = false;
+		modelJointIt = jointListFromAsset.begin();
+
 		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
 		{
 			if ( *masterJointIt == *modelJointIt )
 			{
-				found = true;
+				result = true;
 				break;
 			}			
 		}		
-		if ( !found )
+		if ( !result )
 		{
-			llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset - it is required)." << *masterJointIt<< llendl;
+			llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl;
 			break;
 		}
-	}
-	
-	return found;
+	}	
+	return result;
 }
 
+
 //called in the main thread
 void LLModelLoader::loadTextures()
 {
@@ -2013,6 +2159,9 @@ void LLModelLoader::loadTextures()
 	}
 }
 
+//-----------------------------------------------------------------------------
+// isNodeAJoint()
+//-----------------------------------------------------------------------------
 bool LLModelLoader::isNodeAJoint( domNode* pNode )
 {
 	if ( pNode->getName() == NULL)
@@ -2027,7 +2176,9 @@ bool LLModelLoader::isNodeAJoint( domNode* pNode )
 
 	return false;
 }
-
+//-----------------------------------------------------------------------------
+// isNodeAPivotPoint()
+//-----------------------------------------------------------------------------
 bool LLModelLoader::isNodeAPivotPoint( domNode* pNode )
 {
 	bool result = false;
@@ -2046,14 +2197,18 @@ bool LLModelLoader::isNodeAPivotPoint( domNode* pNode )
 	}	
 	return result;
 }
-
+//-----------------------------------------------------------------------------
+// extractTranslation()
+//-----------------------------------------------------------------------------
 void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform )
 {
 	domFloat3 jointTrans = pTranslate->getValue();
 	LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] );
 	transform.setTranslation( singleJointTranslation );
 }
-
+//-----------------------------------------------------------------------------
+// extractTranslationViaElement()
+//-----------------------------------------------------------------------------
 void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform )
 {
 	domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
@@ -2061,8 +2216,10 @@ void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement,
 	LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
 	transform.setTranslation( singleJointTranslation );
 }
-
-void LLModelLoader::processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms )
+//-----------------------------------------------------------------------------
+// processJointNode()
+//-----------------------------------------------------------------------------
+void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms )
 {
 	if (pNode->getName() == NULL)
 	{
@@ -2135,7 +2292,9 @@ void LLModelLoader::processJointNode( domNode* pNode, std::map<std::string,LLMat
 		}
 	}
 }
-
+//-----------------------------------------------------------------------------
+// getChildFromElement()
+//-----------------------------------------------------------------------------
 daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name )
 {
     daeElement* pChildOfElement = pElement->getChild( name.c_str() );
@@ -2456,8 +2615,10 @@ LLColor4 LLModelLoader::getDaeColor(daeElement* element)
 LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
 : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
 , mPelvisZOffset( 0.0f )
-, mRigValid( false )
+, mLegacyRigValid( false )
+, mRigValidJointUpload( false )
 , mResetJoints( false )
+, mLastJointUpdate( false )
 {
 	mNeedsUpdate = TRUE;
 	mCameraDistance = 0.f;
@@ -2491,6 +2652,40 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
 	mModelPivot = LLVector3( 0.0f, 0.0f, 0.0f );
 	
 	glodInit();
+
+	//move into joint mapper class
+	//1. joints for joint offset verification
+	mMasterJointList.push_front("mPelvis");
+	mMasterJointList.push_front("mTorso");
+	mMasterJointList.push_front("mChest");
+	mMasterJointList.push_front("mNeck");
+	mMasterJointList.push_front("mHead");
+	mMasterJointList.push_front("mCollarLeft");
+	mMasterJointList.push_front("mShoulderLeft");
+	mMasterJointList.push_front("mElbowLeft");
+	mMasterJointList.push_front("mWristLeft");
+	mMasterJointList.push_front("mCollarRight");
+	mMasterJointList.push_front("mShoulderRight");
+	mMasterJointList.push_front("mElbowRight");
+	mMasterJointList.push_front("mWristRight");
+	mMasterJointList.push_front("mHipRight");
+	mMasterJointList.push_front("mKneeRight");
+	mMasterJointList.push_front("mFootRight");
+	mMasterJointList.push_front("mHipLeft");
+	mMasterJointList.push_front("mKneeLeft");
+	mMasterJointList.push_front("mFootLeft");
+	//2. legacy joint list - used to verify rigs that will not be using joint offsets
+	mMasterLegacyJointList.push_front("mPelvis");
+	mMasterLegacyJointList.push_front("mTorso");
+	mMasterLegacyJointList.push_front("mChest");
+	mMasterLegacyJointList.push_front("mNeck");
+	mMasterLegacyJointList.push_front("mHead");
+	mMasterLegacyJointList.push_front("mHipRight");
+	mMasterLegacyJointList.push_front("mKneeRight");
+	mMasterLegacyJointList.push_front("mFootRight");
+	mMasterLegacyJointList.push_front("mHipLeft");
+	mMasterLegacyJointList.push_front("mKneeLeft");
+	mMasterLegacyJointList.push_front("mFootLeft");
 }
 
 LLModelPreview::~LLModelPreview()
@@ -2518,14 +2713,20 @@ U32 LLModelPreview::calcResourceCost()
 		}
 	}
 
-	//Upload skin is selected BUT the joints coming in from the asset
-	//were malformed.
+	//Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
 	if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
 	{
-		if ( !isRigValid() )
+		bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+		if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
+		{
+			mFMP->childDisable("ok_btn");		
+		}
+		else
+		if ( !isLegacyRigValid() )
 		{
 			mFMP->childDisable("ok_btn");
 		}
+		//ok_btn should not have been changed unless something was wrong with joint list
 	}
 	
 	U32 cost = 0;
@@ -2858,7 +3059,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)
 		clearGLODGroup();
 	}
 
-	mModelLoader = new LLModelLoader(filename, lod, this);
+	mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode );
 
 	mModelLoader->start();
 
@@ -3694,12 +3895,22 @@ void LLModelPreview::updateStatusMessages()
 	bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false;
 
 	bool skinAndRigOk = true;
-	bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
-	if ( uploadingSkin && !isRigValid() )
+	bool uploadingSkin		     = mFMP->childGetValue("upload_skin").asBoolean();
+	bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+
+	if ( uploadingSkin )
 	{
-		skinAndRigOk = false;
+		if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
+		{
+			skinAndRigOk = false;
+		}
+		else
+		if ( !isLegacyRigValid() )
+		{
+			skinAndRigOk = false;
+		}
 	}
-
+	
 	if ( upload_ok && !errorStateFromLoader && skinAndRigOk )
 	{
 		mFMP->childEnable("ok_btn");
@@ -4089,7 +4300,55 @@ void LLModelPreview::update()
 	}
 
 }
+//-----------------------------------------------------------------------------
+// changeAvatarsJointPositions()
+//-----------------------------------------------------------------------------
+void LLModelPreview::changeAvatarsJointPositions( LLModel* pModel )
+{
+	if ( mMasterJointList.empty() )
+	{
+		return;
+	}
+
+	std::vector<std::string> :: const_iterator jointListItBegin = pModel->mSkinInfo.mJointNames.begin();
+	std::vector<std::string> :: const_iterator jointListItEnd = pModel->mSkinInfo.mJointNames.end();
+
+	S32 index = 0;
+	for ( ; jointListItBegin!=jointListItEnd; ++jointListItBegin, ++index )
+	{	
+		std::string elem = *jointListItBegin;
+		//llinfos<<"joint "<<elem<<llendl;
+
+		S32 matrixCnt = pModel->mSkinInfo.mAlternateBindMatrix.size();
+		if ( matrixCnt < 1 )
+		{
+			llinfos<<"Total WTF moment :"<<matrixCnt<<llendl;
+		}
+		else
+		{
+			LLMatrix4 jointTransform = pModel->mSkinInfo.mAlternateBindMatrix[index];
 
+			LLJoint* pJoint = gAgentAvatarp->getJoint( elem );
+			if ( pJoint )
+			{   
+				pJoint->storeCurrentXform( jointTransform.getTranslation() );												
+			}	
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// getTranslationForJointOffset()
+//-----------------------------------------------------------------------------
+LLVector3 LLModelPreview::getTranslationForJointOffset( std::string joint )
+{
+	LLMatrix4 jointTransform;
+	if ( mJointTransformMap.find( joint ) != mJointTransformMap.end() )
+	{
+		jointTransform = mJointTransformMap[joint];
+		return jointTransform.getTranslation();
+	}
+	return LLVector3(0.0f,0.0f,0.0f);								
+}
 //-----------------------------------------------------------------------------
 // render()
 //-----------------------------------------------------------------------------
@@ -4140,9 +4399,21 @@ BOOL LLModelPreview::render()
 	LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
 	
 	bool has_skin_weights = false;
-	bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();
+	bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();	
 	bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean();
 
+	bool resetJoints = false;
+	if ( upload_joints != mLastJointUpdate )
+	{
+		if ( mLastJointUpdate )
+		{
+			resetJoints = true;
+		}
+
+		mLastJointUpdate = upload_joints;
+
+	}
+
 	for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
 	{
 		for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
@@ -4187,11 +4458,30 @@ BOOL LLModelPreview::render()
 	if (!upload_skin && upload_joints)
 	{ //can't upload joints if not uploading skin weights
 		mFMP->childSetValue("upload_joints", false);
-		upload_joints = false;
-	}
-
+		upload_joints = false;		
+	}	
+	
 	mFMP->childSetEnabled("upload_joints", upload_skin);
 
+	//poke at avatar when we upload custom joints
+	/*	
+	if ( upload_joints )
+	{
+		for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
+		{
+			for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
+			{
+				LLModelInstance& instance = *model_iter;
+				LLModel* model = instance.mModel;
+				if ( !model->mSkinWeights.empty() )
+				{
+					changeAvatarsJointPositions( model );
+				}
+			}
+		}
+	}
+	*/
+	
 	F32 explode = mFMP->childGetValue("physics_explode").asReal();
 
 	glClear(GL_DEPTH_BUFFER_BIT);
@@ -4468,6 +4758,7 @@ BOOL LLModelPreview::render()
 							//quick 'n dirty software vertex skinning
 
 							//build matrix palette
+							
 							LLMatrix4 mat[64];
 							for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j)
 							{
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index dc6a33d0ab4820e8df7bb35cd38293b9bdda8014..186bf114d1b26f6cdcc5d91d87753e8c7defeca9 100755
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -53,6 +53,9 @@ class domTranslate;
 class LLMenuButton;
 class LLToggleableMenu;
 
+typedef std::map<std::string, LLMatrix4> JointTransformMap;
+typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
+
 const S32 NUM_LOD = 4;
 
 class LLModelLoader : public LLThread
@@ -94,8 +97,8 @@ public:
 	//queue of models that need a physics rep
 	model_queue mPhysicsQ;
 
-	LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview);
-
+	LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, 
+				   std::deque<std::string>& jointsFromNodes );
 	virtual void run();
 	bool doLoadModel();
 	bool loadFromSLM(const std::string& filename);
@@ -115,17 +118,19 @@ public:
 	void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
 	void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
 	
-	bool doesJointArrayContainACompleteRig( const std::vector<std::string> &modelJointList );
-	bool checkForCompleteRig(  const std::vector<std::string> &jointListFromModel );
-	
 	void handlePivotPoint( daeElement* pRoot );
 	bool isNodeAPivotPoint( domNode* pNode );
 	
 	void setLoadState(U32 state);
 
+	void buildJointToNodeMappingFromScene( daeElement* pRoot );
+	void processJointToNodeMapping( domNode* pNode );
+
+
 	//map of avatar joints as named in COLLADA assets to internal joint names
 	std::map<std::string, std::string> mJointMap;
-	std::deque<std::string> mMasterJointList;
+	JointTransformMap& mJointList;	
+	std::deque<std::string>& mJointsFromNode;
 };
 
 class LLFloaterModelPreview : public LLFloater
@@ -297,12 +302,28 @@ public:
 	void updateStatusMessages();
 	void clearGLODGroup();
 	void onLODParamCommit(bool enforce_tri_limit);
+
 	const bool getModelPivot( void ) const { return mHasPivot; }
 	void setHasPivot( bool val ) { mHasPivot = val; }
 	void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
-	const bool isRigValid( void ) const { return mRigValid; }
-	void setRigValid( bool rigValid ) { mRigValid = rigValid; }
-	
+
+	//Sets the current avatars joints to new positions
+	//Makes in world go to shit, however
+	void changeAvatarsJointPositions( LLModel* pModel );
+	//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
+	void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
+	void critiqueJointToNodeMappingFromScene( void  );
+	//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
+	//Accessors for joint position upload friendly rigs
+	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
+	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
+	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
+	//Determines if a rig is a legacy from the joint list
+	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );	
+	//Accessors for the legacy rigs
+	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
+	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }	
+
 	static void	textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
 	
 	boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){  return mDetailsSignal.connect(cb);  }
@@ -314,6 +335,8 @@ public:
 	void setResetJointFlag( bool state ) { mResetJoints = state; }
 	bool getResetJointFlag( void ) { return mResetJoints; }
 
+	LLVector3 getTranslationForJointOffset( std::string joint );
+
  protected:
 	friend class LLModelLoader;
 	friend class LLFloaterModelPreview;
@@ -377,8 +400,15 @@ public:
 	
 	float		mPelvisZOffset;
 	
-	bool		mRigValid;
-};
+	bool		mRigValidJointUpload;
+	bool		mLegacyRigValid;
 
+	bool		mLastJointUpdate;
+
+	std::deque<std::string> mMasterJointList;
+	std::deque<std::string> mMasterLegacyJointList;
+	std::deque<std::string> mJointsFromNode;
+	JointTransformMap		mJointTransformMap;
+};
 
 #endif  // LL_LLFLOATERMODELPREVIEW_H
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 4223e9a784e1dc9fbba5ea72a4523d51b2419146..fcf8b084c50c9d8b0bf78b9ba26ef33555f8f144 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1046,11 +1046,13 @@ void LLFloaterPreference::refreshEnabledState()
 	ctrl_deferred->setEnabled(enabled);
 	
 	LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
+	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
 	LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
 
 	enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE);
 		
 	ctrl_ssao->setEnabled(enabled);
+	ctrl_dof->setEnabled(enabled);
 
 	enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail");
 
@@ -1074,6 +1076,7 @@ void LLFloaterPreference::disableUnavailableSettings()
 	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
 	LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
 	LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
+	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
 
 	// if vertex shaders off, disable all shader related products
 	if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))
@@ -1099,6 +1102,9 @@ void LLFloaterPreference::disableUnavailableSettings()
 		ctrl_ssao->setEnabled(FALSE);
 		ctrl_ssao->setValue(FALSE);
 
+		ctrl_dof->setEnabled(FALSE);
+		ctrl_dof->setValue(FALSE);
+
 		ctrl_deferred->setEnabled(FALSE);
 		ctrl_deferred->setValue(FALSE);
 	}
@@ -1116,6 +1122,9 @@ void LLFloaterPreference::disableUnavailableSettings()
 		ctrl_ssao->setEnabled(FALSE);
 		ctrl_ssao->setValue(FALSE);
 
+		ctrl_dof->setEnabled(FALSE);
+		ctrl_dof->setValue(FALSE);
+
 		ctrl_deferred->setEnabled(FALSE);
 		ctrl_deferred->setValue(FALSE);
 	}
@@ -1130,6 +1139,9 @@ void LLFloaterPreference::disableUnavailableSettings()
 		ctrl_ssao->setEnabled(FALSE);
 		ctrl_ssao->setValue(FALSE);
 
+		ctrl_dof->setEnabled(FALSE);
+		ctrl_dof->setValue(FALSE);
+
 		ctrl_deferred->setEnabled(FALSE);
 		ctrl_deferred->setValue(FALSE);
 	}
@@ -1171,6 +1183,9 @@ void LLFloaterPreference::disableUnavailableSettings()
 		ctrl_ssao->setEnabled(FALSE);
 		ctrl_ssao->setValue(FALSE);
 
+		ctrl_dof->setEnabled(FALSE);
+		ctrl_dof->setValue(FALSE);
+
 		ctrl_deferred->setEnabled(FALSE);
 		ctrl_deferred->setValue(FALSE);
 	}
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
index ada0dcf5691f008529761f3ae567e8ce0fe5b257..c7fab2573f29dfffaa97471fbad3059ec4b18e93 100644
--- a/indra/newview/llfloaterregiondebugconsole.cpp
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -58,8 +58,6 @@ namespace
 {
 	// Signal used to notify the floater of responses from the asynchronous
 	// API.
-	typedef boost::signals2::signal<
-		void (const std::string& output)> console_reply_signal_t;
 	console_reply_signal_t sConsoleReplySignal;
 
 	const std::string PROMPT("\n\n> ");
@@ -132,6 +130,11 @@ namespace
 	};
 }
 
+boost::signals2::connection LLFloaterRegionDebugConsole::setConsoleReplyCallback(const console_reply_signal_t::slot_type& cb)
+{
+	return sConsoleReplySignal.connect(cb);
+}
+
 LLFloaterRegionDebugConsole::LLFloaterRegionDebugConsole(LLSD const & key)
 : LLFloater(key), mOutput(NULL)
 {
diff --git a/indra/newview/llfloaterregiondebugconsole.h b/indra/newview/llfloaterregiondebugconsole.h
index 3aa525724efd36b89597a63263e246b1750bbaa6..fd3af4152e94873d083257bf58a31b6de7e1893a 100644
--- a/indra/newview/llfloaterregiondebugconsole.h
+++ b/indra/newview/llfloaterregiondebugconsole.h
@@ -35,6 +35,9 @@
 
 class LLTextEditor;
 
+typedef boost::signals2::signal<
+	void (const std::string& output)> console_reply_signal_t;
+
 class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Responder
 {
 public:
@@ -48,6 +51,8 @@ public:
 
 	LLTextEditor * mOutput;
 
+	static boost::signals2::connection setConsoleReplyCallback(const console_reply_signal_t::slot_type& cb);
+
  private:
 	void onReplyReceived(const std::string& output);
 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 7792b3fb40932cac3553781e9f96856843fb90c1..34fda493754dda653f2fa98e4dbed3c6374d2e0c 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -53,6 +53,7 @@
 #include "llfloatertopobjects.h" // added to fix SL-32336
 #include "llfloatergroups.h"
 #include "llfloaterreg.h"
+#include "llfloaterregiondebugconsole.h"
 #include "llfloatertelehub.h"
 #include "llfloaterwindlight.h"
 #include "llinventorymodel.h"
@@ -159,9 +160,30 @@ bool estate_dispatch_initialized = false;
 //S32 LLFloaterRegionInfo::sRequestSerial = 0;
 LLUUID LLFloaterRegionInfo::sRequestInvoice;
 
+
+void LLFloaterRegionInfo::onConsoleReplyReceived(const std::string& output)
+{
+	llwarns << "here is what they're giving us:  " << output << llendl;
+
+	if (output.find("FALSE") != std::string::npos)
+	{
+		getChild<LLUICtrl>("mesh_rez_enabled_check")->setValue(FALSE);
+	}
+	else
+	{
+		getChild<LLUICtrl>("mesh_rez_enabled_check")->setValue(TRUE);
+	}
+}
+
+
 LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
 	: LLFloater(seed)
 {
+	mConsoleReplySignalConnection = LLFloaterRegionDebugConsole::setConsoleReplyCallback(
+	boost::bind(
+		&LLFloaterRegionInfo::onConsoleReplyReceived,
+		this,
+		_1));
 }
 
 BOOL LLFloaterRegionInfo::postBuild()
@@ -211,12 +233,14 @@ BOOL LLFloaterRegionInfo::postBuild()
 
 LLFloaterRegionInfo::~LLFloaterRegionInfo()
 {
+	mConsoleReplySignalConnection.disconnect();
 }
 
 void LLFloaterRegionInfo::onOpen(const LLSD& key)
 {
 	refreshFromRegion(gAgent.getRegion());
 	requestRegionInfo();
+	requestMeshRezInfo();
 }
 
 // static
@@ -584,6 +608,7 @@ BOOL LLPanelRegionGeneralInfo::postBuild()
 	initCtrl("access_combo");
 	initCtrl("restrict_pushobject");
 	initCtrl("block_parcel_search_check");
+	initCtrl("mesh_rez_enabled_check");
 
 	childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this));
 	childSetAction("kick_all_btn", onClickKickAll, this);
@@ -691,7 +716,42 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
 	return false;
 }
 
+class ConsoleRequestResponder : public LLHTTPClient::Responder
+{
+public:
+	/*virtual*/
+	void error(U32 status, const std::string& reason)
+	{
+		llwarns << "requesting mesh_rez_enabled failed" << llendl;
+	}
+};
+
+
+// called if this request times out.
+class ConsoleUpdateResponder : public LLHTTPClient::Responder
+{
+public:
+	/* virtual */
+	void error(U32 status, const std::string& reason)
+	{
+		llwarns << "Updating mesh enabled region setting failed" << llendl;
+	}
+};
+
+void LLFloaterRegionInfo::requestMeshRezInfo()
+{
+	std::string sim_console_url = gAgent.getRegion()->getCapability("SimConsoleAsync");
 
+	if (!sim_console_url.empty())
+	{
+		std::string request_str = "get mesh_rez_enabled";
+		
+		LLHTTPClient::post(
+			sim_console_url,
+			LLSD(request_str),
+			new ConsoleRequestResponder);
+	}
+}
 
 // setregioninfo
 // strings[0] = 'Y' - block terraform, 'N' - not
@@ -764,6 +824,27 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
 		sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings);
 	}
 
+	std::string sim_console_url = gAgent.getRegion()->getCapability("SimConsoleAsync");
+
+	if (!sim_console_url.empty())
+	{
+		std::string update_str = "set mesh_rez_enabled ";
+		if (getChild<LLUICtrl>("mesh_rez_enabled_check")->getValue().asBoolean())
+		{
+			update_str += "true";
+		}
+		else
+		{
+			update_str += "false";
+		}
+
+		LLHTTPClient::post(
+			sim_console_url,
+			LLSD(update_str),
+			new ConsoleUpdateResponder);
+	}
+
+
 	// if we changed access levels, tell user about it
 	LLViewerRegion* region = gAgent.getRegion();
 	if (region && (getChild<LLUICtrl>("access_combo")->getValue().asInteger() != region->getSimAccess()) )
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index c0758fa92d31efb39f990872eb54f6283eee4a4a..2b87c27fcf378ce52e0053e775d85258f19d5360 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -84,11 +84,16 @@ public:
 	virtual void refresh();
 	
 	void requestRegionInfo();
+	void requestMeshRezInfo();
 
 private:
 	
 	LLFloaterRegionInfo(const LLSD& seed);
 	~LLFloaterRegionInfo();
+
+	void onConsoleReplyReceived(const std::string& output);
+
+	boost::signals2::connection mConsoleReplySignalConnection;;
 	
 protected:
 	void refreshFromRegion(LLViewerRegion* region);
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index f135fcbed6fd16844ec1ee0be86e0cd5dd1a6e84..64af6c2157b97cf1d6cdea643288cd6ec9de8a27 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -1117,23 +1117,23 @@ void LLPanelObject::getState( )
 				mSculptTypeRevert    = sculpt_params->getSculptType();
 			}
 		
+			U8 sculpt_type = sculpt_params->getSculptType();
+			U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
+			BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
+			BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
+			isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
+
 			LLTextureCtrl*  mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
 			if(mTextureCtrl)
 			{
 				mTextureCtrl->setTentative(FALSE);
-				mTextureCtrl->setEnabled(editable);
+				mTextureCtrl->setEnabled(editable && !isMesh);
 				if (editable)
 					mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture());
 				else
 					mTextureCtrl->setImageAssetID(LLUUID::null);
 			}
 
-			U8 sculpt_type = sculpt_params->getSculptType();
-			U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
-			BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
-			BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
-			isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
-			
 			mComboBaseType->setEnabled(!isMesh);
 			
 			if (mCtrlSculptType)
diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e8fc9dd25958ba55a18bdfe9328763e405f8fcc
--- /dev/null
+++ b/indra/newview/llsceneview.cpp
@@ -0,0 +1,429 @@
+/** 
+ * @file llsceneview.cpp
+ * @brief LLSceneView class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llsceneview.h"
+#include "llviewerwindow.h"
+#include "pipeline.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llagent.h"
+#include "llvolumemgr.h"
+
+LLSceneView* gSceneView = NULL;
+
+//borrow this helper function from llfasttimerview.cpp
+template <class VEC_TYPE>
+void removeOutliers(std::vector<VEC_TYPE>& data, F32 k);
+
+
+LLSceneView::LLSceneView(const LLRect& rect)
+	:	LLFloater(LLSD())
+{
+	setRect(rect);
+	setVisible(FALSE);
+	
+	setCanMinimize(false);
+	setCanClose(true);
+}
+
+void LLSceneView::onClickCloseBtn()
+{
+	setVisible(false);
+}
+
+
+void LLSceneView::draw()
+{
+	S32 margin = 10;
+	S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
+	S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f);
+	
+	LLRect new_rect;
+	new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
+	setRect(new_rect);
+
+	// Draw the window background
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
+	
+
+	//aggregate some statistics
+
+	//object sizes
+	std::vector<F32> size[2];
+
+	//triangle counts
+	std::vector<S32> triangles[2]; 
+	std::vector<S32> visible_triangles[2];
+	S32 total_visible_triangles[] = {0, 0};
+	S32 total_triangles[] = {0, 0};
+	
+	//streaming cost
+	std::vector<F32> streaming_cost[2];
+	F32 total_streaming[] = { 0.f, 0.f };
+
+	//physics cost
+	std::vector<F32> physics_cost[2];
+	F32 total_physics[] = { 0.f, 0.f };
+	
+
+	U32 object_count = 0;
+
+	LLViewerRegion* region = gAgent.getRegion();
+	if (region)
+	{
+		for (U32 i = 0; i < gObjectList.getNumObjects(); ++i)
+		{
+			LLViewerObject* object = gObjectList.getObject(i);
+			
+			if (object && 
+				object->getVolume()&&
+				object->getRegion() == region)
+			{
+				U32 idx = object->isAttachment() ? 1 : 0;
+
+				LLVolume* volume = object->getVolume();
+				object_count++;
+				
+				F32 radius = object->getScale().magVec();
+				size[idx].push_back(radius);
+
+				S32 visible = volume->getNumTriangles();
+				S32 high_triangles = object->getHighLODTriangleCount();
+
+				total_visible_triangles[idx] += visible;
+				total_triangles[idx] += high_triangles;
+
+				visible_triangles[idx].push_back(visible);
+				triangles[idx].push_back(high_triangles);
+
+				F32 streaming = object->getStreamingCost();
+				total_streaming[idx] += streaming;
+				streaming_cost[idx].push_back(streaming);
+
+				F32 physics = object->getPhysicsCost();
+				total_physics[idx] += physics;
+				physics_cost[idx].push_back(physics);
+			}
+		}
+	}
+
+	const char* category[] =
+	{
+		"Region",
+		"Attachment"
+	};
+
+	S32 graph_pos[4];
+
+	for (U32 i = 0; i < 4; ++i)
+	{
+		graph_pos[i] = new_rect.getHeight()/4*(i+1);
+	}
+
+	for (U32 idx = 0; idx < 2; idx++)
+	{
+		if (!size[idx].empty())
+		{ //display graph of object sizes
+			std::sort(size[idx].begin(), size[idx].end());
+
+			ll_remove_outliers(size[idx], 1.f);
+
+			LLRect size_rect;
+			
+			if (idx == 0)
+			{
+				size_rect = LLRect(margin, graph_pos[0]-margin, new_rect.getWidth()/2-margin, margin*2);
+			}
+			else
+			{
+				size_rect = LLRect(margin+new_rect.getWidth()/2, graph_pos[0]-margin, new_rect.getWidth()-margin, margin*2);
+			}
+
+			gl_rect_2d(size_rect, LLColor4::white, false);
+
+			F32 size_domain[] = { 128.f, 0.f };
+			
+			//get domain of sizes
+			for (U32 i = 0; i < size[idx].size(); ++i)
+			{
+				size_domain[0] = llmin(size_domain[0], size[idx][i]);
+				size_domain[1] = llmax(size_domain[1], size[idx][i]);
+			}
+
+			F32 size_range = size_domain[1]-size_domain[0];
+			
+			U32 count = size[idx].size();
+
+			F32 total = 0.f;
+
+			gGL.begin(LLRender::LINE_STRIP);
+
+			for (U32 i = 0; i < count; ++i)
+			{
+				F32 rad = size[idx][i];
+				total += rad;	
+				F32 y = (rad-size_domain[0])/size_range*size_rect.getHeight()+size_rect.mBottom;
+				F32 x = (F32) i / count * size_rect.getWidth() + size_rect.mLeft;
+
+				gGL.vertex2f(x,y);
+
+				if (i%4096 == 0)
+				{
+					gGL.end();
+					gGL.flush();
+					gGL.begin(LLRender::LINE_STRIP);
+				}
+			}
+
+			gGL.end();
+			gGL.flush();
+
+			std::string label = llformat("%s Object Sizes (m) -- [%.1f, %.1f] Mean: %.1f  Median: %.1f -- %d samples",
+											category[idx], size_domain[0], size_domain[1], total/count, size[idx][count/2], count);
+
+			LLFontGL::getFontMonospace()->renderUTF8(label,
+											0 , size_rect.mLeft, size_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
+
+		}
+	}
+
+	for (U32 idx = 0; idx < 2; ++idx)
+	{
+		if (!triangles[idx].empty())
+		{ //plot graph of visible/total triangles
+			std::sort(triangles[idx].begin(), triangles[idx].end());
+			
+			ll_remove_outliers(triangles[idx], 1.f);
+			
+			LLRect tri_rect;
+			if (idx == 0)
+			{
+				tri_rect = LLRect(margin, graph_pos[1]-margin, new_rect.getWidth()/2-margin, graph_pos[0]+margin);
+			}
+			else
+			{
+				tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[1]-margin, new_rect.getWidth()-margin, graph_pos[0]+margin);
+			}
+
+			gl_rect_2d(tri_rect, LLColor4::white, false);
+
+			S32 tri_domain[] = { 65536, 0 };
+						
+			//get domain of triangle counts
+			for (U32 i = 0; i < triangles[idx].size(); ++i)
+			{
+				tri_domain[0] = llmin(tri_domain[0], triangles[idx][i]);
+				tri_domain[1] = llmax(tri_domain[1], triangles[idx][i]);		
+			}
+
+			U32 triangle_range = tri_domain[1]-tri_domain[0];
+
+			U32 count = triangles[idx].size();
+
+			U32 total = 0;
+
+			gGL.begin(LLRender::LINE_STRIP);
+			//plot triangles
+			for (U32 i = 0; i < count; ++i)
+			{
+				U32 tri_count = triangles[idx][i];
+				total += tri_count;	
+				F32 y = (F32) (tri_count-tri_domain[0])/triangle_range*tri_rect.getHeight()+tri_rect.mBottom;
+				F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;
+
+				gGL.vertex2f(x,y);
+
+				if (i%4096 == 0)
+				{
+					gGL.end();
+					gGL.flush();
+					gGL.begin(LLRender::LINE_STRIP);
+				}
+			}
+
+			gGL.end();
+			gGL.flush();
+
+			U32 total_visible = 0;
+			count = visible_triangles[idx].size();
+
+			for (U32 i = 0; i < count; ++i)
+			{
+				U32 tri_count = visible_triangles[idx][i];
+				total_visible += tri_count;	
+			}
+
+			std::string label = llformat("%s Object Triangle Counts (Ktris) -- [%.2f, %.2f] Mean: %.2f  Median: %.2f  Visible: %.2f/%.2f",
+											category[idx], tri_domain[0]/1024.f, tri_domain[1]/1024.f, (total/count)/1024.f, triangles[idx][count/2]/1024.f, total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f);
+
+			LLFontGL::getFontMonospace()->renderUTF8(label,
+											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
+
+		}
+	}
+
+	for (U32 idx = 0; idx < 2; ++idx)
+	{
+		if (!streaming_cost[idx].empty())
+		{ //plot graph of streaming cost
+			std::sort(streaming_cost[idx].begin(), streaming_cost[idx].end());
+			
+			ll_remove_outliers(streaming_cost[idx], 1.f);
+			
+			LLRect tri_rect;
+			if (idx == 0)
+			{
+				tri_rect = LLRect(margin, graph_pos[2]-margin, new_rect.getWidth()/2-margin, graph_pos[1]+margin);
+			}
+			else
+			{
+				tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[2]-margin, new_rect.getWidth()-margin, graph_pos[1]+margin);
+			}
+
+			gl_rect_2d(tri_rect, LLColor4::white, false);
+
+			F32 streaming_domain[] = { 65536, 0 };
+						
+			//get domain of triangle counts
+			for (U32 i = 0; i < streaming_cost[idx].size(); ++i)
+			{
+				streaming_domain[0] = llmin(streaming_domain[0], streaming_cost[idx][i]);
+				streaming_domain[1] = llmax(streaming_domain[1], streaming_cost[idx][i]);		
+			}
+
+			F32 cost_range = streaming_domain[1]-streaming_domain[0];
+
+			U32 count = streaming_cost[idx].size();
+
+			F32 total = 0;
+
+			gGL.begin(LLRender::LINE_STRIP);
+			//plot triangles
+			for (U32 i = 0; i < count; ++i)
+			{
+				F32 sc = streaming_cost[idx][i];
+				total += sc;	
+				F32 y = (F32) (sc-streaming_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom;
+				F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;
+
+				gGL.vertex2f(x,y);
+
+				if (i%4096 == 0)
+				{
+					gGL.end();
+					gGL.flush();
+					gGL.begin(LLRender::LINE_STRIP);
+				}
+			}
+
+			gGL.end();
+			gGL.flush();
+
+			std::string label = llformat("%s Object Streaming Cost -- [%.2f, %.2f] Mean: %.2f  Total: %.2f",
+											category[idx], streaming_domain[0], streaming_domain[1], total/count, total_streaming[idx]);
+
+			LLFontGL::getFontMonospace()->renderUTF8(label,
+											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
+
+		}
+	}
+
+	for (U32 idx = 0; idx < 2; ++idx)
+	{
+		if (!physics_cost[idx].empty())
+		{ //plot graph of physics cost
+			std::sort(physics_cost[idx].begin(), physics_cost[idx].end());
+			
+			ll_remove_outliers(physics_cost[idx], 1.f);
+			
+			LLRect tri_rect;
+			if (idx == 0)
+			{
+				tri_rect = LLRect(margin, graph_pos[3]-margin, new_rect.getWidth()/2-margin, graph_pos[2]+margin);
+			}
+			else
+			{
+				tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[3]-margin, new_rect.getWidth()-margin, graph_pos[2]+margin);
+			}
+
+			gl_rect_2d(tri_rect, LLColor4::white, false);
+
+			F32 physics_domain[] = { 65536, 0 };
+						
+			//get domain of triangle counts
+			for (U32 i = 0; i < physics_cost[idx].size(); ++i)
+			{
+				physics_domain[0] = llmin(physics_domain[0], physics_cost[idx][i]);
+				physics_domain[1] = llmax(physics_domain[1], physics_cost[idx][i]);		
+			}
+
+			F32 cost_range = physics_domain[1]-physics_domain[0];
+
+			U32 count = physics_cost[idx].size();
+
+			F32 total = 0;
+
+			gGL.begin(LLRender::LINE_STRIP);
+			//plot triangles
+			for (U32 i = 0; i < count; ++i)
+			{
+				F32 pc = physics_cost[idx][i];
+				total += pc;	
+				F32 y = (F32) (pc-physics_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom;
+				F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;
+
+				gGL.vertex2f(x,y);
+
+				if (i%4096 == 0)
+				{
+					gGL.end();
+					gGL.flush();
+					gGL.begin(LLRender::LINE_STRIP);
+				}
+			}
+
+			gGL.end();
+			gGL.flush();
+
+			std::string label = llformat("%s Object Physics Cost -- [%.2f, %.2f] Mean: %.2f  Total: %.2f",
+											category[idx], physics_domain[0], physics_domain[1], total/count, total_physics[idx]);
+
+			LLFontGL::getFontMonospace()->renderUTF8(label,
+											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
+
+		}
+	}
+
+	
+	
+
+	LLView::draw();
+}
+
+
diff --git a/indra/newview/llsceneview.h b/indra/newview/llsceneview.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a3a14bbee45571dd6dee59bc3ab2633dfa7a380
--- /dev/null
+++ b/indra/newview/llsceneview.h
@@ -0,0 +1,48 @@
+/** 
+ * @file llsceneview.h
+ * @brief LLSceneView class header file
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSCENEVIEW_H
+#define LL_LLSCENEVIEW_H
+
+#include "llfloater.h"
+
+
+class LLSceneView : public LLFloater
+{
+public:
+	LLSceneView(const LLRect& rect);
+
+	virtual void draw();
+	
+protected:
+	virtual void onClickCloseBtn();
+
+
+};
+
+extern LLSceneView* gSceneView;
+
+#endif // LL_LLSCENEVIEW_H
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index b45d1aa3a6d3c81223fc34d3ef720f58f983978f..ba48ad45172ca79d9804b7dc1898861a4ce01caa 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1024,7 +1024,7 @@ void render_hud_attachments()
 		gPipeline.renderGeom(hud_cam);
 
 		LLSpatialGroup::sNoDelete = FALSE;
-		gPipeline.clearReferences();
+		//gPipeline.clearReferences();
 
 		render_hud_elements();
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 22d5f18e3dfec56e79f5c0ae35c1e71da7daf527..bb049731643886c4e2b0eb472f9d1310f23db7f7 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -76,6 +76,7 @@
 #include "llmoveview.h"
 #include "llparcel.h"
 #include "llrootview.h"
+#include "llsceneview.h"
 #include "llselectmgr.h"
 #include "llsidetray.h"
 #include "llstatusbar.h"
@@ -515,6 +516,11 @@ class LLAdvancedToggleConsole : public view_listener_t
 		{
 			toggle_visibility( (void*)gDebugView->mFastTimerView );
 		}
+		else if ("scene view" == console_type)
+		{
+			toggle_visibility( (void*)gSceneView);
+		}
+
 #if MEM_TRACK_MEM
 		else if ("memory view" == console_type)
 		{
@@ -550,6 +556,10 @@ class LLAdvancedCheckConsole : public view_listener_t
 		{
 			new_value = get_visibility( (void*)gDebugView->mFastTimerView );
 		}
+		else if ("scene view" == console_type)
+		{
+			new_value = get_visibility( (void*) gSceneView);
+		}
 #if MEM_TRACK_MEM
 		else if ("memory view" == console_type)
 		{
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 70b180903366c622f5661731d7ce0dd8acc5f45c..a5b59e8281929c4be873d2cdcc59093b4c175660 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -240,6 +240,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
 	mState(0),
 	mMedia(NULL),
 	mClickAction(0),
+	mObjectCost(0),
+	mLinksetCost(0),
+	mPhysicsCost(0),
 	mLinksetPhysicsCost(0.f),
 	mCostStale(true),
 	mPhysicsShapeUnknown(true),
@@ -3144,6 +3147,11 @@ U32 LLViewerObject::getTriangleCount()
 	return 0;
 }
 
+U32 LLViewerObject::getHighLODTriangleCount()
+{
+	return 0;
+}
+
 void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
 {
 	LLVector4a center;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 44f46b8c0f83df0dd0ebde8cf141d2013fdc33ee..e417343becb07402ec4755c4fd80ca198b260cfe 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -328,6 +328,7 @@ public:
 
 	virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL);
 	virtual U32 getTriangleCount();
+	virtual U32 getHighLODTriangleCount();
 
 	void setObjectCost(F32 cost);
 	F32 getObjectCost();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 8e4e6b5b07d3beb098a6c549e582060294452518..b946dbbd0f69dac0e2b7ac3789808383900397c4 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -3746,7 +3746,11 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
 	LLVector3 mouse_world_start = mouse_point_global;
 	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
 
-	//gDebugRaycastIntersection = mouse_world_end;
+	if (!LLViewerJoystick::getInstance()->getOverrideCamera())
+	{ //always set raycast intersection to mouse_world_end unless
+		//flycam is on (for DoF effect)
+		gDebugRaycastIntersection = mouse_world_end;
+	}
 
 	if (start)
 	{
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 7c4a4c13ba3d792d5359dbe7c5671d9280b59ff7..45277265df73b31eccd17a69275a3a75283648c8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3108,6 +3108,36 @@ U32 LLVOVolume::getTriangleCount()
 	return count;
 }
 
+U32 LLVOVolume::getHighLODTriangleCount()
+{
+	U32 ret = 0;
+
+	LLVolume* volume = getVolume();
+
+	if (!isSculpted())
+	{
+		LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3);
+		ret = ref->getNumTriangles();
+		LLPrimitive::getVolumeManager()->unrefVolume(ref);
+	}
+	else if (isMesh())
+	{
+		LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3);
+		if (ref->isTetrahedron() || ref->getNumVolumeFaces() == 0)
+		{
+			gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH);
+		}
+		ret = ref->getNumTriangles();
+		LLPrimitive::getVolumeManager()->unrefVolume(ref);
+	}
+	else
+	{ //default sculpts have a constant number of triangles
+		ret = 31*2*31;  //31 rows of 31 columns of quads for a 32x32 vertex patch
+	}
+
+	return ret;
+}
+
 //static
 void LLVOVolume::preUpdateGeom()
 {
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 029811886d0f5660ab2da8f7f88e7965f7a7a3eb..fc00f0c0d0da3bcd6830e8597c6a104393fc7f5c 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -132,6 +132,7 @@ public:
 				U32 	getRenderCost(std::set<LLUUID> &textures) const;
 	/*virtual*/	F32		getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL);
 	/*virtual*/ U32		getTriangleCount();
+	/*virtual*/ U32		getHighLODTriangleCount();
 	/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, 
 										  S32 face = -1,                        // which face to check, -1 = ALL_SIDES
 										  BOOL pick_transparent = FALSE,
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 82a29bbbe98bf0d3447756e29bdbb28d33573d66..d18e1de60cb5fca5807e63de349c5226a6533fa6 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -240,6 +240,16 @@ glh::matrix4f glh_get_current_projection()
 	return glh_copy_matrix(gGLProjection);
 }
 
+glh::matrix4f glh_get_last_modelview()
+{
+	return glh_copy_matrix(gGLLastModelView);
+}
+
+glh::matrix4f glh_get_last_projection()
+{
+	return glh_copy_matrix(gGLLastProjection);
+}
+
 void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst)
 {
 	for (U32 i = 0; i < 16; i++)
@@ -1910,7 +1920,7 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
 
 static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
 
-void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip)
+void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep)
 {
 	LLFastTimer t(FTM_CULL);
 	LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
@@ -1930,6 +1940,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 		mScreen.bindTarget();
 	}
 
+	if (sUseOcclusion > 1)
+	{
+		gGL.setColorMask(false, false);
+	}
+
 	glMatrixMode(GL_PROJECTION);
 	glPushMatrix();
 	glLoadMatrixd(gGLLastProjection);
@@ -1944,10 +1959,37 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 	LLGLDisable test(GL_ALPHA_TEST);
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-	if (sUseOcclusion > 1)
+
+	//setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling)
+	LLViewerRegion* region = gAgent.getRegion();
+	LLPlane plane;
+
+	if (planep)
 	{
-		gGL.setColorMask(false, false);
+		plane = *planep;
 	}
+	else 
+	{
+		if (region)
+		{
+			LLVector3 pnorm;
+			F32 height = region->getWaterHeight();
+			if (water_clip < 0)
+			{ //camera is above water, clip plane points up
+				pnorm.setVec(0,0,1);
+				plane.setVec(pnorm, -height);
+			}
+			else if (water_clip > 0)
+			{	//camera is below water, clip plane points down
+				pnorm = LLVector3(0,0,-1);
+				plane.setVec(pnorm, height);
+			}
+		}
+	}
+	
+	glh::matrix4f modelview = glh_get_last_modelview();
+	glh::matrix4f proj = glh_get_last_projection();
+	LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender);
 
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 
@@ -6314,8 +6356,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 		F32 fnumber = gSavedSettings.getF32("CameraFNumber");
 		F32 default_focal_length = gSavedSettings.getF32("CameraFocalLength");
 
-		if (LLToolMgr::getInstance()->inBuildMode())
-		{ //squish focal length when in build mode so DoF doesn't make editing objects difficult
+		if (LLToolMgr::getInstance()->inBuildMode() || !gSavedSettings.getBOOL("RenderDepthOfField"))
+		{ //squish focal length when in build mode (or if DoF is disabled) so DoF doesn't make editing objects difficult
 			default_focal_length = 5.f;
 		}
 
@@ -7887,18 +7929,13 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 					gPipeline.pushRenderTypeMask();
 					gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
 						LLPipeline::RENDER_TYPE_WL_SKY,
+						LLPipeline::RENDER_TYPE_CLOUDS,
 						LLPipeline::END_RENDER_TYPES);
 
 					static LLCullResult result;
 					updateCull(camera, result);
 					stateSort(camera, result);
 
-					andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-						LLPipeline::RENDER_TYPE_CLOUDS,
-						LLPipeline::RENDER_TYPE_WL_SKY,
-						LLPipeline::END_RENDER_TYPES);
-
-					//bad pop here 
 					renderGeom(camera, TRUE);
 
 					gPipeline.popRenderTypeMask();
@@ -7931,7 +7968,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 
 					LLGLUserClipPlane clip_plane(plane, mat, projection);
 					LLGLDisable cull(GL_CULL_FACE);
-					updateCull(camera, ref_result, 1);
+					updateCull(camera, ref_result, -water_clip, &plane);
 					stateSort(camera, ref_result);
 				}	
 
@@ -7988,9 +8025,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 			{
 				//clip out geometry on the same side of water as the camera
 				mat = glh_get_current_modelview();
-				LLGLUserClipPlane clip_plane(LLPlane(-pnorm, -(pd+pad)), mat, projection);
+				LLPlane plane(-pnorm, -(pd+pad));
+
+				LLGLUserClipPlane clip_plane(plane, mat, projection);
 				static LLCullResult result;
-				updateCull(camera, result, water_clip);
+				updateCull(camera, result, water_clip, &plane);
 				stateSort(camera, result);
 
 				gGL.setColorMask(true, true);
@@ -8785,7 +8824,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 		near_clip = -max.mV[2];
 		F32 far_clip = -min.mV[2]*2.f;
 
-		far_clip = llmin(far_clip, 128.f);
+		//far_clip = llmin(far_clip, 128.f);
 		far_clip = llmin(far_clip, camera.getFar());
 
 		F32 range = far_clip-near_clip;
@@ -9135,7 +9174,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 			}
 		}
 
-		shadow_cam.setFar(128.f);
+		//shadow_cam.setFar(128.f);
 		shadow_cam.setOriginAndLookAt(eye, up, center);
 
 		shadow_cam.setOrigin(0,0,0);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 074c1742e29a0eef4058b7a52acd06df2ae300f1..0cf3fde562747685740e5840908fe727b0ce34d5 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -208,7 +208,7 @@ public:
 	BOOL visibleObjectsInFrustum(LLCamera& camera);
 	BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max);
 	BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0));
-	void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0);  //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
+	void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL);  //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
 	void createObjects(F32 max_dtime);
 	void createObject(LLViewerObject* vobj);
 	void updateGeom(F32 max_dtime);
diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
index 4b312c6ce78866124887dbc7293bf9b932497645..03af348a8d73e8cfedee346ae17786e00a56dd2c 100644
--- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml
@@ -291,7 +291,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 		 height="388"
 		 top_delta="0"
 		 name="optimize_panel"
-		 visible="true"
+		 visible="false"
 		 width="535"
 		 left="0">
 		<panel
@@ -441,10 +441,10 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 				 follows="all"
 				 width="185">
 			</panel>
-			<text top="45" left="224" text_color="White" font="SansSerifSmallBold" width="300" height="4">Performance</text>
-			<text top="65" left="204" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text>
-			<text top="45" left="384" text_color="White" font="SansSerifSmallBold" width="300" height="4">Accuracy</text>
-			<text top="65" left="364" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text>
+			<text top="45" left="214" text_color="White" font="SansSerifSmallBold" halign="center" width="110" height="30" wrap="true">Higher Performance</text>
+			<text top="75" left="204" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text>
+			<text top="45" left="378" text_color="White" font="SansSerifSmallBold" halign="center" width="90" height="30" wrap="true">Higher Accuracy</text>
+			<text top="75" left="364" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text>
 
 			<slider
 		   follows="left|top"
@@ -457,7 +457,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 		   min_val="2"
 		   name="accuracy_slider"
 		   show_text="false"
-		   top="120"
+		   top="130"
 		   width="290" />
 			<text 
 			font="SansSerifSmall" 
@@ -475,9 +475,8 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 				 image_name="model_wizard\divider_line.png"/>
 	
 			<text top_delta="20" width="200" text_color="White" left_delta="50" name="streaming cost"  height="20">Resource Cost:    [COST]</text>
-			<text top_delta="24" width="100" text_color="White" left_delta="0"  height="20">Upload Fee:</text>
 			<text
-						 top_pad="5"
+						 top_pad="15"
 						 width="130"
 						 height="14"
 						 left="10"
@@ -572,10 +571,10 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 		 bg_opaque_color="DkGray2"
 		 background_visible="true"
 		 background_opaque="true">
-      <text top="15" left="30" text_color="White" font="SansSerifSmallBold" width="300" height="4">Performance</text>
-      <text top="35" left="10" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text>
-      <text top="15" left="390" text_color="White" font="SansSerifSmallBold" width="300" height="4">Accuracy</text>
-      <text top="35" left="360" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text>
+      <text top="25" left="30" text_color="White" font="SansSerifSmallBold" width="300" height="4">Performance</text>
+      <text top="45" left="10" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text>
+      <text top="25" left="390" text_color="White" font="SansSerifSmallBold" width="300" height="4">Accuracy</text>
+      <text top="45" left="360" halign="center" width="130" word_wrap="true"   font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text>
 
       <slider
 		   follows="left|top"
@@ -588,7 +587,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 		   min_val="0"
 		   name="physics_slider"
 		   show_text="false"
-		   top="80"
+		   top="90"
 		   width="440" />
       <text
 			font="SansSerifSmall"
@@ -608,9 +607,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 			 height="2"
 			 image_name="model_wizard\divider_line.png"/>
 		
-	<text top_delta="20" width="180" text_color="White" left="160" name="streaming cost"  height="20">Resource Cost:       [COST]</text>
-      <text top_delta="26" width="180" text_color="White" left_delta="0" name="physics cost"  height="20">Physics Cost:           [COST]</text>
-      <text top_delta="26" width="180" text_color="White" left_delta="0"  height="20">Upload Fee:</text>
+	<text top_delta="30" width="180" text_color="White" left="160" name="streaming cost"  height="20">Resource Cost:       [COST]</text>
  
     </panel>
 	</panel>
@@ -619,7 +616,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 		 height="388"
 		 top_delta="0"
 		 name="physics2_panel"
-		 visible="false"
+		 visible="true"
 		 width="535"
 		 left="0">
 		<panel
@@ -738,10 +735,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se
 			 height="15"
 			 name="dimension_z"
 			 left_delta="46"/>
-			<text top="40" width="180" text_color="White" left="225" name="streaming cost"  height="20">Resource Cost:       [COST]</text>
-			<text top_delta="26" width="180" text_color="White" left_delta="0" name="physics cost"  height="20">Physics Cost:           [COST]</text>
-			<text top_delta="26" width="180" text_color="White" left_delta="0"  height="20">Upload Fee:</text>
-
+			<text top="60" width="180" text_color="White" left="225" name="streaming cost"  height="20">Resource Cost:       [COST]</text>
 		</panel>
 	</panel>
 
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 0efb6c6e90b973b8a73c9ada560247b020c9e366..941ba3bfea0c9ff1522f6fbd725b846305e9bdf6 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1901,6 +1901,16 @@
                  function="Advanced.ToggleConsole"
                  parameter="memory view" />
             </menu_item_check>
+            <menu_item_check
+               label="Scene Statistics"
+               name="Scene Statistics">
+              <menu_item_check.on_check
+               function="Advanced.CheckConsole"
+               parameter="scene view" />
+              <menu_item_check.on_click
+               function="Advanced.ToggleConsole"
+               parameter="scene view" />
+            </menu_item_check>
 
             <menu_item_separator/>
 
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 928ca6d8d0e899f0da8539e1e6c22ab9da514c3c..9ecab1a356f9326350556b63f31a75b6802827c5 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -258,6 +258,19 @@
          	<check_box.commit_callback
 			 function="Pref.VertexShaderEnable" />
     	</check_box>
+      <check_box
+		 control_name="RenderDepthOfField"
+		 height="16"
+		 initial_value="true"
+		 label="Depth of Field"
+		 layout="topleft"
+		 left_delta="0"
+		 name="UseDoF"
+		 top_pad="1"
+		 width="256">
+        <check_box.commit_callback
+     function="Pref.VertexShaderEnable" />
+      </check_box>
 
         <text
          type="string"
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
index ca9579284b8e0dc0db16f8be742ad7b06937f433..e0d9f3f71456a996806dedfa1d3345de074d3ba0 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -114,7 +114,7 @@
      layout="topleft"
      left="10"
      name="allow_land_resell_check"
-     top="160"
+     top="150"
      width="80" />
     <check_box
      height="20"
@@ -122,7 +122,7 @@
      layout="topleft"
      left="10"
      name="allow_parcel_changes_check"
-     top="180"
+     top="170"
      width="80" />
     <check_box
      height="20"
@@ -131,7 +131,16 @@
      left="10"
      name="block_parcel_search_check"
      tool_tip="Let people see this region and its parcels in search results"
-     top="200"
+     top="190"
+     width="80" />
+	<check_box
+     height="20"
+     label="Allow Mesh Objects"
+     layout="topleft"
+     left="10"
+     name="mesh_rez_enabled_check"
+     tool_tip="Let people rez mesh objects on this region"
+     top="210"
      width="80" />
     <spinner
      decimal_digits="0"