diff options
41 files changed, 1422 insertions, 459 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 82f0b19be1..e355dcabab 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 25b29ac1a8..eea7c977fb 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 03b893de29..5af1122451 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 d5f0b81830..b508705759 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 0d7ba15b12..43992d51cb 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 6c0895512e..a9f22193f8 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 24bd3299f1..3740b1a742 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 73f63458a3..f41f4b7382 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 b08c5dd295..28a38d4390 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 ea2df4b51a..d9f021b114 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 7a6b40006b..f377685045 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 1e0693d19f..25ff958107 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 32aab152a3..1dd29bfc70 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 ea2df4b51a..0000000000 --- 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 c2d05c601a..0000000000 --- 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 cc921f23d7..08b16d787f 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 0876c3fd99..b6d67899f8 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 6e78ea6bbe..35712163eb 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 a808cc47a2..cdd2bcf8e3 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 dc6a33d0ab..186bf114d1 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 4223e9a784..fcf8b084c5 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 ada0dcf569..c7fab2573f 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 3aa525724e..fd3af4152e 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 7792b3fb40..34fda49375 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 c0758fa92d..2b87c27fcf 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 f135fcbed6..64af6c2157 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 0000000000..8e8fc9dd25 --- /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 0000000000..2a3a14bbee --- /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 b45d1aa3a6..ba48ad4517 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 22d5f18e3d..bb04973164 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 70b1809033..a5b59e8281 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 44f46b8c0f..e417343bec 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 8e4e6b5b07..b946dbbd0f 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 7c4a4c13ba..45277265df 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 029811886d..fc00f0c0d0 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 82a29bbbe9..d18e1de60c 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 074c1742e2..0cf3fde562 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 4b312c6ce7..03af348a8d 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 0efb6c6e90..941ba3bfea 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 928ca6d8d0..9ecab1a356 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 ca9579284b..e0d9f3f714 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"  | 
