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" |