diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
index de2ea2a065afe32e5a5b8e5ffc1d0cb7c6dc320f..3424613e948fd120e63a10ca111f1bfa556b80a9 100644
--- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
@@ -91,7 +91,9 @@ void main()
 
 	// Collect normal lights (need to be divided by two, as we later multiply by 2)
 	col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz);
+//	col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z);
 	col.rgb += light_diffuse[2].rgb * calcDirectionalLight(norm, light_position[2].xyz);
+//	col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z);
 	col.rgb += light_diffuse[3].rgb * calcDirectionalLight(norm, light_position[3].xyz);
 	col /= 2.0;
 	vertex_color = col*color;
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index e180d91461b50100503724ff5fb8ffad65e4615c..af6977d3cd689912e8768a35ab10a9a4f1eb7eef 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -125,11 +125,17 @@ BOOL LLViewerDynamicTexture::render()
 //-----------------------------------------------------------------------------
 void LLViewerDynamicTexture::preRender(BOOL clear_depth)
 {
+	// <FS:Beq> changes to support higher resolution rendering in the preview
+	////only images up to 512x512 are supported
+	//llassert(mFullHeight <= 512);
+	//llassert(mFullWidth <= 512);
 	gPipeline.allocatePhysicsBuffer();
 	llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth()));
 	llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight()));
 
+//	if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI)
 	if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsATI)
+// </FS:Beq>
 	{ //using offscreen render target, just use the bottom left corner
 		mOrigin.set(0, 0);
 	}
@@ -215,13 +221,15 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 	{
 		return TRUE;
 	}
-
+	// <FS:Beq> changes to support higher resolution rendering in the preview
+	//	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI;
 	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsATI;
 	if (use_fbo)
 	{
+//		gPipeline.mWaterDis.bindTarget();
 		gPipeline.mPhysicsDisplay.bindTarget();
 	}
-
+	// </FS:Beq>
 	LLGLSLShader::bindNoShader();
 	LLVertexBuffer::unbind();
 	
@@ -257,7 +265,10 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 
 	if (use_fbo)
 	{
+		// <FS:Beq> changes to support higher resolution rendering in the preview
+		// gPipeline.mWaterDis.flush();
 		gPipeline.mPhysicsDisplay.flush();
+		// </FS:Beq>
 	}
 
 	return ret;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 79b9df2fa6b6b5fca2fc031681f878a814800bf6..7624245c16220a806b1f1250d4cec35d61d86d6f 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -427,8 +427,11 @@ void LLFloaterModelPreview::initModelPreview()
 	{
 		delete mModelPreview;
 	}
+	// <FS:Beq> mesh uploader changes to allow higher resolution render
+	//	mModelPreview = new LLModelPreview(512, 512, this);
 	auto size = gSavedSettings.getS32("PreviewRenderSize");
 	mModelPreview = new LLModelPreview(size, size, this );
+	// </FS:Beq>
 	mModelPreview->setPreviewTarget(16.f);
 	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
 	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, _1));
@@ -438,6 +441,8 @@ void LLFloaterModelPreview::onViewOptionChecked(LLUICtrl* ctrl)
 {
 	if (mModelPreview)
 	{
+		// <FS:Beq> only show explode when phsyics is on
+		//		mModelPreview->mViewOption[ctrl->getName()] = !mModelPreview->mViewOption[ctrl->getName()];
 		auto name = ctrl->getName();
 		mModelPreview->mViewOption[name] = !mModelPreview->mViewOption[name];
 		if (name == "show_physics")
@@ -659,6 +664,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
 	}
 }
 
