Merge branch 'DRTVWR-570-maint-Q' of https://bitbucket.org/lindenlab/viewer

# Conflicts:
#	indra/llcommon/llsdserialize.cpp
#	indra/llmath/llvolume.cpp
#	indra/llmath/llvolume.h
#	indra/newview/llfloateropenobject.cpp
#	indra/newview/llfloateropenobject.h
#	indra/newview/llmaterialmgr.cpp
#	indra/newview/llmeshrepository.cpp
#	indra/newview/llmeshrepository.h
#	indra/newview/skins/default/xui/en/floater_openobject.xml
master
Ansariel 2022-10-01 13:10:39 +02:00
commit 2aceea66ff
21 changed files with 711 additions and 699 deletions

View File

@ -1384,6 +1384,7 @@ Sovereign Engineer
OPEN-343
SL-11625
BUG-229030
SL-14696
SL-14705
SL-14706
SL-14707
@ -1391,6 +1392,7 @@ Sovereign Engineer
SL-14732
SL-15096
SL-16127
SL-18249
SpacedOut Frye
VWR-34
VWR-45

View File

@ -34,6 +34,9 @@
#include <iostream>
#include "apr_base64.h"
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
#else
@ -2128,8 +2131,8 @@ std::string zip_llsd(LLSD& data)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
// free(output);
if( output )
deflateEnd(&strm);
if(output)
free(output);
LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
@ -2153,8 +2156,8 @@ std::string zip_llsd(LLSD& data)
}
else
{
// free(output);
if( output )
deflateEnd(&strm);
if(output)
free(output);
LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
@ -2166,8 +2169,7 @@ std::string zip_llsd(LLSD& data)
std::string result((char*) output, size);
deflateEnd(&strm);
// free(output);
if( output )
if(output)
free(output);
return result;
@ -2178,59 +2180,70 @@ std::string zip_llsd(LLSD& data)
// and deserializes from that copy using LLSDSerialize
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size)
{
U8* result = NULL;
U32 cur_size = 0;
z_stream strm;
const U32 CHUNK = 65536;
U8 *in = new(std::nothrow) U8[size];
std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]);
if (!in)
{
return ZR_MEM_ERROR;
}
is.read((char*) in, size);
is.read((char*) in.get(), size);
U8 out[CHUNK];
return unzip_llsd(data, in.get(), size);
}
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size)
{
U8* result = NULL;
U32 cur_size = 0;
z_stream strm;
constexpr U32 CHUNK = 1024 * 512;
static thread_local std::unique_ptr<U8[]> out;
if (!out)
{
out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);
}
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = size;
strm.next_in = in;
strm.next_in = const_cast<U8*>(in);
S32 ret = inflateInit(&strm);
do
{
strm.avail_out = CHUNK;
strm.next_out = out;
strm.next_out = out.get();
ret = inflate(&strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR)
{
LL_DEBUGS() << "Unzip error: Z_STREAM_ERROR" << LL_ENDL; // <FS>
inflateEnd(&strm);
// free(result);
if( result )
free(result);
delete [] in;
return ZR_DATA_ERROR;
}
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
LL_DEBUGS() << "Unzip error: " << ret << LL_ENDL; // <FS>
{
inflateEnd(&strm);
// free(result);
if( result )
free(result);
return ZR_DATA_ERROR;
}
case Z_STREAM_ERROR:
case Z_BUF_ERROR:
{
inflateEnd(&strm);
free(result);
return ZR_BUFFER_ERROR;
}
case Z_MEM_ERROR:
{
inflateEnd(&strm);
// free(result);
if( result )
free(result);
delete [] in;
return ZR_MEM_ERROR;
break;
}
}
U32 have = CHUNK-strm.avail_out;
@ -2243,21 +2256,18 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
{
free(result);
}
delete[] in;
return ZR_MEM_ERROR;
}
result = new_result;
memcpy(result+cur_size, out, have);
memcpy(result+cur_size, out.get(), have);
cur_size += have;
} while (ret == Z_OK);
} while (ret == Z_OK && ret != Z_STREAM_END);
inflateEnd(&strm);
delete [] in;
if (ret != Z_STREAM_END)
{
LL_DEBUGS() << "Unzip error: !Z_STREAM_END" << LL_ENDL; // <FS>
// free(result);
if( result )
free(result);
@ -2266,41 +2276,11 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
//result now points to the decompressed LLSD block
{
std::istringstream istr;
// Since we are using this for meshes, data we are dealing with tend to be large.
// So string can potentially fail to allocate, make sure this won't cause problems
try
{
std::string res_str((char*)result, cur_size);
char* result_ptr = strip_deprecated_header((char*)result, cur_size);
std::string deprecated_header("<? LLSD/Binary ?>");
if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
{
res_str = res_str.substr(deprecated_header.size() + 1, cur_size);
}
cur_size = res_str.size();
istr.str(res_str);
}
#ifdef LL_WINDOWS
catch (std::length_error)
{
// free(result);
if( result )
free(result);
return ZR_SIZE_ERROR;
}
#endif
catch (std::bad_alloc&)
{
// free(result);
if( result )
free(result);
return ZR_MEM_ERROR;
}
if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH))
boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size);
if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))
{
// free(result);
if( result )
@ -2314,41 +2294,169 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
free(result);
return ZR_OK;
}
// </FS:Beq pp Rye>
//This unzip function will only work with a gzip header and trailer - while the contents
//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
//and trailers are different for the formats.
U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, std::istream& is, S32 size)
{
// <FS:Beq pp Rye> Add non-allocating variants of unzip_llsd
// if (size == 0)
// {
// LL_WARNS() << "No data to unzip." << LL_ENDL;
// return NULL;
// }
// U8* result = NULL;
// U32 cur_size = 0;
// z_stream strm;
// const U32 CHUNK = 0x4000;
// U8 *in = new(std::nothrow) U8[size];
// if (in == NULL)
// {
// LL_WARNS() << "Memory allocation failure." << LL_ENDL;
// return NULL;
// }
// is.read((char*) in, size);
// U8 out[CHUNK];
// strm.zalloc = Z_NULL;
// strm.zfree = Z_NULL;
// strm.opaque = Z_NULL;
// strm.avail_in = size;
// strm.next_in = in;
// valid = true; // <FS:ND/> Default is all okay.
// S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
// do
// {
// strm.avail_out = CHUNK;
// strm.next_out = out;
// ret = inflate(&strm, Z_NO_FLUSH);
// if (ret == Z_STREAM_ERROR)
// {
// inflateEnd(&strm);
// // free(result);
// if( result )
// free(result);
// delete [] in;
// in = NULL; result = NULL;// <FS:ND> Or we get a double free aftr the while loop ...
// valid = false;
// }
// switch (ret)
// {
// case Z_NEED_DICT:
// ret = Z_DATA_ERROR;
// case Z_DATA_ERROR:
// case Z_MEM_ERROR:
// inflateEnd(&strm);
// // free(result);
// if( result )
// free(result);
// delete [] in;
// valid = false;
// in = NULL; result = NULL;// <FS:ND> Or we get a double free aftr the while loop ...
// break;
// }
// if( valid ) {// <FS:ND> in case this stream is invalid, do not pass the already freed buffer to realloc.
// U32 have = CHUNK-strm.avail_out;
// U8* new_result = (U8*) realloc(result, cur_size + have);
// if (new_result == NULL)
// {
// LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
// << " bytes; requested " << cur_size + have
// << " bytes; total syze: ." << size << " bytes."
// << LL_ENDL;
// inflateEnd(&strm);
// if (result)
// {
// free(result);
// }
// delete[] in;
// valid = false;
// return NULL;
// }
// result = new_result;
// memcpy(result+cur_size, out, have);
// cur_size += have;
// } // </FS:ND>
// } while (ret == Z_OK);
// inflateEnd(&strm);
// delete [] in;
// if (ret != Z_STREAM_END)
// {
// // <FS:ND> result might have been freed above. And calling free with a null pointer is not defined.
// // free(result);
// if( result )
// free(result);
// // </FS:ND>
// valid = false;
// return NULL;
// }
// //result now points to the decompressed LLSD block
// {
// outsize= cur_size;
// valid = true;
// }
// return result;
// }
if (size == 0)
{
LL_WARNS() << "No data to unzip." << LL_ENDL;
return nullptr;
}
std::unique_ptr<U8[]> in;
try
{
in = std::make_unique<U8[]>(size);
}
catch (const std::bad_alloc&)
{
LL_WARNS() << "Memory allocation failure." << LL_ENDL;
return nullptr;
}
is.read((char*)in.get(), size);
return unzip_llsdNavMesh(valid, outsize, in.get(), size);
}
U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8* in, S32 size)
{
if (size == 0)
{
LL_WARNS() << "No data to unzip." << LL_ENDL;
return NULL;
return nullptr;
}
U8* result = NULL;
U8* result = nullptr;
U32 cur_size = 0;
z_stream strm;
const U32 CHUNK = 0x4000;
U8 *in = new(std::nothrow) U8[size];
if (in == NULL)
{
LL_WARNS() << "Memory allocation failure." << LL_ENDL;
return NULL;
}
is.read((char*) in, size);
U8 out[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = size;
strm.next_in = in;
strm.next_in = const_cast<U8*>(in);
valid = true; // <FS:ND/> Default is all okay.
S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP);
do
{
strm.avail_out = CHUNK;
@ -2357,36 +2465,27 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
if (ret == Z_STREAM_ERROR)
{
inflateEnd(&strm);
// free(result);
if( result )
free(result);
delete [] in;
in = NULL; result = NULL;// <FS:ND> Or we get a double free aftr the while loop ...
valid = false;
free(result);
return nullptr;
}
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
[[fallthrough]];
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
// free(result);
if( result )
free(result);
delete [] in;
free(result);
valid = false;
in = NULL; result = NULL;// <FS:ND> Or we get a double free aftr the while loop ...
break;
return nullptr;
}
if( valid ) {// <FS:ND> in case this stream is invalid, do not pass the already freed buffer to realloc.
U32 have = CHUNK-strm.avail_out;
U32 have = CHUNK - strm.avail_out;
U8* new_result = (U8*) realloc(result, cur_size + have);
if (new_result == NULL)
U8* new_result = (U8*)realloc(result, cur_size + have);
if (!new_result)
{
LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
<< " bytes; requested " << cur_size + have
@ -2397,40 +2496,50 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
{
free(result);
}
delete[] in;
valid = false;
return NULL;
return nullptr;
}
result = new_result;
memcpy(result+cur_size, out, have);
memcpy(result + cur_size, out, have);
cur_size += have;
} // </FS:ND>
} while (ret == Z_OK);
inflateEnd(&strm);
delete [] in;
if (ret != Z_STREAM_END)
{
// <FS:ND> result might have been freed above. And calling free with a null pointer is not defined.
// free(result);
if( result )
free(result);
// </FS:ND>
free(result);
valid = false;
return NULL;
return nullptr;
}
//result now points to the decompressed LLSD block
{
outsize= cur_size;
valid = true;
outsize = cur_size;
valid = true;
}
return result;
}
// </FS:Beq pp Rye>
char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size)
{
const char* deprecated_header = "<? LLSD/Binary ?>";
constexpr size_t deprecated_header_size = 17;
if (cur_size > deprecated_header_size
&& memcmp(in, deprecated_header, deprecated_header_size) == 0)
{
in = in + deprecated_header_size;
cur_size = cur_size - deprecated_header_size;
if (header_size)
{
*header_size = deprecated_header_size + 1;
}
}
return in;
}

