diff options
| author | Brad Linden <brad@lindenlab.com> | 2024-06-12 10:31:27 -0700 | 
|---|---|---|
| committer | Brad Linden <brad@lindenlab.com> | 2024-06-12 10:31:27 -0700 | 
| commit | d12c897bfc77a800fcec5e22a21c9d0344b0d0bc (patch) | |
| tree | 18752bdf92b12fce68642c94acec2d78b9c43fbe /indra | |
| parent | 9775d7ea10ff87d913b1ba361a9204f961cd9c3f (diff) | |
| parent | f0de2ba6340e0d540aa70ac0086defde52cf60af (diff) | |
Merge remote-tracking branch 'origin/project/gltf_development' into brad/maint-a-merge-to-gltf-dev
 # Conflicts:
 #	indra/newview/gltf/primitive.cpp
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llrender/llglslshader.h | 4 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 6 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.h | 6 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 10 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 3 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl | 19 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl | 117 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.cpp | 69 | ||||
| -rw-r--r-- | indra/newview/gltf/asset.h | 23 | ||||
| -rw-r--r-- | indra/newview/gltf/buffer_util.h | 37 | ||||
| -rw-r--r-- | indra/newview/gltf/primitive.cpp | 201 | ||||
| -rw-r--r-- | indra/newview/gltf/primitive.h | 3 | ||||
| -rw-r--r-- | indra/newview/gltfscenemanager.cpp | 70 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.cpp | 10 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml | 9 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml | 202 | 
17 files changed, 604 insertions, 187 deletions
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 3b4224cbfd..9339e7998d 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -328,14 +328,16 @@ public:      // bit 0 = alpha mode blend (1) or opaque (0)      // bit 1 = rigged (1) or static (0)      // bit 2 = unlit (1) or lit (0) +    // bit 3 = single (0) or multi (1) uv coordinates      struct GLTFVariant      {          constexpr static U8 ALPHA_BLEND = 1;          constexpr static U8 RIGGED = 2;          constexpr static U8 UNLIT = 4; +        constexpr static U8 MULTI_UV = 8;      }; -    constexpr static U8 NUM_GLTF_VARIANTS = 8; +    constexpr static U8 NUM_GLTF_VARIANTS = 16;      std::vector<LLGLSLShader> mGLTFVariants; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 51028e5667..cfefde3acc 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1686,7 +1686,7 @@ void LLRender::flush()                  if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)                  { -                    vb->setTexCoordData(mTexcoordsp.get()); +                    vb->setTexCoord0Data(mTexcoordsp.get());                  }                  if (attribute_mask & LLVertexBuffer::MAP_COLOR) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index c3cb015556..634be615e6 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1178,7 +1178,13 @@ void LLShaderMgr::initAttribsAndUniforms()      mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF)      mReservedUniforms.push_back("texture_normal_transform"); // (GLTF)      mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF) +    mReservedUniforms.push_back("texture_occlusion_transform"); // (GLTF)      mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF) +    mReservedUniforms.push_back("base_color_texcoord"); // (GLTF) +    mReservedUniforms.push_back("emissive_texcoord"); // (GLTF) +    mReservedUniforms.push_back("normal_texcoord"); // (GLTF) +    mReservedUniforms.push_back("metallic_roughness_texcoord"); // (GLTF) +    mReservedUniforms.push_back("occlusion_texcoord"); // (GLTF)      mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF) diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 53e3d010db..c00aff3a9a 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -56,7 +56,13 @@ public:          TEXTURE_BASE_COLOR_TRANSFORM,         //  "texture_base_color_transform" (GLTF)          TEXTURE_NORMAL_TRANSFORM,             //  "texture_normal_transform" (GLTF)          TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, //  "texture_metallic_roughness_transform" (GLTF) +        TEXTURE_OCCLUSION_TRANSFORM,          //  "texture_occlusion_transform" (GLTF)          TEXTURE_EMISSIVE_TRANSFORM,           //  "texture_emissive_transform" (GLTF) +        BASE_COLOR_TEXCOORD,                  //  "base_color_texcoord" (GLTF) +        EMISSIVE_TEXCOORD,                    //  "emissive_texcoord" (GLTF) +        NORMAL_TEXCOORD,                      //  "normal_texcoord" (GLTF) +        METALLIC_ROUGHNESS_TEXCOORD,          //  "metallic_roughness_texcoord" (GLTF) +        OCCLUSION_TEXCOORD,                   //  "occlusion_texcoord" (GLTF)          TERRAIN_TEXTURE_TRANSFORMS,           //  "terrain_texture_transforms" (GLTF) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 5bace72ffd..f82ec30242 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1633,7 +1633,7 @@ void LLVertexBuffer::setPositionData(const LLVector4a* data)      flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data, mMappedData);  } -void LLVertexBuffer::setTexCoordData(const LLVector2* data) +void LLVertexBuffer::setTexCoord0Data(const LLVector2* data)  {  #if !LL_DARWIN      llassert(sGLRenderBuffer == mGLBuffer); @@ -1641,6 +1641,14 @@ void LLVertexBuffer::setTexCoordData(const LLVector2* data)      flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data, mMappedData);  } +void LLVertexBuffer::setTexCoord1Data(const LLVector2* data) +{ +#if !LL_DARWIN +    llassert(sGLRenderBuffer == mGLBuffer); +#endif +    flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + sTypeSize[TYPE_TEXCOORD1] * getNumVerts() - 1, (U8*)data, mMappedData); +} +  void LLVertexBuffer::setColorData(const LLColor4U* data)  {  #if !LL_DARWIN diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 94339191a4..66a7f2bf26 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -196,7 +196,8 @@ public:      void setTangentData(const LLVector4a* data);      void setWeight4Data(const LLVector4a* data);      void setJointData(const U64* data); -    void setTexCoordData(const LLVector2* data); +    void setTexCoord0Data(const LLVector2* data); +    void setTexCoord1Data(const LLVector2* data);      void setColorData(const LLColor4U* data);      void setIndexData(const U16* data);      void setIndexData(const U32* data); diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl index d71a3fad99..789c00259b 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessF.glsl @@ -37,8 +37,8 @@ uniform sampler2D emissiveMap;  uniform vec3 emissiveColor;  in vec3 vary_position;  in vec4 vertex_color; -in vec2 base_color_texcoord; -in vec2 emissive_texcoord; +in vec2 base_color_uv; +in vec2 emissive_uv;  uniform float minimum_alpha;  void mirrorClip(vec3 pos); @@ -59,8 +59,9 @@ uniform float roughnessFactor;  in vec3 vary_normal;  in vec3 vary_tangent;  flat in float vary_sign; -in vec2 normal_texcoord; -in vec2 metallic_roughness_texcoord; +in vec2 normal_uv; +in vec2 metallic_roughness_uv; +in vec2 occlusion_uv;  #endif  // ================================== @@ -164,7 +165,7 @@ void main()      vec3 pos = vary_position;      mirrorClip(pos); -    vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; +    vec4 basecolor = texture(diffuseMap, base_color_uv.xy).rgba;      basecolor.rgb = srgb_to_linear(basecolor.rgb);      basecolor *= vertex_color; @@ -174,7 +175,7 @@ void main()      }      vec3 emissive = emissiveColor; -    emissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb); +    emissive *= srgb_to_linear(texture(emissiveMap, emissive_uv.xy).rgb);  // ==================================  // ================================== @@ -184,7 +185,7 @@ void main()  // ==================================  #ifndef UNLIT      // from mikktspace.com -    vec3 vNt = texture(normalMap, normal_texcoord.xy).xyz*2.0-1.0; +    vec3 vNt = texture(normalMap, normal_uv.xy).xyz*2.0-1.0;      float sign = vary_sign;      vec3 vN = vary_normal;      vec3 vT = vary_tangent.xyz; @@ -198,8 +199,8 @@ void main()      //   occlusion 1.0      //   roughness 0.0      //   metal     0.0 -    vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb; -    orm.r = texture(occlusionMap, metallic_roughness_texcoord.xy).r; +    vec3 orm = texture(metallicRoughnessMap, metallic_roughness_uv.xy).rgb; +    orm.r = texture(occlusionMap, occlusion_uv.xy).r;      orm.g *= roughnessFactor;      orm.b *= metallicFactor;  #endif diff --git a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl index f123c29101..aac3dc917f 100644 --- a/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl +++ b/indra/newview/app_settings/shaders/class1/gltf/pbrmetallicroughnessV.glsl @@ -33,33 +33,97 @@ uniform mat4 projection_matrix;  uniform mat3 normal_matrix;  uniform mat4 modelview_projection_matrix;  #endif -uniform mat4 texture_matrix0;  uniform vec4[2] texture_base_color_transform;  uniform vec4[2] texture_normal_transform;  uniform vec4[2] texture_metallic_roughness_transform;  uniform vec4[2] texture_emissive_transform; +uniform vec4[2] texture_occlusion_transform;  in vec3 position;  in vec4 diffuse_color;  in vec2 texcoord0; -out vec2 base_color_texcoord; -out vec2 emissive_texcoord; +out vec2 base_color_uv; +out vec2 emissive_uv;  out vec4 vertex_color;  out vec3 vary_position;  #ifndef UNLIT  in vec3 normal;  in vec4 tangent; -out vec2 normal_texcoord; -out vec2 metallic_roughness_texcoord; +out vec2 normal_uv; +out vec2 metallic_roughness_uv; +out vec2 occlusion_uv;  out vec3 vary_tangent;  flat out float vary_sign;  out vec3 vary_normal; -vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);  #endif -vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); +#ifdef MULTI_UV +in vec2 texcoord1; +uniform int base_color_texcoord; +uniform int emissive_texcoord; +#ifndef UNLIT +uniform int normal_texcoord; +uniform int metallic_roughness_texcoord; +uniform int occlusion_texcoord; +#endif +#endif + +vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p) +{ +    texcoord.y = 1.0 - texcoord.y; + +    vec2 Scale = p[0].xy; +    float Rotation = -p[0].z; +    vec2 Offset = vec2(p[0].w, p[1].x); + +    mat3 translation = mat3(1,0,0, 0,1,0, Offset.x, Offset.y, 1); +    mat3 rotation = mat3( +        cos(Rotation), sin(Rotation), 0, +        -sin(Rotation), cos(Rotation), 0, +        0, 0, 1); + +    mat3 scale = mat3(Scale.x,0,0, 0,Scale.y,0, 0,0,1); + +    mat3 matrix = translation * rotation * scale; + +    vec2 uvTransformed = ( matrix * vec3(texcoord.xy, 1) ).xy; + +    uvTransformed.y = 1.0 - uvTransformed.y; + +    return uvTransformed; +} + +#ifndef UNLIT +vec3 gltf_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform) +{ //derived from tangent_space_transform in textureUtilV.glsl +    vec2 weights = vec2(0, 1); + +    // Convert to left-handed coordinate system +    weights.y = -weights.y; + +    // Apply KHR_texture_transform (rotation only) +    float khr_rotation = khr_gltf_transform[0].z; +    mat2 khr_rotation_mat = mat2( +        cos(khr_rotation),-sin(khr_rotation), +        sin(khr_rotation), cos(khr_rotation) +    ); +    weights = khr_rotation_mat * weights; + +    // Convert back to right-handed coordinate system +    weights.y = -weights.y; + +    // Similar to the MikkTSpace-compatible method of extracting the binormal +    // from the normal and tangent, as seen in the fragment shader +    vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz); + +    return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); + +    return vertex_tangent.xyz; +} +#endif +  #ifdef ALPHA_BLEND @@ -136,14 +200,41 @@ void main()      gl_Position = vert;  #endif -    base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); -    emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0); +    vec2 bcuv; +    vec2 emuv; + +#ifdef MULTI_UV +    vec2 uv[2]; +    uv[0] = texcoord0; +    uv[1] = texcoord1; + +    bcuv = uv[base_color_texcoord]; +    emuv = uv[emissive_texcoord]; +#else +    bcuv = texcoord0; +    emuv = texcoord0; +#endif + +    base_color_uv = gltf_texture_transform(bcuv, texture_base_color_transform); +    emissive_uv = gltf_texture_transform(emuv, texture_emissive_transform);  #ifndef UNLIT -    normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0); -    metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_transform, texture_matrix0); +    vec2 normuv; +    vec2 rmuv; +    vec2 ouv; +#ifdef MULTI_UV +    normuv = uv[normal_texcoord]; +    rmuv = uv[metallic_roughness_texcoord]; +    ouv = uv[occlusion_texcoord]; +#else +    normuv = texcoord0; +    rmuv = texcoord0; +    ouv = texcoord0; +#endif +    normal_uv = gltf_texture_transform(normuv, texture_normal_transform); +    metallic_roughness_uv = gltf_texture_transform(rmuv, texture_metallic_roughness_transform); +    occlusion_uv = gltf_texture_transform(ouv, texture_occlusion_transform);  #endif -      #ifndef UNLIT  #ifdef HAS_SKIN @@ -155,7 +246,7 @@ void main()  #endif      n = normalize(n); -    vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform, texture_matrix0)); +    vary_tangent = normalize(gltf_tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform));      vary_sign = tangent.w;      vary_normal = n;  #endif diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index a4efb25860..21be69aae2 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -45,7 +45,8 @@ namespace LL      namespace GLTF      {          static std::unordered_set<std::string> ExtensionsSupported = { -            "KHR_materials_unlit" +            "KHR_materials_unlit", +            "KHR_texture_transform"          };          Material::AlphaMode gltf_alpha_mode_to_enum(const std::string& alpha_mode) @@ -906,6 +907,25 @@ void Material::TextureInfo::serialize(object& dst) const  {      write(mIndex, "index", dst, INVALID_INDEX);      write(mTexCoord, "texCoord", dst, 0); +    write_extensions(dst, &mTextureTransform, "KHR_texture_transform"); +} + +S32 Material::TextureInfo::getTexCoord() const +{ +    if (mTextureTransform.mPresent && mTextureTransform.mTexCoord != INVALID_INDEX) +    { +        return mTextureTransform.mTexCoord; +    } +    return mTexCoord; +} + +bool Material::isMultiUV() const +{ +    return mPbrMetallicRoughness.mBaseColorTexture.getTexCoord() != 0 || +        mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord() != 0 || +        mNormalTexture.getTexCoord() != 0 || +        mOcclusionTexture.getTexCoord() != 0 || +        mEmissiveTexture.getTexCoord() != 0;  }  const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src) @@ -914,6 +934,7 @@ const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)      {          copy(src, "index", mIndex);          copy(src, "texCoord", mTexCoord); +        copy_extensions(src, "KHR_texture_transform", &mTextureTransform);      }      return *this; @@ -931,17 +952,16 @@ bool Material::TextureInfo::operator!=(const Material::TextureInfo& rhs) const  void Material::OcclusionTextureInfo::serialize(object& dst) const  { -    write(mIndex, "index", dst, INVALID_INDEX); -    write(mTexCoord, "texCoord", dst, 0); +    TextureInfo::serialize(dst);      write(mStrength, "strength", dst, 1.f);  }  const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src)  { +    TextureInfo::operator=(src); +      if (src.is_object())      { -        copy(src, "index", mIndex); -        copy(src, "texCoord", mTexCoord);          copy(src, "strength", mStrength);      } @@ -950,13 +970,13 @@ const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(  void Material::NormalTextureInfo::serialize(object& dst) const  { -    write(mIndex, "index", dst, INVALID_INDEX); -    write(mTexCoord, "texCoord", dst, 0); +    TextureInfo::serialize(dst);      write(mScale, "scale", dst, 1.f);  }  const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src)  { +    TextureInfo::operator=(src);      if (src.is_object())      {          copy(src, "index", mIndex); @@ -1015,6 +1035,41 @@ void Material::Unlit::serialize(object& dst) const      // no members and object has already been created, nothing to do  } +void TextureTransform::getPacked(F32* packed) const +{ +    packed[0] = mScale.x; +    packed[1] = mScale.y; +    packed[2] = mRotation; +    packed[3] = mOffset.x; +    packed[4] = mOffset.y; + +    packed[5] = packed[6] = packed[7] = 0.f; +} + + +const TextureTransform& TextureTransform::operator=(const Value& src) +{ +    mPresent = true; +    if (src.is_object()) +    { +        copy(src, "offset", mOffset); +        copy(src, "rotation", mRotation); +        copy(src, "scale", mScale); +        copy(src, "texCoord", mTexCoord); +    } + +    return *this; +} + +void TextureTransform::serialize(object& dst) const +{ +    write(mOffset, "offset", dst, vec2(0.f, 0.f)); +    write(mRotation, "rotation", dst, 0.f); +    write(mScale, "scale", dst, vec2(1.f, 1.f)); +    write(mTexCoord, "texCoord", dst, -1); +} + +  void Material::serialize(object& dst) const  {      write(mName, "name", dst); diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 8f28e5905f..ea3f7d480a 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -57,6 +57,21 @@ namespace LL              bool mPresent = false;          }; +        class TextureTransform : public Extension // KHR_texture_transform implementation +        { +        public: +            vec2 mOffset = vec2(0.f, 0.f); +            F32 mRotation = 0.f; +            vec2 mScale = vec2(1.f, 1.f); +            S32 mTexCoord = INVALID_INDEX; + +            // get the texture transform as a packed array of floats +            // dst MUST point to at least 8 floats +            void getPacked(F32* dst) const; + +            const TextureTransform& operator=(const Value& src); +            void serialize(boost::json::object& dst) const; +        };          class Material          { @@ -82,9 +97,15 @@ namespace LL                  S32 mIndex = INVALID_INDEX;                  S32 mTexCoord = 0; +                TextureTransform mTextureTransform; +                  bool operator==(const TextureInfo& rhs) const;                  bool operator!=(const TextureInfo& rhs) const; +                // get the UV channel that should be used for sampling this texture +                // returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord +                S32 getTexCoord() const; +                  const TextureInfo& operator=(const Value& src);                  void serialize(boost::json::object& dst) const;              }; @@ -135,6 +156,8 @@ namespace LL              bool mDoubleSided = false;              Unlit mUnlit; +            bool isMultiUV() const; +              const Material& operator=(const Value& src);              void serialize(boost::json::object& dst) const;          }; diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h index c26752a6b6..c1101818b7 100644 --- a/indra/newview/gltf/buffer_util.h +++ b/indra/newview/gltf/buffer_util.h @@ -590,8 +590,8 @@ namespace LL          // Write all extensions to dst.extensions          // Usage:          //  write_extensions(dst, -        //                   "KHR_materials_unlit", mUnlit, -        //                   "KHR_materials_pbrSpecularGlossiness", mPbrSpecularGlossiness); +        //                   mUnlit, "KHR_materials_unlit", +        //                   mPbrSpecularGlossiness, "KHR_materials_pbrSpecularGlossiness");          // returns true if any of the extensions are written          template<class... Types>          inline bool write_extensions(boost::json::object& dst, Types... args) @@ -816,6 +816,39 @@ namespace LL              return true;          } +        // vec2 +        template<> +        inline bool copy(const Value& src, vec2& dst) +        { +            if (src.is_array()) +            { +                const boost::json::array& arr = src.as_array(); +                if (arr.size() == 2) +                { +                    std::error_code ec; +                    vec2 t; +                    t.x = arr[0].to_number<F32>(ec); if (ec) return false; +                    t.y = arr[1].to_number<F32>(ec); if (ec) return false; + +                    dst = t; +                    return true; +                } +            } +            return false; +        } + +        template<> +        inline bool write(const vec2& src, Value& dst) +        { +            dst = boost::json::array(); +            boost::json::array& arr = dst.as_array(); +            arr.resize(2); +            arr[0] = src.x; +            arr[1] = src.y; +             +            return true; +        } +          // bool          template<>          inline bool copy(const Value& src, bool& dst) diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index 197ffb68e8..dd37b5b4d0 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -42,13 +42,14 @@ using namespace boost::json;  // Mesh data useful for Mikktspace tangent generation (and flat normal generation)  struct MikktMesh  { -    std::vector<LLVector3> p; -    std::vector<LLVector3> n; -    std::vector<LLVector2> tc; -    std::vector<LLVector4> w; -    std::vector<LLVector4> t; -    std::vector<LLColor4U> c; -    std::vector<U64> j; +    std::vector<LLVector3> p;       //positions +    std::vector<LLVector3> n;       //normals +    std::vector<LLVector4> t;       //tangents +    std::vector<LLVector2> tc0;     //texcoords 0 +    std::vector<LLVector2> tc1;     //texcoords 1 +    std::vector<LLColor4U> c;       //colors +    std::vector<LLVector4> w;       //weights +    std::vector<U64> j;             //joints      // initialize from src primitive and make an unrolled triangle list      // returns false if the Primitive cannot be converted to a triangle list @@ -57,15 +58,28 @@ struct MikktMesh          bool indexed = !prim->mIndexArray.empty();          auto vert_count = indexed ? prim->mIndexArray.size() : prim->mPositions.size(); -        if (prim->mMode != Primitive::Mode::TRIANGLES) +        U32 triangle_count = 0; + +        if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP || +            prim->mMode == Primitive::Mode::TRIANGLE_FAN) +        { +            triangle_count = vert_count - 2; +        } +        else if (prim->mMode == Primitive::Mode::TRIANGLES)          { -            LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32) prim->mMode << LL_ENDL; +            triangle_count = vert_count / 3; +        } +        else +        { +            LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32)prim->mMode << LL_ENDL;              return false;          } +        vert_count = triangle_count * 3; +          p.resize(vert_count);          n.resize(vert_count); -        tc.resize(vert_count); +        tc0.resize(vert_count);          c.resize(vert_count);          bool has_normals = !prim->mNormals.empty(); @@ -78,6 +92,7 @@ struct MikktMesh          {              t.resize(vert_count);          } +          bool rigged = !prim->mWeights.empty();          if (rigged)          { @@ -85,23 +100,69 @@ struct MikktMesh              j.resize(vert_count);          } -        for (U32 i = 0; i < vert_count; ++i) +        bool multi_uv = !prim->mTexCoords1.empty(); +        if (multi_uv)          { -            U32 idx = indexed ? prim->mIndexArray[i] : i; +            tc1.resize(vert_count); +        } -            p[i].set(prim->mPositions[idx].getF32ptr()); -            tc[i].set(prim->mTexCoords[idx]); -            c[i] = prim->mColors[idx]; +        for (int tri_idx = 0; tri_idx < triangle_count; ++tri_idx) +        { +            U32 idx[3]; + +            if (prim->mMode == Primitive::Mode::TRIANGLES) +            { +                idx[0] = tri_idx * 3; +                idx[1] = tri_idx * 3 + 1; +                idx[2] = tri_idx * 3 + 2; +            } +            else if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP) +            { +                idx[0] = tri_idx; +                idx[1] = tri_idx + 1; +                idx[2] = tri_idx + 2; + +                if (tri_idx % 2 != 0) +                { +                    std::swap(idx[1], idx[2]); +                } +            } +            else if (prim->mMode == Primitive::Mode::TRIANGLE_FAN) +            { +                idx[0] = 0; +                idx[1] = tri_idx + 1; +                idx[2] = tri_idx + 2; +            } -            if (has_normals) +            if (indexed)              { -                n[i].set(prim->mNormals[idx].getF32ptr()); +                idx[0] = prim->mIndexArray[idx[0]]; +                idx[1] = prim->mIndexArray[idx[1]]; +                idx[2] = prim->mIndexArray[idx[2]];              } -            if (rigged) +            for (U32 v = 0; v < 3; ++v)              { -                w[i].set(prim->mWeights[idx].getF32ptr()); -                j[i] = prim->mJoints[idx]; +                U32 i = tri_idx * 3 + v; +                p[i].set(prim->mPositions[idx[v]].getF32ptr()); +                tc0[i].set(prim->mTexCoords0[idx[v]]); +                c[i] = prim->mColors[idx[v]]; + +                if (multi_uv) +                { +                    tc1[i].set(prim->mTexCoords1[idx[v]]); +                } + +                if (has_normals) +                { +                    n[i].set(prim->mNormals[idx[v]].getF32ptr()); +                } + +                if (rigged) +                { +                    w[i].set(prim->mWeights[idx[v]].getF32ptr()); +                    j[i] = prim->mJoints[idx[v]]; +                }              }          } @@ -138,25 +199,34 @@ struct MikktMesh      void write(Primitive* prim) const      {          //re-weld -        meshopt_Stream mos[] = +        std::vector<meshopt_Stream> mos =          {              { &p[0], sizeof(LLVector3), sizeof(LLVector3) },              { &n[0], sizeof(LLVector3), sizeof(LLVector3) },              { &t[0], sizeof(LLVector4), sizeof(LLVector4) }, -            { &tc[0], sizeof(LLVector2), sizeof(LLVector2) }, -            { &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }, -            { w.empty() ? nullptr : &w[0], sizeof(LLVector4), sizeof(LLVector4) }, -            { j.empty() ? nullptr : &j[0], sizeof(U64), sizeof(U64) } +            { &tc0[0], sizeof(LLVector2), sizeof(LLVector2) }, +            { &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }          }; +        if (!w.empty()) +        { +            mos.push_back({ &w[0], sizeof(LLVector4), sizeof(LLVector4) }); +            mos.push_back({ &j[0], sizeof(U64), sizeof(U64) }); +        } + +        if (!tc1.empty()) +        { +            mos.push_back({ &tc1[0], sizeof(LLVector2), sizeof(LLVector2) }); +        } +          std::vector<U32> remap;          remap.resize(p.size()); -        U32 stream_count = w.empty() ? 5 : 7; +        U32 stream_count = mos.size(); -        size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, p.size(), p.size(), mos, stream_count); +        size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, p.size(), p.size(), mos.data(), stream_count); -        prim->mTexCoords.resize(vert_count); +        prim->mTexCoords0.resize(vert_count);          prim->mNormals.resize(vert_count);          prim->mTangents.resize(vert_count);          prim->mPositions.resize(vert_count); @@ -166,6 +236,10 @@ struct MikktMesh              prim->mWeights.resize(vert_count);              prim->mJoints.resize(vert_count);          } +        if (!tc1.empty()) +                    { +            prim->mTexCoords1.resize(vert_count); +        }          prim->mIndexArray.resize(remap.size()); @@ -178,7 +252,7 @@ struct MikktMesh              prim->mPositions[dst_idx].load3(p[src_idx].mV);              prim->mNormals[dst_idx].load3(n[src_idx].mV); -            prim->mTexCoords[dst_idx] = tc[src_idx]; +            prim->mTexCoords0[dst_idx] = tc0[src_idx];              prim->mTangents[dst_idx].loadua(t[src_idx].mV);              prim->mColors[dst_idx] = c[src_idx]; @@ -187,6 +261,11 @@ struct MikktMesh                  prim->mWeights[dst_idx].loadua(w[src_idx].mV);                  prim->mJoints[dst_idx] = j[src_idx];              } + +            if (!tc1.empty()) +            { +                prim->mTexCoords1[dst_idx] = tc1[src_idx]; +            }          }          prim->mGLMode = LLRender::TRIANGLES; @@ -210,8 +289,8 @@ struct MikktMesh      mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)      { -        F32* uv = tc[face_num * 3 + vert_num].mV; -        return mikk::float3(uv[0], uv[1], 1.0f); +        F32* uv = tc0[face_num * 3 + vert_num].mV; +        return mikk::float3(uv[0], 1.f-uv[1], 1.0f);      }      mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) @@ -228,6 +307,14 @@ struct MikktMesh  }; +static void vertical_flip(std::vector<LLVector2>& texcoords) +{ +    for (auto& tc : texcoords) +    { +        tc[1] = 1.f - tc[1]; +    } +} +  bool Primitive::prep(Asset& asset)  {      // allocate vertex buffer @@ -261,7 +348,11 @@ bool Primitive::prep(Asset& asset)          }          else if (attribName == "TEXCOORD_0")          { -            copy(asset, accessor, mTexCoords); +            copy(asset, accessor, mTexCoords0); +        } +        else if (attribName == "TEXCOORD_1") +        { +            copy(asset, accessor, mTexCoords1);          }          else if (attribName == "JOINTS_0")          { @@ -297,24 +388,28 @@ bool Primitive::prep(Asset& asset)          mask |= LLVertexBuffer::MAP_JOINT;      } -    if (mTexCoords.empty()) +    if (mTexCoords0.empty())      { -        mTexCoords.resize(mPositions.size()); +        mTexCoords0.resize(mPositions.size());      } -    // TODO: support more than one texcoord set (or no texcoords)      mask |= LLVertexBuffer::MAP_TEXCOORD0; +    if (!mTexCoords1.empty()) +    { +        mask |= LLVertexBuffer::MAP_TEXCOORD1; +    } +      if (mColors.empty())      {          mColors.resize(mPositions.size(), LLColor4U::white);      } +    mShaderVariant = 0; +      // TODO: support colorless vertex buffers      mask |= LLVertexBuffer::MAP_COLOR; -    mShaderVariant = 0; -      bool unlit = false;      // bake material basecolor into color array @@ -332,6 +427,11 @@ bool Primitive::prep(Asset& asset)              mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;              unlit = true;          } + +        if (material.isMultiUV()) +        { +            mShaderVariant |= LLGLSLShader::GLTFVariant::MULTI_UV; +        }      }      if (mNormals.empty() && !unlit) @@ -437,16 +537,18 @@ bool Primitive::prep(Asset& asset)      }      // flip texcoord y, upload, then flip back (keep the off-spec data in vram only) -    for (auto& tc : mTexCoords) -    { -        tc[1] = 1.f - tc[1]; -    } -    mVertexBuffer->setTexCoordData(mTexCoords.data()); -    for (auto& tc : mTexCoords) +    vertical_flip(mTexCoords0); +    mVertexBuffer->setTexCoord0Data(mTexCoords0.data()); +    vertical_flip(mTexCoords0); + +    if (!mTexCoords1.empty())      { -        tc[1] = 1.f - tc[1]; +        vertical_flip(mTexCoords1); +        mVertexBuffer->setTexCoord1Data(mTexCoords1.data()); +        vertical_flip(mTexCoords1);      } +      if (!mIndexArray.empty())      {          mVertexBuffer->setIndexData(mIndexArray.data()); @@ -456,10 +558,13 @@ bool Primitive::prep(Asset& asset)      mVertexBuffer->unbind(); -    Material& material = asset.mMaterials[mMaterial]; -    if (material.mAlphaMode == Material::AlphaMode::BLEND) +    if (mMaterial != INVALID_INDEX)      { -        mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; +        Material& material = asset.mMaterials[mMaterial]; +        if (material.mAlphaMode == Material::AlphaMode::BLEND) +        { +            mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; +        }      }      return true; @@ -617,7 +722,7 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,      //create a proxy LLVolumeFace for the raycast      LLVolumeFace face;      face.mPositions = mPositions.data(); -    face.mTexCoords = mTexCoords.data(); +    face.mTexCoords = mTexCoords0.data();      face.mNormals = mNormals.data();      face.mTangents = mTangents.data();      face.mIndices = nullptr; // unreferenced diff --git a/indra/newview/gltf/primitive.h b/indra/newview/gltf/primitive.h index f9d7c63c65..7cc05cf831 100644 --- a/indra/newview/gltf/primitive.h +++ b/indra/newview/gltf/primitive.h @@ -58,7 +58,8 @@ namespace LL              LLPointer<LLVertexBuffer> mVertexBuffer;              // CPU copy of mesh data, keep these as LLVector types for compatibility with raycasting code -            std::vector<LLVector2> mTexCoords; +            std::vector<LLVector2> mTexCoords0; +            std::vector<LLVector2> mTexCoords1;              std::vector<LLVector4a> mNormals;              std::vector<LLVector4a> mTangents;              std::vector<LLVector4a> mPositions; diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index b948b2e2d6..e01aec0497 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -552,10 +552,16 @@ void GLTFSceneManager::render(bool opaque, bool rigged, bool unlit)  void GLTFSceneManager::render(U8 variant)  { -    // for debugging, just render the whole scene as opaque -    // by traversing the whole scenegraph -    // Assumes camera transform is already set and -    // appropriate shader is already boundd +    // just render the whole scene by traversing the whole scenegraph +    // Assumes camera transform is already set and appropriate shader is already bound. +    // Eventually we'll want a smarter render pipe that has pre-sorted the scene graph +    // into buckets by material and shader. + +    // HACK -- implicitly render multi-uv variant +    if (!(variant & LLGLSLShader::GLTFVariant::MULTI_UV)) +    { +        render((U8) (variant | LLGLSLShader::GLTFVariant::MULTI_UV)); +    }      gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -666,11 +672,30 @@ static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info,  {      if (info.mIndex != INVALID_INDEX)      { -        LLViewerTexture* tex = asset.mImages[asset.mTextures[info.mIndex].mSource].mTexture; +        Texture& texture = asset.mTextures[info.mIndex]; + +        LLViewerTexture* tex = asset.mImages[texture.mSource].mTexture;          if (tex)          {              tex->addTextureStats(2048.f * 2048.f); -            LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex); +            S32 channel = LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex); + +            if (channel != -1 && texture.mSampler != -1) +            { // set sampler state +                Sampler& sampler = asset.mSamplers[texture.mSampler]; +                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sampler.mWrapS); +                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, sampler.mWrapT); +                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler.mMagFilter); + +                // NOTE: do not set min filter.  Always respect client preference for min filter +            } +            else +            { +                // set default sampler state +                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +            }          }          else          { @@ -713,10 +738,10 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)      bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, material.mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep); -    F32 base_color_packed[8]; -    //mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed); -    LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed); -    shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed); +    F32 tf[8]; +    material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf); +    shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf); +    shader->uniform1i(LLShaderMgr::BASE_COLOR_TEXCOORD, material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord());      if (!LLPipeline::sShadowRender)      { @@ -731,20 +756,21 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)          shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, material.mPbrMetallicRoughness.mMetallicFactor);          shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(material.mEmissiveFactor)); -        F32 normal_packed[8]; -        //mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); -        LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); -        shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed); +        material.mNormalTexture.mTextureTransform.getPacked(tf); +        shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::NORMAL_TEXCOORD, material.mNormalTexture.getTexCoord()); + +        material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf); +        shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::METALLIC_ROUGHNESS_TEXCOORD, material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord()); -        F32 metallic_roughness_packed[8]; -        //mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed); -        LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed); -        shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed); +        material.mOcclusionTexture.mTextureTransform.getPacked(tf); +        shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::OCCLUSION_TEXCOORD, material.mOcclusionTexture.getTexCoord()); -        F32 emissive_packed[8]; -        //mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed); -        LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed); -        shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, (F32*)emissive_packed); +        material.mEmissiveTexture.mTextureTransform.getPacked(tf); +        shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf); +        shader->uniform1i(LLShaderMgr::EMISSIVE_TEXCOORD, material.mEmissiveTexture.getTexCoord());      }  } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d43d6fea37..5913e7ba6f 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -249,7 +249,7 @@ static bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader  } -static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged, bool unlit, bool use_sun_shadow) +static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged, bool unlit, bool multi_uv, bool use_sun_shadow)  {      variant.mName = shader.mName.c_str();      variant.mFeatures = shader.mFeatures; @@ -271,6 +271,11 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool          variant.addPermutation("UNLIT", "1");      } +    if (multi_uv) +    { +        variant.addPermutation("MULTI_UV", "1"); +    } +      if (alpha_blend)      {          variant.addPermutation("ALPHA_BLEND", "1"); @@ -317,8 +322,9 @@ static bool make_gltf_variants(LLGLSLShader& shader, bool use_sun_shadow)          bool alpha_blend = i & LLGLSLShader::GLTFVariant::ALPHA_BLEND;          bool rigged = i & LLGLSLShader::GLTFVariant::RIGGED;          bool unlit = i & LLGLSLShader::GLTFVariant::UNLIT; +        bool multi_uv = i & LLGLSLShader::GLTFVariant::MULTI_UV; -        if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, use_sun_shadow)) +        if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, multi_uv, use_sun_shadow))          {              return false;          } diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml b/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml index cbcbe418cd..9a90700056 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml @@ -3,7 +3,6 @@   border="true"   follows="top|left"   height="460" - help_topic="panel_region_terrain_tab"   label="Terrain"   layout="topleft"   left="0" @@ -225,13 +224,12 @@            left="0"            name="terrain_tabs"            tab_position="top" -          tab_width="100" +          tab_width="110"            tab_padding_right="3"            top_pad="0"            width="700">            <panel              border="true" -            class="panel_settings_terrain_elevation"              filename="panel_settings_terrain_elevation.xml"              label="Elevation"              layout="topleft" @@ -240,7 +238,6 @@              name="terrain_elevation_panel" />            <panel              border="true" -            class="panel_settings_terrain_transform"              filename="panel_settings_terrain_transform.xml"              label="Transforms"              layout="topleft" @@ -256,8 +253,8 @@       height="20"       label="Apply"       layout="topleft" -     left="353" +     left="351"       name="apply_btn" -     top_delta="290" +     top_delta="310"       width="100" />  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml b/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml index 7052622813..0bf0d8cffc 100644 --- a/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml +++ b/indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml @@ -10,6 +10,62 @@    <text     type="string"     length="1" +   halign="center" +   valign="center" +   follows="left|top" +   height="20" +   layout="topleft" +   name="terrain0_label" +   left="48" +   top_delta="0" +   width="62"> +      1 +  </text> +  <text +   type="string" +   length="1" +   halign="center" +   valign="center" +   follows="left|top" +   height="20" +   layout="topleft" +   name="terrain1_label" +   left_delta="110" +   top_delta="0" +   width="62"> +      2 +  </text> +  <text +   type="string" +   length="1" +   halign="center" +   valign="center" +   follows="left|top" +   height="20" +   layout="topleft" +   name="terrain2_label" +   left_delta="110" +   top_delta="0" +   width="62"> +      3 +  </text> +  <text +   type="string" +   length="1" +   halign="center" +   valign="center" +   follows="left|top" +   height="20" +   layout="topleft" +   name="terrain3_label" +   left_delta="110" +   top_delta="0" +   width="62"> +      4 +  </text> +  <text +   type="string" +   length="1"     halign="left"     valign="center"     follows="left|top" @@ -17,19 +73,10 @@     layout="topleft"     name="terrain0ScaleU_label"     left="10" -   top_pad="3" +   top_pad="0"     width="170">        Scale u    </text> -  <view_border -   bevel_style="none" -   follows="top|left" -   height="0" -   layout="topleft" -   left="8" -   top_pad="-2" -   name="terrain0ScaleU_horizontal" -   width="430" />    <spinner     follows="left|top"     height="19" @@ -37,7 +84,7 @@     label="Scale u"     label_width="0"     layout="topleft" -   left="10" +   left="46"     min_val="-100"     max_val="100"     name="terrain0ScaleU" @@ -78,6 +125,15 @@     max_val="100"     name="terrain3ScaleU"     width="64" /> +  <view_border +   bevel_style="none" +   follows="top|left" +   height="0" +   layout="topleft" +   left="8" +   top_pad="8" +   name="terrainScaleU_horizontal" +   width="432" />    <text     type="string"     length="1" @@ -88,19 +144,10 @@     layout="topleft"     name="terrain0ScaleV_label"     left="10" -   top_pad="3" +   top_pad="0"     width="170">        Scale v    </text> -  <view_border -   bevel_style="none" -   follows="top|left" -   height="0" -   layout="topleft" -   left="8" -   top_pad="-2" -   name="terrain0ScaleV_horizontal" -   width="430" />    <spinner     follows="left|top"     height="19" @@ -108,7 +155,7 @@     label="Scale v"     label_width="0"     layout="topleft" -   left="10" +   left="46"     min_val="-100"     max_val="100"     name="terrain0ScaleV" @@ -149,6 +196,15 @@     max_val="100"     name="terrain3ScaleV"     width="64" /> +  <view_border +   bevel_style="none" +   follows="top|left" +   height="0" +   layout="topleft" +   left="8" +   top_pad="8" +   name="terrainScaleV_horizontal" +   width="432" />    <text     type="string"     length="1" @@ -159,19 +215,10 @@     layout="topleft"     name="terrain0Rotation_label"     left="10" -   top_pad="3" +   top_pad="0"     width="170">        Rotation    </text> -  <view_border -   bevel_style="none" -   follows="top|left" -   height="0" -   layout="topleft" -   left="8" -   top_pad="-2" -   name="terrain0Rotation_horizontal" -   width="430" />    <spinner     follows="left|top"     height="19" @@ -179,7 +226,7 @@     label="Rotation"     label_width="0"     layout="topleft" -   left="10" +   left="46"     min_val="-360"     max_val="360"     name="terrain0Rotation" @@ -192,8 +239,8 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-360" +   max_val="360"     name="terrain1Rotation"     width="64" />    <spinner @@ -204,8 +251,8 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-360" +   max_val="360"     name="terrain2Rotation"     width="64" />    <spinner @@ -216,10 +263,19 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-360" +   max_val="360"     name="terrain3Rotation"     width="64" /> +  <view_border +   bevel_style="none" +   follows="top|left" +   height="0" +   layout="topleft" +   left="8" +   top_pad="8" +   name="terrainRotation_horizontal" +   width="432" />    <text     type="string"     length="1" @@ -230,19 +286,10 @@     layout="topleft"     name="terrain0OffsetU_label"     left="10" -   top_pad="3" +   top_pad="0"     width="170">        Offset y    </text> -  <view_border -   bevel_style="none" -   follows="top|left" -   height="0" -   layout="topleft" -   left="8" -   top_pad="-2" -   name="terrain0OffsetU_horizontal" -   width="430" />    <spinner     follows="left|top"     height="19" @@ -250,7 +297,7 @@     label="Offset u"     label_width="0"     layout="topleft" -   left="10" +   left="46"     min_val="-999"     max_val="999"     name="terrain0OffsetU" @@ -263,8 +310,8 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-999" +   max_val="999"     name="terrain1OffsetU"     width="64" />    <spinner @@ -275,8 +322,8 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-999" +   max_val="999"     name="terrain2OffsetU"     width="64" />    <spinner @@ -287,10 +334,19 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-999" +   max_val="999"     name="terrain3OffsetU"     width="64" /> +  <view_border +   bevel_style="none" +   follows="top|left" +   height="0" +   layout="topleft" +   left="8" +   top_pad="8" +   name="terrainOffsetU_horizontal" +   width="432" />    <text     type="string"     length="1" @@ -301,19 +357,10 @@     layout="topleft"     name="terrain0OffsetV_label"     left="10" -   top_pad="3" +   top_pad="0"     width="170">        Offset v    </text> -  <view_border -   bevel_style="none" -   follows="top|left" -   height="0" -   layout="topleft" -   left="8" -   top_pad="-2" -   name="terrain0OffsetV_horizontal" -   width="430" />    <spinner     follows="left|top"     height="19" @@ -321,7 +368,7 @@     label="Offset v"     label_width="0"     layout="topleft" -   left="10" +   left="46"     min_val="-999"     max_val="999"     name="terrain0OffsetV" @@ -334,8 +381,8 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-999" +   max_val="999"     name="terrain1OffsetV"     width="64" />    <spinner @@ -346,8 +393,8 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-999" +   max_val="999"     name="terrain2OffsetV"     width="64" />    <spinner @@ -358,8 +405,17 @@     label_width="0"     layout="topleft"     left_delta="110" -   min_val="-100" -   max_val="100" +   min_val="-999" +   max_val="999"     name="terrain3OffsetV"     width="64" /> +  <view_border +   bevel_style="none" +   follows="top|left" +   height="0" +   layout="topleft" +   left="8" +   top_pad="8" +   name="terrainOffsetV_horizontal" +   width="432" />  </panel>  | 