+// <FS:Beq> extracted method to simplify changes in layout
 void LLFloaterModelPreview::draw3dPreview()
 {
 	gGL.color3f(1.f, 1.f, 1.f);
@@ -1260,7 +1266,7 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
 , mResetJoints( false )
 , mModelNoErrors( true )
 , mLastJointUpdate( false )
-, mHasDegenerate( false )
+, mHasDegenerate( false ) // <FS:Beq>
 {
 	mNeedsUpdate = TRUE;
 	mCameraDistance = 0.f;
@@ -2750,7 +2756,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
 
 void LLModelPreview::updateStatusMessages()
 {
-// bit mask values for physics errors. used to prevent overwrite of single line status
+// <FS:Beq> bit mask values for physics errors. used to prevent overwrite of single line status
 // TODO: use this to provied multiline status
 	enum PhysicsError
 	{
@@ -2760,10 +2766,10 @@ void LLModelPreview::updateStatusMessages()
 		TOOMANYHULLS=4,
 		TOOMANYVERTSINHULL=8
 	};
-
+// </FS:Beq>
 	assert_main_thread();
 
-	U32 has_physics_error{ PhysicsError::NONE }; // physics error bitmap
+	U32 has_physics_error{ PhysicsError::NONE }; // <FS:Beq> physics error bitmap
 	//triangle/vertex/submesh count for each mesh asset for each lod
 	std::vector<S32> tris[LLModel::NUM_LODS];
 	std::vector<S32> verts[LLModel::NUM_LODS];
@@ -2852,25 +2858,38 @@ void LLModelPreview::updateStatusMessages()
 	{
 		mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
 	}
-
+	// <FS:Beq> make has_degenerate a member so that we can use it in the render method
+	// has_degenerate = false
 	mHasDegenerate = false;
 	{//check for degenerate triangles in physics mesh
 		U32 lod = LLModel::LOD_PHYSICS;
 		const LLVector4a scale(0.5f);
-		for (U32 i = 0; i < mModel[lod].size() && !mHasDegenerate; ++i)
+		for (U32 i = 0; i < mModel[lod].size() && !mHasDegenerate; ++i)// <FS:Beq> make has_degenerate a member 
 		{ //for each model in the lod
 			if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())
 			{ //no decomp exists
 				S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
-				for (S32 j = 0; j < cur_submeshes && !mHasDegenerate; ++j)
+				for (S32 j = 0; j < cur_submeshes && !mHasDegenerate; ++j)// <FS:Beq> make has_degenerate a member 
 				{ //for each submesh (face), add triangles and vertices to current total
 					LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
-					for (S32 k = 0; (k < face.mNumIndices) && !mHasDegenerate; )
+					for (S32 k = 0; (k < face.mNumIndices) && !mHasDegenerate; )// <FS:Beq> make has_degenerate a member 
 					{
 						U16 index_a = face.mIndices[k + 0];
 						U16 index_b = face.mIndices[k + 1];
 						U16 index_c = face.mIndices[k + 2];
-
+						// <FS:Beq> FIRE-23367/23387 - Allow forced empty triangle placeholders created by the LOD processing.
+						//	LLVector4a v1; v1.setMul(face.mPositions[index_a], scale);
+						//	LLVector4a v2; v2.setMul(face.mPositions[index_b], scale);
+						//	LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);
+
+						//	if (ll_is_degenerate(v1, v2, v3))
+						//	{
+						//		mHasDegenerate = true;// <FS:Beq> make has_degenerate a member 
+						//	}
+						//	else
+						//	{
+						//		k += 3;
+						//	}
 						if (index_c == 0 && index_b == 0 && index_a == 0) // test in reverse as 3rd index is less likely to be 0 in a normal case
 						{
 							LL_DEBUGS("MeshValidation") << "Empty placeholder triangle (3 identical index 0 verts) ignored" << LL_ENDL;
@@ -2882,7 +2901,7 @@ void LLModelPreview::updateStatusMessages()
 							LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);
 							if (ll_is_degenerate(v1, v2, v3))
 							{
-								mHasDegenerate = true;
+								mHasDegenerate = true;// <FS:Beq> make has_degenerate a member 
 							}
 						}
 						k += 3;
@@ -2892,7 +2911,7 @@ void LLModelPreview::updateStatusMessages()
 		}
 	}
 
-	// flag degenerates here rather than deferring to a MAV error later
+	// <FS:Beq> flag degenerates here rather than deferring to a MAV error later
 	mFMP->childSetVisible("physics_status_message_text", mHasDegenerate); //display or clear
 	auto degenerateIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon");
 	degenerateIcon->setVisible(mHasDegenerate);
@@ -2903,6 +2922,7 @@ void LLModelPreview::updateStatusMessages()
 		LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Error");
 		degenerateIcon->setImage(img);
 	}
+	// </FS:Beq>
 
 	mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
 
@@ -3072,7 +3092,12 @@ void LLModelPreview::updateStatusMessages()
 			mModelNoErrors = false;
 		}
 	}
-
+	// <FS:Beq> Improve the error checking the TO DO here is no longer applicable but not an FS comment so edited to stop it being picked up
+	//// To do investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics
+	//// current use of has_degenerate won't block upload permanently - later checks will restore the button
+	//if (!mModelNoErrors || mHasDegenerate)
+	//{
+	//	mFMP->childDisable("ok_btn");
 	if (!mModelNoErrors || mHasDegenerate)
 	{
 		mFMP->childDisable("ok_btn");
@@ -3697,7 +3722,7 @@ BOOL LLModelPreview::render()
 	bool textures = mViewOption["show_textures"];
 	bool physics = mViewOption["show_physics"];
 
-	// Extra configurability, to be exposed later as controls?
+	// <FS:Beq> Extra configurability, to be exposed later as controls?
 	static LLCachedControl<LLColor4> canvas_col(gSavedSettings, "MeshPreviewCanvasColor");
 	static LLCachedControl<LLColor4> edge_col(gSavedSettings, "MeshPreviewEdgeColor");
 	static LLCachedControl<LLColor4> base_col(gSavedSettings, "MeshPreviewBaseColor");
@@ -3710,12 +3735,16 @@ BOOL LLModelPreview::render()
 	static LLCachedControl<LLColor4> deg_fill_col(gSavedSettings, "MeshPreviewDegenerateFillColor");	
 	static LLCachedControl<F32> deg_edge_width(gSavedSettings, "MeshPreviewDegenerateEdgeWidth");
 	static LLCachedControl<F32> deg_point_size(gSavedSettings, "MeshPreviewDegeneratePointSize");
-
+	// </FS:Beq>
 	S32 width = getWidth();
 	S32 height = getHeight();
 
 	LLGLSUIDefault def;
 	LLGLDisable no_blend(GL_BLEND);
+// <FS:Beq> Clean up render of mesh preview
+//	LLGLEnable blend(GL_BLEND);
+//	gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
+// </FS:Beq> 
 
 	LLGLEnable cull(GL_CULL_FACE);
 	LLGLDepthTest depth(GL_TRUE);
@@ -3735,7 +3764,8 @@ BOOL LLModelPreview::render()
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		gGL.pushMatrix();
 		gGL.loadIdentity();
-
+		// <FS:Beq> uploader improvements
+		//gGL.color4f(0.169f, 0.169f, 0.169f, 1.f);
 		gGL.color4fv(static_cast<LLColor4>(canvas_col).mV);
 		gl_rect_2d_simple( width, height );
 
@@ -3884,7 +3914,11 @@ BOOL LLModelPreview::render()
 	stop_glerror();
 
 	gGL.pushMatrix();
+	// <FS:Beq> mesh uploader improvements configurable brightness
+	//const F32 BRIGHTNESS = 0.9f;
+	//gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS);
 	gGL.color4fv(edge_col().mV);
+	// </FS:Beq>
 
 	const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
 
@@ -3969,12 +4003,19 @@ BOOL LLModelPreview::render()
 						}
 						else
 						{
+						// <FS:Beq> improved mesh uploader
+						//	gGL.diffuseColor4f(1,1,1,1);
 							gGL.diffuseColor4fv(static_cast<LLColor4>(base_col).mV);
+						// </FS:Beq>
+
 						}
 
 						buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
 						gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+						// <FS:Beq> improved mesh uploader
+						//gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
 						gGL.diffuseColor4fv(static_cast<LLColor4>(edge_col).mV);
+						// </FS:Beq> 
 						if (edges)
 						{
 							glLineWidth(edge_width);
@@ -3989,10 +4030,25 @@ BOOL LLModelPreview::render()
 
 			if (physics)
 			{
+				// <FS:Beq> model upload improvements - use the settings
+				////Vector4a physicsFillColour(0.4, 0.4, 0.4, 0.4);
+				//const LLColor4 physicsFillColour(0.0, 0.5, 1.0, 0.5);
+				////LLVector4a physicsEdgeColour(1.0, 1.0, 0.0, 1.0);
+				//const LLColor4 physicsEdgeColour=physicsFillColour*0.5;
+				//const LLColor4 degenerateFill(1.0, 0.0, 0.0, 0.5);
+				//const LLColor4 degenerateEdge(1.0,0.0,0.0,1.0);
+				// </FS:Beq> 
+
 				glClear(GL_DEPTH_BUFFER_BIT);
+				//<FS:Beq> refactor to remove silly variable names
+				//				for (U32 i = 0; i < 2; i++)
 				for (U32 pass = 0; pass < 2; pass++)
+				//</FS:Beq>
 				{
+					//<FS:Beq> refactor to remove silly variable names
+					//if (i == 0)
 					if (pass == 0)
+					//</FS:Beq>
 					{ //depth only pass
 						gGL.setColorMask(false, false);
 					}
@@ -4002,7 +4058,10 @@ BOOL LLModelPreview::render()
 					}
 
 					//enable alpha blending on second pass but not first pass
+					//<FS:Beq> refactor to remove silly variable names
+					//LLGLState blend(GL_BLEND, i);
 					LLGLState blend(GL_BLEND, pass);
+					//</FS:Beq>
 
 					gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
 
@@ -4106,11 +4165,16 @@ BOOL LLModelPreview::render()
 						gGL.popMatrix();
 					}
 
-					// only do this if mDegenerate was set in the preceding mesh checks [Check this if the ordering ever breaks]
+					//<FS:Beq> refactor to remove silly variable names
+					// also only do this if mDegenerate was set in the preceding mesh checks [Check this if the ordering ever breaks]
+					//if (i > 0)
 					if (pass > 0 && mHasDegenerate)
+					//</FS:Beq>
 					{
 						glLineWidth(deg_edge_width);
 						glPointSize(deg_point_size);
+// <FS:Beq> This single line is why the degenerate triangles display has been crap forever. 
+// 						gPipeline.enableLightsFullbright(LLColor4::white);
 						//show degenerate triangles
 						LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
 						LLGLDisable cull(GL_CULL_FACE);
@@ -4148,10 +4212,13 @@ BOOL LLModelPreview::render()
 									}
 
 									auto num_degenerate = 0;
+									//<FS:Beq> More nested i variable silliness
+									//									for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
 									auto num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
 									for (U32 v = 0; v < num_models; ++v)
 									{
 										LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][v];
+									//</FS:Beq>
 										if(buffer->getNumVerts() < 3)continue;
 
 										buffer->setBuffer(type_mask & buffer->getTypeMask());
@@ -4164,6 +4231,7 @@ BOOL LLModelPreview::render()
 										buffer->getIndexStrider(idx, 0);
 
 										LLVector4a v1, v2, v3;
+										//<FS:Beq> rename inner most i to avoid merge confusion
 										for (U32 indices_offset = 0; indices_offset < buffer->getNumIndices(); indices_offset += 3)
 										{
 											v1.setMul(pos[*idx++], scale);
@@ -4274,6 +4342,8 @@ BOOL LLModelPreview::render()
 							}
 						
 							buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
+							// <FS:Beq> configurable colour and width
+							//gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
 
 							if (edges)
 							{
@@ -4284,6 +4354,7 @@ BOOL LLModelPreview::render()
 								glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 								glLineWidth(1.f);
 							}
+							// </FS:Beq>
 						}
 					}
 				}