View File

@ -858,9 +858,12 @@ public:
ZR_SIZE_ERROR,
ZR_DATA_ERROR,
ZR_PARSE_ERROR,
ZR_BUFFER_ERROR,
ZR_VERSION_ERROR
} EZipRresult;
// return OK or reason for failure
static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size);
static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);
};
//dirty little zip functions -- yell at davep
@ -868,4 +871,9 @@ LL_COMMON_API std::string zip_llsd(LLSD& data);
LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size);
// <FS:Beq pp Rye> Add non-allocating variants of unzip_llsd
LL_COMMON_API U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8* in, S32 size);
// returns a pointer to the array or past the array if the deprecated header exists
LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr);
#endif // LL_LLSDSERIALIZE_H

View File

@ -2411,13 +2411,12 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL;
return false;
}
// <FS:Beq pp Rye> Add non-allocating variants of of unpackVolumeFaces
return unpackVolumeFacesInternal(mdl);
}
bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size)
{
//input stream is now pointing at a zlib compressed block of LLSD
//input data is now pointing at a zlib compressed block of LLSD
//decompress block
LLSD mdl;
U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size);
@ -2431,7 +2430,6 @@ bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size)
bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
{
// </FS:Beq pp Rye>
{
U32 face_count = mdl.size();

View File

@ -1108,14 +1108,12 @@ protected:
BOOL generate();
void createVolumeFaces();
public:
virtual bool unpackVolumeFaces(std::istream& is, S32 size);
// <FS:Beq pp Rye> Add non-allocating variants of of unpackVolumeFaces
bool unpackVolumeFaces(std::istream& is, S32 size);
bool unpackVolumeFaces(U8* in_data, S32 size);
private:
bool unpackVolumeFacesInternal(const LLSD& mdl);
public:
// </FS:Beq pp Rye>
virtual void setMeshAssetLoaded(BOOL loaded);
virtual BOOL isMeshAssetLoaded();

View File

@ -1416,6 +1416,16 @@ LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin):
fromLLSD(skin);
}
LLMeshSkinInfo::LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& skin) :
mMeshID(mesh_id),
mPelvisOffset(0.0),
mLockScaleIfJointPosition(false),
mInvalidJointsScrubbed(false),
mJointNumsInitialized(false)
{
fromLLSD(skin);
}
void LLMeshSkinInfo::fromLLSD(LLSD& skin)
{
if (skin.has("joint_names"))

View File

@ -43,12 +43,13 @@ class domMesh;
#define MAX_MODEL_FACES 8
LL_ALIGN_PREFIX(16)
class LLMeshSkinInfo
class LLMeshSkinInfo : public LLRefCount
{
LL_ALIGN_NEW
public:
LLMeshSkinInfo();
LLMeshSkinInfo(LLSD& data);
LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const;
void updateHash();

View File

@ -25,6 +25,17 @@
/*[EXTRA_CODE_HERE]*/
// Inputs
VARYING vec4 vary_HazeColor;
VARYING float vary_LightNormPosDot;
uniform sampler2D rainbow_map;
uniform sampler2D halo_map;
uniform float moisture_level;
uniform float droplet_radius;
uniform float ice_level;
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_data[3];
#else
@ -35,11 +46,34 @@ out vec4 frag_data[3];
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
VARYING vec4 vary_HazeColor;
vec3 rainbow(float d)
{
// 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec
// Rainbox tex is mapped with REPEAT, so -.75 as tex coord is same as 0.25. -0.825 -> 0.175. etc.
// SL-13629
// Unfortunately the texture is inverted, so we need to invert the y coord, but keep the 'interesting'
// part within the same 0.175..0.250 range, i.e. d = (1 - d) - 1.575
d = clamp(-0.575 - d, 0.0, 1.0);
// With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
// So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
// space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
float interior_coord = max(0.0, d - 0.25) * 4.2857;
d = clamp(d, 0.0, 0.25) + interior_coord;
float rad = (droplet_radius - 5.0f) / 1024.0f;
return pow(texture2D(rainbow_map, vec2(rad+0.5, d)).rgb, vec3(1.8)) * moisture_level;
}
vec3 halo22(float d)
{
d = clamp(d, 0.1, 1.0);
float v = sqrt(clamp(1 - (d * d), 0, 1));
return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
}
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light);
vec3 srgb_to_linear(vec3 c);
void main()
{
@ -48,14 +82,18 @@ void main()
// the fragment) if the sky wouldn't show up because the clouds
// are fully opaque.
vec4 color;
color = vary_HazeColor;
vec4 color = vary_HazeColor;
float rel_pos_lightnorm = vary_LightNormPosDot;
float optic_d = rel_pos_lightnorm;
vec3 halo_22 = halo22(optic_d);
color.rgb += rainbow(optic_d);
color.rgb += halo_22;
color.rgb *= 2.;
color.rgb = scaleSoftClip(color.rgb);
/// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 0.0);
// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 1.0);
frag_data[1] = vec4(0.0,0.0,0.0,0.0);
frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog

View File

@ -33,6 +33,7 @@ ATTRIBUTE vec3 position;
// Output parameters
VARYING vec4 vary_HazeColor;
VARYING float vary_LightNormPosDot;
// Inputs
uniform vec3 camPosLocal;
@ -72,27 +73,29 @@ void main()
vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
// Adj position vector to clamp altitude
if (rel_pos.y > 0)
if (rel_pos.y > 0.)
{
rel_pos *= (max_y / rel_pos.y);
}
if (rel_pos.y < 0)
if (rel_pos.y < 0.)
{
rel_pos *= (-32000. / rel_pos.y);
}
// Can normalize then
vec3 rel_pos_norm = normalize(rel_pos);
// Normalized
vec3 rel_pos_norm = normalize(rel_pos);
float rel_pos_len = length(rel_pos);
float rel_pos_len = length(rel_pos);
// Grab this value and pass to frag shader for rainbows
float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz);
vary_LightNormPosDot = rel_pos_lightnorm_dot;
// Initialize temp variables
vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
vec4 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
@ -112,7 +115,7 @@ void main()
combined_haze = exp(-combined_haze * density_dist);
// Compute haze glow
float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
float haze_glow = 1.0 - rel_pos_lightnorm_dot;
// haze_glow is 0 at the sun and increases away from sun
haze_glow = max(haze_glow, .001);
// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
@ -123,30 +126,30 @@ void main()
// Add "minimum anti-solar illumination"
// For sun, add to glow. For moon, remove glow entirely. SL-13768
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
vec4 color =
(blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Haze color above cloud
vec4 color = (blue_horizon * blue_weight * (sunlight + ambient_color)
+ (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Final atmosphere additive
color *= (1. - combined_haze);
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient_color;
tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= max(0.0, (1. - cloud_shadow));
// Haze color below cloud
vec4 additiveColorBelowCloud =
(blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
vec4 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)
+ (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));
// Attenuate cloud color by atmosphere
combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
// At horizon, blend high altitude sky color towards the darker color below the clouds
color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
// Haze color above cloud
vary_HazeColor = color;

View File

@ -1,199 +0,0 @@
/**
* @file class2/deferred/skyF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
uniform mat4 modelview_projection_matrix;
// SKY ////////////////////////////////////////////////////////////////////////
// The vertex shader for creating the atmospheric sky
///////////////////////////////////////////////////////////////////////////////
// Inputs
uniform vec3 camPosLocal;
uniform vec4 lightnorm;
uniform vec4 sunlight_color;
uniform vec4 moonlight_color;
uniform int sun_up_factor;
uniform vec4 ambient_color;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
uniform float cloud_shadow;
uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
uniform vec4 glow;
uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_data[3];
#else
#define frag_data gl_FragData
#endif
VARYING vec3 pos;
/////////////////////////////////////////////////////////////////////////
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
uniform sampler2D rainbow_map;
uniform sampler2D halo_map;
uniform float moisture_level;
uniform float droplet_radius;
uniform float ice_level;
vec3 rainbow(float d)
{
// d is the dot product of view and sun directions, so ranging -1.0..1.0
// 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
// Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
// SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
// Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
// interesting range, but in reversed order: i.e. d = (1 - d) - 1.575
d = clamp(-0.575 - d, 0.0, 1.0);
// With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
// So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
// space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
float interior_coord = max(0.0, d - 0.25) * 4.2857;
d = clamp(d, 0.0, 0.25) + interior_coord;
float rad = (droplet_radius - 5.0f) / 1024.0f;
return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
}
vec3 halo22(float d)
{
d = clamp(d, 0.1, 1.0);
float v = sqrt(clamp(1 - (d * d), 0, 1));
return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
}
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light);
void main()
{
// World / view / projection
// Get relative position (offset why?)
vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
// Adj position vector to clamp altitude
if (rel_pos.y > 0.)
{
rel_pos *= (max_y / rel_pos.y);
}
if (rel_pos.y < 0.)
{
rel_pos *= (-32000. / rel_pos.y);
}
// Normalized
vec3 rel_pos_norm = normalize(rel_pos);
float rel_pos_len = length(rel_pos);
// Initialize temp variables
vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
vec4 blue_weight = blue_density / combined_haze;
vec4 haze_weight = haze_density / combined_haze;
// Compute sunlight from rel_pos & lightnorm (for long rays like sky)
float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y);
sunlight *= exp(-light_atten * off_axis);
// Distance
float density_dist = rel_pos_len * density_multiplier;
// Transparency (-> combined_haze)
// ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
// compiler gets confused.
combined_haze = exp(-combined_haze * density_dist);
// Compute haze glow
float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
haze_glow = 1. - haze_glow;
// haze_glow is 0 at the sun and increases away from sun
haze_glow = max(haze_glow, .001);
// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
haze_glow *= glow.x;
// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
haze_glow = pow(haze_glow, glow.z);
// glow.z should be negative, so we're doing a sort of (1 / "angle") function
// Add "minimum anti-solar illumination"
// For sun, add to glow. For moon, remove glow entirely. SL-13768
haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
// Haze color above cloud
vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color)
+ haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color);
// Final atmosphere additive
color *= (1. - combined_haze);
// Increase ambient when there are more clouds
// TODO 9/20: DJH what does this do? max(0,(1-ambient)) will change the color
vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= max(0.0, (1. - cloud_shadow));
// Haze color below cloud
vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient)
+ haze_horizon * haze_weight * (sunlight * haze_glow + ambient);
// Attenuate cloud color by atmosphere
combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
// At horizon, blend high altitude sky color towards the darker color below the clouds
color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
float optic_d = dot(rel_pos_norm, lightnorm.xyz);
vec3 halo_22 = halo22(optic_d);
color.rgb += rainbow(optic_d);
color.rgb += halo_22;
color.rgb *= 2.;
color.rgb = scaleSoftClip(color.rgb);
// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 1.0);
frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0);
frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0); // 1.0 in norm.w masks off fog
}

View File

@ -1,42 +0,0 @@
/**
* @file WLSkyV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
// SKY ////////////////////////////////////////////////////////////////////////
// The vertex shader for creating the atmospheric sky
///////////////////////////////////////////////////////////////////////////////
VARYING vec3 pos;
void main()
{
// World / view / projection
pos = position.xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
}

View File

@ -59,8 +59,6 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key)
{
// <FS:Ansariel> Cinder's fly-out button
//mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this));
//mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this));
//mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit", boost::bind(&LLFloaterOpenObject::onClickReplace, this));
mCommitCallbackRegistrar.add("OpenObject.CopyAction", boost::bind(&LLFloaterOpenObject::onClickCopy, this, _2));
// </FS:Ansariel>
mCommitCallbackRegistrar.add("OpenObject.Cancel", boost::bind(&LLFloaterOpenObject::onClickCancel, this));
@ -260,18 +258,6 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data)
// moveToInventory(false);
// closeFloater();
//}
//
//void LLFloaterOpenObject::onClickMoveAndWear()
//{
// moveToInventory(true, false);
// closeFloater();
//}
//
//void LLFloaterOpenObject::onClickReplace()
//{
// moveToInventory(true, true);
// closeFloater();
//}
// </FS:Ansariel>
void LLFloaterOpenObject::onClickCancel()

View File

@ -64,8 +64,6 @@ protected:
// <FS:Ansariel> Cinder's fly-out button
//void onClickMoveToInventory();
//void onClickMoveAndWear();
//void onClickReplace();
void onClickCopy(const LLSD& value);
// </FS:Ansariel>
void onClickCancel();

View File

@ -429,12 +429,10 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
std::istringstream content_stream(content_string);
const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
LLSD response_data;
U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@ -472,15 +470,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
std::istringstream content_stream(content_string);
const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
LLSD response_data;
// <FS:Beq pp Rye> Use new variant unzip_llsd
// U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
// </FS:Beq pp Rye>
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@ -544,12 +537,10 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size());
std::istringstream content_stream(content_string);
const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
LLSD response_data;
U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;

File diff suppressed because it is too large Load Diff

View File

@ -210,10 +210,8 @@ public:
LLCondition* mSignal;
//map of known mesh headers
typedef std::map<LLUUID, LLSD> mesh_header_map;
typedef boost::unordered_map<LLUUID, std::pair<U32, LLSD>> mesh_header_map; // pair is header_size and data
mesh_header_map mMeshHeader;
std::map<LLUUID, U32> mMeshHeaderSize;
class HeaderRequest : public RequestStats
{
@ -283,10 +281,13 @@ public:
};
//set of requested skin info
std::set<UUIDBasedRequest> mSkinRequests;
std::deque<UUIDBasedRequest> mSkinRequests;
// list of completed skin info requests
std::list<LLMeshSkinInfo> mSkinInfoQ;
std::deque<LLMeshSkinInfo*> mSkinInfoQ;
// list of skin info requests that have failed or are unavailaibe
std::deque<UUIDBasedRequest> mSkinUnavailableQ;
//set of requested decompositions
std::set<UUIDBasedRequest> mDecompositionRequests;
@ -304,13 +305,13 @@ public:
std::queue<LODRequest> mLODReqQ;
//queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD)
std::queue<LODRequest> mUnavailableQ;
std::deque<LODRequest> mUnavailableQ;
//queue of successfully loaded meshes
std::queue<LoadedMesh> mLoadedQ;
std::deque<LoadedMesh> mLoadedQ;
//map of pending header requests and currently desired LODs
typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map;
typedef boost::unordered_map<LLUUID, std::vector<S32> > pending_lod_map;
pending_lod_map mPendingLOD;
// llcorehttp library interface objects.
@ -360,7 +361,7 @@ public:
//send request for skin info, returns true if header info exists
// (should hold onto mesh_id and try again later if header info does not exist)
bool fetchMeshSkinInfo(const LLUUID& mesh_id);
bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);
//send request for decomposition, returns true if header info exists
// (should hold onto mesh_id and try again later if header info does not exist)
@ -599,18 +600,20 @@ public:
void shutdown();
S32 update();
void unregisterMesh(LLVOVolume* volume);
//mesh management functions
S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
void notifyLoadedMeshes();
void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
void notifySkinInfoReceived(LLMeshSkinInfo& info);
void notifySkinInfoReceived(LLMeshSkinInfo* info);
void notifySkinInfoUnavailable(const LLUUID& info);
void notifyDecompositionReceived(LLModel::Decomposition* info);
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
static S32 getActualMeshLOD(LLSD& header, S32 lod);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);
@ -635,13 +638,13 @@ public:
static void metricsProgress(unsigned int count);
static void metricsUpdate();
typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map;
typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;
mesh_load_map mLoadingMeshes[4];
// <FS:Ansariel> DAE export
LLUUID getCreatorFromHeader(const LLUUID& mesh_id);
typedef std::unordered_map<LLUUID, LLMeshSkinInfo> skin_map;
typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map;
skin_map mSkinMap;
typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map;
@ -652,7 +655,7 @@ public:
std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
//list of mesh ids awaiting skin info
typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map;
typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;
skin_load_map mLoadingSkins;
//list of mesh ids that need to send skin info fetch requests
@ -677,6 +680,8 @@ public:
std::vector<LLMeshUploadThread*> mUploadWaitList;
LLPhysicsDecomp* mDecompThread;
LLFrameTimer mSkinInfoCullTimer;
class inventory_data
{

View File

@ -1438,7 +1438,8 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par
mHaveInventory(FALSE),
mIsInventoryEmpty(TRUE),
mInventoryNeedsUpdate(FALSE),
mInventoryViewModel(p.name)
mInventoryViewModel(p.name),
mShowRootFolder(p.show_root_folder)
{
// Setup context menu callbacks
mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2));
@ -1710,15 +1711,23 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root
// </FS:Ansariel>
LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p);
new_folder->addToFolder(mFolders);
new_folder->toggleOpen();
if (mShowRootFolder)
{
new_folder->addToFolder(mFolders);
new_folder->toggleOpen();
}
if (!contents.empty())
{
createViewsForCategory(&contents, inventory_root, new_folder);
createViewsForCategory(&contents, inventory_root, mShowRootFolder ? new_folder : mFolders);
}
// Refresh for label to add item count
new_folder->refresh();
if (mShowRootFolder)
{
// Refresh for label to add item count
new_folder->refresh();
}
}
}

View File

@ -48,8 +48,14 @@ class LLViewerObject;
class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener
{
public:
// dummy param block for template registration purposes
struct Params : public LLPanel::Params {};
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Optional<bool> show_root_folder;
Params()
: show_root_folder("show_root_folder", true)
{}
};
LLPanelObjectInventory(const Params&);
virtual ~LLPanelObjectInventory();
@ -113,6 +119,7 @@ private:
BOOL mIsInventoryEmpty; // 'Empty' label
BOOL mInventoryNeedsUpdate; // for idle, set on changed callback
LLFolderViewModelInventory mInventoryViewModel;
bool mShowRootFolder;
};
#endif // LL_LLPANELOBJECTINVENTORY_H

View File

@ -245,6 +245,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mColorChanged = FALSE;
mSpotLightPriority = 0.f;
mSkinInfoFailed = false;
mSkinInfo = NULL;
mMediaImplList.resize(getNumTEs());
mLastFetchedMediaVersion = -1;
mServerDrawableUpdateCount = 0;
@ -263,6 +266,8 @@ LLVOVolume::~LLVOVolume()
delete mVolumeImpl;
mVolumeImpl = NULL;
gMeshRepo.unregisterMesh(this);
if(!mMediaImplList.empty())
{
for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
@ -1254,6 +1259,12 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
// if it's a mesh
if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{
if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID())
{
mSkinInfo = NULL;
mSkinInfoFailed = false;
}
if (!getVolume()->isMeshAssetLoaded())
{
//load request not yet issued, request pipeline load this mesh
@ -1265,6 +1276,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
}
}
if (!mSkinInfo && !mSkinInfoFailed)
{
const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this);
if (skin_info)
{
notifySkinInfoLoaded(skin_info);
}
}
}
else // otherwise is sculptie
{
@ -1317,6 +1336,9 @@ void LLVOVolume::updateSculptTexture()
{
mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
}
mSkinInfoFailed = false;
mSkinInfo = NULL;
}
else
{
@ -1371,6 +1393,20 @@ void LLVOVolume::notifyMeshLoaded()
updateVisualComplexity();
}
void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin)
{
mSkinInfoFailed = false;
mSkinInfo = skin;
notifyMeshLoaded();
}
void LLVOVolume::notifySkinInfoUnavailable()
{
mSkinInfoFailed = true;
mSkinInfo = nullptr;
}
// sculpt replaces generate() for sculpted surfaces
void LLVOVolume::sculpt()
{
@ -3847,7 +3883,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const
{
if (getVolume())
{
return gMeshRepo.getSkinInfo(getMeshID(), this);
return mSkinInfo;
}
else
{

View File

@ -357,6 +357,8 @@ public:
void updateVisualComplexity();
void notifyMeshLoaded();
void notifySkinInfoLoaded(const LLMeshSkinInfo* skin);
void notifySkinInfoUnavailable();
// Returns 'true' iff the media data for this object is in flight
bool isMediaDataBeingFetched() const;
@ -445,6 +447,8 @@ private:
LLPointer<LLRiggedVolume> mRiggedVolume;
bool mSkinInfoFailed;
LLConstPointer<LLMeshSkinInfo> mSkinInfo;
// statics
public:
static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop

View File

@ -308,12 +308,12 @@ void LLLocalMeshObject::attachSkinInfo()
auto skinmap_seeker = gMeshRepo.mSkinMap.find(mSculptID);
if (skinmap_seeker == gMeshRepo.mSkinMap.end())
{
gMeshRepo.mSkinMap[mSculptID] = mMeshSkinInfo;
gMeshRepo.mSkinMap[mSculptID] = &mMeshSkinInfo;
}
else
{
// NOTE: seems necessary, not tested without.
skinmap_seeker->second = mMeshSkinInfo;
skinmap_seeker->second = &mMeshSkinInfo;
}
}