@@ -4341,9 +4412,11 @@ void LLModelPreview::rotate(F32 yaw_radians, F32 pitch_radians)
 void LLModelPreview::zoom(F32 zoom_amt)
 {
 	F32 new_zoom = mCameraZoom+zoom_amt;
-	// TODO: stop clamping in render
+	// <FS:Beq> add configurable zoom TODO: stop clamping in render
+	// mCameraZoom = llclamp(new_zoom, 1.f, 10.f);
 	static LLCachedControl<F32> zoom_limit(gSavedSettings, "MeshPreviewZoomLimit");
 	mCameraZoom	= llclamp(new_zoom, 1.f, zoom_limit());
+	// </FS:Beq>
 }
 
 void LLModelPreview::pan(F32 right, F32 up)
@@ -4549,6 +4622,12 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
 		childSetTextArg("server_weight", "[SIM]", tbd);
 		childSetTextArg("physics_weight", "[PH]", tbd);
 		childSetTextArg("upload_fee", "[FEE]", tbd);
+		// <FS:Beq> add extended info fields
+		//childSetTextArg("price_breakdown", "[STREAMING]", dashes);
+		//childSetTextArg("price_breakdown", "[PHYSICS]", dashes);
+		//childSetTextArg("price_breakdown", "[INSTANCES]", dashes);
+		//childSetTextArg("price_breakdown", "[TEXTURES]", dashes);
+		//childSetTextArg("price_breakdown", "[MODEL]", dashes);
 		std::string dashes = hasString("--") ? getString("--") : "--";
 		childSetTextArg("price_breakdown", "[STREAMING]", dashes);
 		childSetTextArg("price_breakdown", "[PHYSICS]", dashes);
@@ -4558,6 +4637,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
 		childSetTextArg("physics_breakdown", "[PCH]", dashes);
 		childSetTextArg("physics_breakdown", "[PM]", dashes);
 		childSetTextArg("physics_breakdown", "[PHU]", dashes);
+		// </FS:Beq>
 	}
 }
 
@@ -4607,7 +4687,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
 	childSetTextArg("price_breakdown", "[INSTANCES]", llformat("%d", result["upload_price_breakdown"]["mesh_instance"].asInteger()));
 	childSetTextArg("price_breakdown", "[TEXTURES]", llformat("%d", result["upload_price_breakdown"]["texture"].asInteger()));
 	childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger()));
-
+//<FS:Beq> Updates for enhanced Mesh feedback at upload
 	childSetTextArg("physics_breakdown", "[PCH]", llformat("%0.3f", result["model_physics_cost"]["hull"].asReal()));
 	childSetTextArg("physics_breakdown", "[PM]", llformat("%0.3f", result["model_physics_cost"]["mesh"].asReal()));
 	childSetTextArg("physics_breakdown", "[PHU]", llformat("%0.3f", result["model_physics_cost"]["decomposition"].asReal()));
@@ -4616,7 +4696,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
 	childSetTextArg("streaming_breakdown", "[STR_MED]", llformat("%d", result["streaming_params"]["medium_lod"].asInteger()));
 	childSetTextArg("streaming_breakdown", "[STR_LOW]", llformat("%d", result["streaming_params"]["low_lod"].asInteger()));
 	childSetTextArg("streaming_breakdown", "[STR_LOWEST]", llformat("%d", result["streaming_params"]["lowest_lod"].asInteger()));
-
+//</FS:Beq>
 	childSetVisible("upload_fee", true);
 	childSetVisible("price_breakdown", true);
 	mUploadBtn->setEnabled(isModelUploadAllowed());