Merge branch 'project/gltf_development' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/newview/gltf/primitive.cpp
#	indra/newview/lldynamictexture.cpp
#	indra/newview/llfloaterregioninfo.h
#	indra/newview/lltexturectrl.cpp
#	indra/newview/lltinygltfhelper.cpp
#	indra/newview/llvlcomposition.cpp
#	indra/newview/llvlcomposition.h
#	indra/newview/llvovolume.cpp
master
Ansariel 2024-06-13 03:21:12 +02:00
commit 050d2fefab
44 changed files with 779 additions and 317 deletions

View File

@ -2,6 +2,7 @@
1b68f71348ecf3983b76b40d7940da8377f049b7 1b68f71348ecf3983b76b40d7940da8377f049b7
# Trim trailing whitespace # Trim trailing whitespace
a0b3021bdcf76859054fda8e30abb3ed47749e83 a0b3021bdcf76859054fda8e30abb3ed47749e83
8444cd9562a6a7b755fcb075864e205122354192
# Wrong line endings # Wrong line endings
1b67dd855c41f5a0cda7ec2a68d98071986ca703 1b67dd855c41f5a0cda7ec2a68d98071986ca703
6cc7dd09d5e69cf57e6de7fb568a0ad2693f9c9a 6cc7dd09d5e69cf57e6de7fb568a0ad2693f9c9a

View File

@ -1,13 +1,14 @@
# PBR Terrain Appearance # PBR Terrain Appearance
## Tiling ## Tiling Without Texture Transforms
This section assumes the PBR terrain of the current region and adjacent regions have the default texture transforms.
The southwest corner of a region with PBR materials should exactly match up with the bottom left corner of the material texture(s). The southwest corner of a region with PBR materials should exactly match up with the bottom left corner of the material texture(s).
If two adjacent regions have the same PBR terrain settings, then: If two adjacent regions have the same PBR terrain settings, then there should not be seams between the two regions at their shared border.
- There should not be seams between the two regions at their shared border The ground should not suddenly slide beneath the avatar when moving between two PBR terrain regions (except due to movement of the avatar, which is not covered by this test plan)
- The ground should not suddenly slide beneath the avatar when moving between regions (except due to movement of the avatar, which is not covered by this test plan)
## Feature Gating ## Feature Gating
@ -35,3 +36,17 @@ Availability of PBR textures varies by machine and graphics setting:
### PBR Alpha ### PBR Alpha
PBR terrain does not support materials with alpha blend or double-sided. In addition, the viewer does not make any guarantees about what will render behind the terrain if alpha is used. PBR terrain does not support materials with alpha blend or double-sided. In addition, the viewer does not make any guarantees about what will render behind the terrain if alpha is used.
## PBR Terrain Texture Transforms
Like PBR materials on prims, PBR terrain repeats are based on the [KHR\_texture\_transform](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) spec, and thus should be expected to behave the same way.
The southwest corner of a region, at z=0, is the UV origin for all texture coordinates of the whole region. Unless an offset is also applied, scale and rotation of the terrain texture transforms are relative to that point.
When an avatar faces north and looks down at flat ground, the textures of the materials should appear to face upright, unless a rotation is applied.
If triplanar mapping is enabled, and an avatar faces an axially-aligned wall, the textures of the materials should appear to face upright, unless a rotation is applied.
Textures of materials should not appear mirrored.
When triplanar mapping is enabled, rotations on the axially aligned walls should apply in the same direction as they would on flat ground.

View File

@ -12,6 +12,10 @@ All tests in this section assume the PBR terrain feature flag is enabled, and th
### Feature Availability ### Feature Availability
These features are related to UI, where the Region/Estate floater is opened to the terrain Tab.
#### Feature: PBR Terrain
On the client, the advanced setting `RenderTerrainPBREnabled` is the PBR terrain feature flag. On the client, the advanced setting `RenderTerrainPBREnabled` is the PBR terrain feature flag.
The PBR terrain feature flag should be set automatically when logging in/teleporting to a new region. The PBR terrain feature flag should be set automatically when logging in/teleporting to a new region.
@ -29,6 +33,24 @@ When the PBR terrain feature flag is enabled:
- The "PBR Metallic Roughness" checkbox should be visible - The "PBR Metallic Roughness" checkbox should be visible
- The user should be able to apply PBR terrain or textures to the region, depending on if the "PBR Metallic Roughness" checkbox is checked. - The user should be able to apply PBR terrain or textures to the region, depending on if the "PBR Metallic Roughness" checkbox is checked.
#### Feature: PBR Terrain Texture Transforms
On the client, the advanced setting, `RenderTerrainPBRTransformsEnabled` is the PBR terrain texture transform flag. Generally, this feature should not be expected to work correctly unless the PBR terrain feature is also enabled.
The PBR terrain texture transform flag should be set automatically when logging in/teleporting to a new region.
- The flag should be enabled on regions where the PBR terrain texture transform feature is enabled
- Otherwise the flag should be disabled
When the PBR terrain texture transform feature is enabled, the UI of the Terrain tab should be overhauled. Availability of features depends on the type of terrain.
When "PBR Metallic Roughness" is checked:
- There should be a way for the user to change the texture transforms for the terrain in the current region
- For each of the four swatches, the user can change the scale, offset, and rotation of that swatch. Nonuniform scale is allowed
When "PBR Metallic Roughness" is unchecked, the controls for texture transforms should be hidden.
### Current Composition Type ### Current Composition Type
When the Region/Estate floater is opened to the terrain Tab, the current terrain should be shown in the four swatches, and the "PBR Metallic Roughness" checkbox should be checked or unchecked accordingly. When the Region/Estate floater is opened to the terrain Tab, the current terrain should be shown in the four swatches, and the "PBR Metallic Roughness" checkbox should be checked or unchecked accordingly.

View File

@ -61,14 +61,14 @@
#include <excpt.h> #include <excpt.h>
#endif #endif
// static // static
bool LLCoros::on_main_coro() bool LLCoros::on_main_coro()
{ {
if (!LLCoros::instanceExists() || LLCoros::getName().empty()) if (!LLCoros::instanceExists() || LLCoros::getName().empty())
{ {
return true; return true;
} }
return false; return false;
} }

View File

@ -3,25 +3,25 @@
* @author Nat Goodspeed * @author Nat Goodspeed
* @date 2009-06-02 * @date 2009-06-02
* @brief Manage running boost::coroutine instances * @brief Manage running boost::coroutine instances
* *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2010, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -100,7 +100,7 @@ public:
static bool on_main_coro(); static bool on_main_coro();
// For debugging, return true if on the main thread and not in a coroutine // For debugging, return true if on the main thread and not in a coroutine
// Non-thread-safe code in the main loop should be protected by // Non-thread-safe code in the main loop should be protected by
// llassert(LLCoros::on_main_thread_main_coro()) // llassert(LLCoros::on_main_thread_main_coro())
static bool on_main_thread_main_coro(); static bool on_main_thread_main_coro();
@ -168,7 +168,7 @@ public:
* LLCoros::launch()). * LLCoros::launch()).
*/ */
static std::string getName(); static std::string getName();
/** /**
* rethrow() is called by the thread's main fiber to propagate an * rethrow() is called by the thread's main fiber to propagate an
* exception from any coroutine into the main fiber, where it can engage * exception from any coroutine into the main fiber, where it can engage

View File

@ -3,25 +3,25 @@
* @author Nat Goodspeed * @author Nat Goodspeed
* @date 2008-09-12 * @date 2008-09-12
* @brief Implementation for llevents. * @brief Implementation for llevents.
* *
* $LicenseInfo:firstyear=2008&license=viewerlgpl$ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2010, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -423,8 +423,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
float nodePosition = 1.0; float nodePosition = 1.0;
// if the supplied name is empty we are not interested in the ordering mechanism // if the supplied name is empty we are not interested in the ordering mechanism
// and can bypass attempting to find the optimal location to insert the new // and can bypass attempting to find the optimal location to insert the new
// listener. We'll just tack it on to the end. // listener. We'll just tack it on to the end.
if (!name.empty()) // should be the same as testing against ANONYMOUS if (!name.empty()) // should be the same as testing against ANONYMOUS
{ {
@ -569,12 +569,12 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// Now that newNode has a value that places it appropriately in mSignal, // Now that newNode has a value that places it appropriately in mSignal,
// connect it. // connect it.
LLBoundListener bound = mSignal->connect(nodePosition, listener); LLBoundListener bound = mSignal->connect(nodePosition, listener);
if (!name.empty()) if (!name.empty())
{ // note that we are not tracking anonymous listeners here either. { // note that we are not tracking anonymous listeners here either.
// This means that it is the caller's responsibility to either assign // This means that it is the caller's responsibility to either assign
// to a TempBoundListerer (scoped_connection) or manually disconnect // to a TempBoundListerer (scoped_connection) or manually disconnect
// when done. // when done.
mConnections[name] = bound; mConnections[name] = bound;
} }
return bound; return bound;
@ -641,9 +641,9 @@ bool LLEventMailDrop::post(const LLSD& event)
{ {
// forward the call to our base class // forward the call to our base class
bool posted = LLEventStream::post(event); bool posted = LLEventStream::post(event);
if (!posted) if (!posted)
{ // if the event was not handled we will save it for later so that it can { // if the event was not handled we will save it for later so that it can
// be posted to any future listeners when they attach. // be posted to any future listeners when they attach.
mEventHistory.push_back(event); mEventHistory.push_back(event);
} }

View File

@ -268,7 +268,7 @@ public:
F32 mAlphaCutoff; F32 mAlphaCutoff;
AlphaMode mAlphaMode; AlphaMode mAlphaMode;
bool mDoubleSided = false; bool mDoubleSided = false;
// Override specific flags for state that can't use off-by-epsilon or UUID // Override specific flags for state that can't use off-by-epsilon or UUID

View File

@ -1276,7 +1276,7 @@ bool LLGLManager::initGL()
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize);
// sanity clamp max uniform block size to 64k just in case // sanity clamp max uniform block size to 64k just in case
// there's some implementation that reports a crazy value // there's some implementation that reports a crazy value
mMaxUniformBlockSize = llmin(mMaxUniformBlockSize, 65536); mMaxUniformBlockSize = llmin(mMaxUniformBlockSize, 65536);

View File

@ -172,11 +172,11 @@ void clear_glerror();
# define llglassertok() assert_glerror() # define llglassertok() assert_glerror()
// stop_glerror is still needed on OS X but has performance implications // stop_glerror is still needed on OS X but has performance implications
// use macro below to conditionally add stop_glerror to non-release builds // use macro below to conditionally add stop_glerror to non-release builds
// on OS X // on OS X
#if LL_DARWIN && !LL_RELEASE_FOR_DOWNLOAD #if LL_DARWIN && !LL_RELEASE_FOR_DOWNLOAD
#define STOP_GLERROR stop_glerror() #define STOP_GLERROR stop_glerror()
#else #else
#define STOP_GLERROR #define STOP_GLERROR
#endif #endif

View File

@ -384,7 +384,7 @@ void LLGLSLShader::unloadInternal()
bool LLGLSLShader::createShader() bool LLGLSLShader::createShader()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
unloadInternal(); unloadInternal();
sInstances.insert(this); sInstances.insert(this);
@ -968,7 +968,7 @@ bool LLGLSLShader::mapUniforms()
glUniformBlockBinding(mProgramObject, UBOBlockIndex, i); glUniformBlockBinding(mProgramObject, UBOBlockIndex, i);
} }
} }
unbind(); unbind();
LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;

View File

@ -328,14 +328,16 @@ public:
// bit 0 = alpha mode blend (1) or opaque (0) // bit 0 = alpha mode blend (1) or opaque (0)
// bit 1 = rigged (1) or static (0) // bit 1 = rigged (1) or static (0)
// bit 2 = unlit (1) or lit (0) // bit 2 = unlit (1) or lit (0)
// bit 3 = single (0) or multi (1) uv coordinates
struct GLTFVariant struct GLTFVariant
{ {
constexpr static U8 ALPHA_BLEND = 1; constexpr static U8 ALPHA_BLEND = 1;
constexpr static U8 RIGGED = 2; constexpr static U8 RIGGED = 2;
constexpr static U8 UNLIT = 4; 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; std::vector<LLGLSLShader> mGLTFVariants;

View File

@ -1731,7 +1731,7 @@ void LLRender::flush()
if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
{ {
vb->setTexCoordData(mTexcoordsp.get()); vb->setTexCoord0Data(mTexcoordsp.get());
} }
if (attribute_mask & LLVertexBuffer::MAP_COLOR) if (attribute_mask & LLVertexBuffer::MAP_COLOR)

View File

@ -1184,7 +1184,13 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF) mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF)
mReservedUniforms.push_back("texture_normal_transform"); // (GLTF) mReservedUniforms.push_back("texture_normal_transform"); // (GLTF)
mReservedUniforms.push_back("texture_metallic_roughness_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("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) mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF)

View File

@ -56,7 +56,13 @@ public:
TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF) TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF)
TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF) TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF)
TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_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) 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) TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF)

View File

@ -317,7 +317,7 @@ public:
{ //allocate a new buffer { //allocate a new buffer
LL_PROFILE_GPU_ZONE("vbo alloc"); LL_PROFILE_GPU_ZONE("vbo alloc");
// ON OS X, we don't allocate a VBO until the last possible moment // ON OS X, we don't allocate a VBO until the last possible moment
// in unmapBuffer // in unmapBuffer
data = (U8*) ll_aligned_malloc_16(size); data = (U8*) ll_aligned_malloc_16(size);
STOP_GLERROR; STOP_GLERROR;
@ -329,12 +329,12 @@ public:
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
llassert(size >= 2); llassert(size >= 2);
if (data) if (data)
{ {
ll_aligned_free_16(data); ll_aligned_free_16(data);
} }
mAllocated -= size; mAllocated -= size;
STOP_GLERROR; STOP_GLERROR;
if (name) if (name)
@ -1517,7 +1517,7 @@ void LLVertexBuffer::setBuffer()
// no data may be pending // no data may be pending
llassert(mMappedVertexRegions.empty()); llassert(mMappedVertexRegions.empty());
llassert(mMappedIndexRegions.empty()); llassert(mMappedIndexRegions.empty());
// a shader must be bound // a shader must be bound
llassert(LLGLSLShader::sCurBoundShaderPtr); llassert(LLGLSLShader::sCurBoundShaderPtr);
@ -1661,7 +1661,7 @@ void LLVertexBuffer::setPositionData(const LLVector4a* data)
flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data, mMappedData); 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 #if !LL_DARWIN
llassert(sGLRenderBuffer == mGLBuffer); llassert(sGLRenderBuffer == mGLBuffer);
@ -1669,6 +1669,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); 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) void LLVertexBuffer::setColorData(const LLColor4U* data)
{ {
#if !LL_DARWIN #if !LL_DARWIN

View File

@ -110,7 +110,7 @@ public:
TYPE_WEIGHT, // "weight" TYPE_WEIGHT, // "weight"
TYPE_WEIGHT4, // "weight4" TYPE_WEIGHT4, // "weight4"
TYPE_CLOTHWEIGHT, // "clothing" TYPE_CLOTHWEIGHT, // "clothing"
TYPE_JOINT, // "joint" TYPE_JOINT, // "joint"
TYPE_TEXTURE_INDEX, // "texture_index" TYPE_TEXTURE_INDEX, // "texture_index"
TYPE_MAX, // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer TYPE_MAX, // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer
TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer
@ -200,7 +200,8 @@ public:
void setTangentData(const LLVector4a* data); void setTangentData(const LLVector4a* data);
void setWeight4Data(const LLVector4a* data); void setWeight4Data(const LLVector4a* data);
void setJointData(const U64* 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 setColorData(const LLColor4U* data);
void setIndexData(const U16* data); void setIndexData(const U16* data);
void setIndexData(const U32* data); void setIndexData(const U32* data);

View File

@ -153,7 +153,7 @@ float terrain_mix(TerrainMix tm, vec4 tms4);
vec3 mikktspace(vec3 vNt, vec3 vT) vec3 mikktspace(vec3 vNt, vec3 vT)
{ {
vec3 vN = vary_normal; vec3 vN = vary_normal;
vec3 vB = vary_sign * cross(vN, vT); vec3 vB = vary_sign * cross(vN, vT);
vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );

View File

@ -37,8 +37,8 @@ uniform sampler2D emissiveMap;
uniform vec3 emissiveColor; uniform vec3 emissiveColor;
in vec3 vary_position; in vec3 vary_position;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 base_color_texcoord; in vec2 base_color_uv;
in vec2 emissive_texcoord; in vec2 emissive_uv;
uniform float minimum_alpha; uniform float minimum_alpha;
void mirrorClip(vec3 pos); void mirrorClip(vec3 pos);
@ -59,8 +59,9 @@ uniform float roughnessFactor;
in vec3 vary_normal; in vec3 vary_normal;
in vec3 vary_tangent; in vec3 vary_tangent;
flat in float vary_sign; flat in float vary_sign;
in vec2 normal_texcoord; in vec2 normal_uv;
in vec2 metallic_roughness_texcoord; in vec2 metallic_roughness_uv;
in vec2 occlusion_uv;
#endif #endif
// ================================== // ==================================
@ -164,7 +165,7 @@ void main()
vec3 pos = vary_position; vec3 pos = vary_position;
mirrorClip(pos); 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.rgb = srgb_to_linear(basecolor.rgb);
basecolor *= vertex_color; basecolor *= vertex_color;
@ -174,7 +175,7 @@ void main()
} }
vec3 emissive = emissiveColor; 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 #ifndef UNLIT
// from mikktspace.com // 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; float sign = vary_sign;
vec3 vN = vary_normal; vec3 vN = vary_normal;
vec3 vT = vary_tangent.xyz; vec3 vT = vary_tangent.xyz;
@ -198,8 +199,8 @@ void main()
// occlusion 1.0 // occlusion 1.0
// roughness 0.0 // roughness 0.0
// metal 0.0 // metal 0.0
vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb; vec3 orm = texture(metallicRoughnessMap, metallic_roughness_uv.xy).rgb;
orm.r = texture(occlusionMap, metallic_roughness_texcoord.xy).r; orm.r = texture(occlusionMap, occlusion_uv.xy).r;
orm.g *= roughnessFactor; orm.g *= roughnessFactor;
orm.b *= metallicFactor; orm.b *= metallicFactor;
#endif #endif

View File

@ -33,33 +33,97 @@ uniform mat4 projection_matrix;
uniform mat3 normal_matrix; uniform mat3 normal_matrix;
uniform mat4 modelview_projection_matrix; uniform mat4 modelview_projection_matrix;
#endif #endif
uniform mat4 texture_matrix0;
uniform vec4[2] texture_base_color_transform; uniform vec4[2] texture_base_color_transform;
uniform vec4[2] texture_normal_transform; uniform vec4[2] texture_normal_transform;
uniform vec4[2] texture_metallic_roughness_transform; uniform vec4[2] texture_metallic_roughness_transform;
uniform vec4[2] texture_emissive_transform; uniform vec4[2] texture_emissive_transform;
uniform vec4[2] texture_occlusion_transform;
in vec3 position; in vec3 position;
in vec4 diffuse_color; in vec4 diffuse_color;
in vec2 texcoord0; in vec2 texcoord0;
out vec2 base_color_texcoord; out vec2 base_color_uv;
out vec2 emissive_texcoord; out vec2 emissive_uv;
out vec4 vertex_color; out vec4 vertex_color;
out vec3 vary_position; out vec3 vary_position;
#ifndef UNLIT #ifndef UNLIT
in vec3 normal; in vec3 normal;
in vec4 tangent; in vec4 tangent;
out vec2 normal_texcoord; out vec2 normal_uv;
out vec2 metallic_roughness_texcoord; out vec2 metallic_roughness_uv;
out vec2 occlusion_uv;
out vec3 vary_tangent; out vec3 vary_tangent;
flat out float vary_sign; flat out float vary_sign;
out vec3 vary_normal; out vec3 vary_normal;
vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
#endif #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 #ifdef ALPHA_BLEND
@ -136,14 +200,41 @@ void main()
gl_Position = vert; gl_Position = vert;
#endif #endif
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); vec2 bcuv;
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0); 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 #ifndef UNLIT
normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0); vec2 normuv;
metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_transform, texture_matrix0); 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 #endif
#ifndef UNLIT #ifndef UNLIT
#ifdef HAS_SKIN #ifdef HAS_SKIN
@ -155,7 +246,7 @@ void main()
#endif #endif
n = normalize(n); 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_sign = tangent.w;
vary_normal = n; vary_normal = n;
#endif #endif

View File

@ -108,7 +108,8 @@ void Buffer::erase(Asset& asset, S32 offset, S32 length)
mData.erase(mData.begin() + offset, mData.begin() + offset + length); mData.erase(mData.begin() + offset, mData.begin() + offset + length);
mByteLength = mData.size(); llassert(mData.size() <= size_t(INT_MAX));
mByteLength = S32(mData.size());
for (BufferView& view : asset.mBufferViews) for (BufferView& view : asset.mBufferViews)
{ {
@ -141,7 +142,7 @@ bool Buffer::prep(Asset& asset)
} }
mData.resize(mByteLength); mData.resize(mByteLength);
if (!file.read((U8*)mData.data(), mData.size())) if (!file.read((U8*)mData.data(), mByteLength))
{ {
LL_WARNS("GLTF") << "Failed to load buffer data from asset: " << id << LL_ENDL; LL_WARNS("GLTF") << "Failed to load buffer data from asset: " << id << LL_ENDL;
return false; return false;

View File

@ -189,16 +189,15 @@ void Animation::Sampler::getFrameInfo(Asset& asset, F32 time, U32& frameIndex, F
if (mFrameTimes.size() > 1) if (mFrameTimes.size() > 1)
{ {
llassert(mFrameTimes.size() <= size_t(U32_MAX));
frameIndex = U32(mFrameTimes.size()) - 2;
t = 1.f;
if (time > mMaxTime) if (time > mMaxTime)
{ {
frameIndex = (U32)mFrameTimes.size() - 2;
t = 1.0f;
return; return;
} }
frameIndex = (U32)mFrameTimes.size() - 2;
t = 1.f;
for (U32 i = 0; i < (U32)mFrameTimes.size() - 1; i++) for (U32 i = 0; i < (U32)mFrameTimes.size() - 1; i++)
{ {
if (time >= mFrameTimes[i] && time < mFrameTimes[i + 1]) if (time >= mFrameTimes[i] && time < mFrameTimes[i + 1])
@ -382,7 +381,7 @@ void Skin::uploadMatrixPalette(Asset& asset)
glGenBuffers(1, &mUBO); glGenBuffers(1, &mUBO);
} }
U32 joint_count = llmin(max_joints, mJoints.size()); size_t joint_count = llmin<size_t>(max_joints, mJoints.size());
std::vector<mat4> t_mp; std::vector<mat4> t_mp;

View File

@ -45,7 +45,8 @@ namespace LL
namespace GLTF namespace GLTF
{ {
static std::unordered_set<std::string> ExtensionsSupported = { 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) 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(mIndex, "index", dst, INVALID_INDEX);
write(mTexCoord, "texCoord", dst, 0); 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) 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, "index", mIndex);
copy(src, "texCoord", mTexCoord); copy(src, "texCoord", mTexCoord);
copy_extensions(src, "KHR_texture_transform", &mTextureTransform);
} }
return *this; return *this;
@ -931,17 +952,16 @@ bool Material::TextureInfo::operator!=(const Material::TextureInfo& rhs) const
void Material::OcclusionTextureInfo::serialize(object& dst) const void Material::OcclusionTextureInfo::serialize(object& dst) const
{ {
write(mIndex, "index", dst, INVALID_INDEX); TextureInfo::serialize(dst);
write(mTexCoord, "texCoord", dst, 0);
write(mStrength, "strength", dst, 1.f); write(mStrength, "strength", dst, 1.f);
} }
const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src) const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src)
{ {
TextureInfo::operator=(src);
if (src.is_object()) if (src.is_object())
{ {
copy(src, "index", mIndex);
copy(src, "texCoord", mTexCoord);
copy(src, "strength", mStrength); copy(src, "strength", mStrength);
} }
@ -950,13 +970,13 @@ const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(
void Material::NormalTextureInfo::serialize(object& dst) const void Material::NormalTextureInfo::serialize(object& dst) const
{ {
write(mIndex, "index", dst, INVALID_INDEX); TextureInfo::serialize(dst);
write(mTexCoord, "texCoord", dst, 0);
write(mScale, "scale", dst, 1.f); write(mScale, "scale", dst, 1.f);
} }
const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src) const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src)
{ {
TextureInfo::operator=(src);
if (src.is_object()) if (src.is_object())
{ {
copy(src, "index", mIndex); 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 // 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 void Material::serialize(object& dst) const
{ {
write(mName, "name", dst); write(mName, "name", dst);

View File

@ -57,6 +57,21 @@ namespace LL
bool mPresent = false; 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 class Material
{ {
@ -82,9 +97,15 @@ namespace LL
S32 mIndex = INVALID_INDEX; S32 mIndex = INVALID_INDEX;
S32 mTexCoord = 0; S32 mTexCoord = 0;
TextureTransform mTextureTransform;
bool operator==(const TextureInfo& rhs) const; bool operator==(const TextureInfo& rhs) const;
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); const TextureInfo& operator=(const Value& src);
void serialize(boost::json::object& dst) const; void serialize(boost::json::object& dst) const;
}; };
@ -135,6 +156,8 @@ namespace LL
bool mDoubleSided = false; bool mDoubleSided = false;
Unlit mUnlit; Unlit mUnlit;
bool isMultiUV() const;
const Material& operator=(const Value& src); const Material& operator=(const Value& src);
void serialize(boost::json::object& dst) const; void serialize(boost::json::object& dst) const;
}; };

View File

@ -590,8 +590,8 @@ namespace LL
// Write all extensions to dst.extensions // Write all extensions to dst.extensions
// Usage: // Usage:
// write_extensions(dst, // write_extensions(dst,
// "KHR_materials_unlit", mUnlit, // mUnlit, "KHR_materials_unlit",
// "KHR_materials_pbrSpecularGlossiness", mPbrSpecularGlossiness); // mPbrSpecularGlossiness, "KHR_materials_pbrSpecularGlossiness");
// returns true if any of the extensions are written // returns true if any of the extensions are written
template<class... Types> template<class... Types>
inline bool write_extensions(boost::json::object& dst, Types... args) inline bool write_extensions(boost::json::object& dst, Types... args)
@ -816,6 +816,39 @@ namespace LL
return true; 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 // bool
template<> template<>
inline bool copy(const Value& src, bool& dst) inline bool copy(const Value& src, bool& dst)

View File

@ -42,30 +42,45 @@ using namespace boost::json;
// Mesh data useful for Mikktspace tangent generation (and flat normal generation) // Mesh data useful for Mikktspace tangent generation (and flat normal generation)
struct MikktMesh struct MikktMesh
{ {
std::vector<LLVector3> p; std::vector<LLVector3> p; //positions
std::vector<LLVector3> n; std::vector<LLVector3> n; //normals
std::vector<LLVector2> tc; std::vector<LLVector4> t; //tangents
std::vector<LLVector4> w; std::vector<LLVector2> tc0; //texcoords 0
std::vector<LLVector4> t; std::vector<LLVector2> tc1; //texcoords 1
std::vector<LLColor4U> c; std::vector<LLColor4U> c; //colors
std::vector<U64> j; std::vector<LLVector4> w; //weights
std::vector<U64> j; //joints
// initialize from src primitive and make an unrolled triangle list // initialize from src primitive and make an unrolled triangle list
// returns false if the Primitive cannot be converted to a triangle list // returns false if the Primitive cannot be converted to a triangle list
bool copy(const Primitive* prim) bool copy(const Primitive* prim)
{ {
bool indexed = !prim->mIndexArray.empty(); bool indexed = !prim->mIndexArray.empty();
U32 vert_count = indexed ? prim->mIndexArray.size() : prim->mPositions.size(); size_t vert_count = indexed ? prim->mIndexArray.size() : prim->mPositions.size();
if (prim->mMode != Primitive::Mode::TRIANGLES) size_t triangle_count = 0;
if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP ||
prim->mMode == Primitive::Mode::TRIANGLE_FAN)
{ {
LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32) prim->mMode << LL_ENDL; triangle_count = vert_count - 2;
}
else if (prim->mMode == Primitive::Mode::TRIANGLES)
{
triangle_count = vert_count / 3;
}
else
{
LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32)prim->mMode << LL_ENDL;
return false; return false;
} }
vert_count = triangle_count * 3;
llassert(vert_count <= size_t(U32_MAX)); // triangle_count will also naturally be under the limit
p.resize(vert_count); p.resize(vert_count);
n.resize(vert_count); n.resize(vert_count);
tc.resize(vert_count); tc0.resize(vert_count);
c.resize(vert_count); c.resize(vert_count);
bool has_normals = !prim->mNormals.empty(); bool has_normals = !prim->mNormals.empty();
@ -78,6 +93,7 @@ struct MikktMesh
{ {
t.resize(vert_count); t.resize(vert_count);
} }
bool rigged = !prim->mWeights.empty(); bool rigged = !prim->mWeights.empty();
if (rigged) if (rigged)
{ {
@ -85,23 +101,69 @@ struct MikktMesh
j.resize(vert_count); j.resize(vert_count);
} }
for (int 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()); for (U32 tri_idx = 0; tri_idx < U32(triangle_count); ++tri_idx)
tc[i].set(prim->mTexCoords[idx]); {
c[i] = prim->mColors[idx]; U32 idx[3];
if (has_normals) if (prim->mMode == Primitive::Mode::TRIANGLES)
{ {
n[i].set(prim->mNormals[idx].getF32ptr()); 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 (rigged) if (indexed)
{ {
w[i].set(prim->mWeights[idx].getF32ptr()); idx[0] = prim->mIndexArray[idx[0]];
j[i] = prim->mJoints[idx]; idx[1] = prim->mIndexArray[idx[1]];
idx[2] = prim->mIndexArray[idx[2]];
}
for (U32 v = 0; v < 3; ++v)
{
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]];
}
} }
} }
@ -110,8 +172,8 @@ struct MikktMesh
void genNormals() void genNormals()
{ {
U32 tri_count = p.size() / 3; size_t tri_count = p.size() / 3;
for (U32 i = 0; i < tri_count; ++i) for (size_t i = 0; i < tri_count; ++i)
{ {
LLVector3 v0 = p[i * 3]; LLVector3 v0 = p[i * 3];
LLVector3 v1 = p[i * 3 + 1]; LLVector3 v1 = p[i * 3 + 1];
@ -138,25 +200,34 @@ struct MikktMesh
void write(Primitive* prim) const void write(Primitive* prim) const
{ {
//re-weld //re-weld
meshopt_Stream mos[] = std::vector<meshopt_Stream> mos =
{ {
{ &p[0], sizeof(LLVector3), sizeof(LLVector3) }, { &p[0], sizeof(LLVector3), sizeof(LLVector3) },
{ &n[0], sizeof(LLVector3), sizeof(LLVector3) }, { &n[0], sizeof(LLVector3), sizeof(LLVector3) },
{ &t[0], sizeof(LLVector4), sizeof(LLVector4) }, { &t[0], sizeof(LLVector4), sizeof(LLVector4) },
{ &tc[0], sizeof(LLVector2), sizeof(LLVector2) }, { &tc0[0], sizeof(LLVector2), sizeof(LLVector2) },
{ &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }, { &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }
{ w.empty() ? nullptr : &w[0], sizeof(LLVector4), sizeof(LLVector4) },
{ j.empty() ? nullptr : &j[0], sizeof(U64), sizeof(U64) }
}; };
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; std::vector<U32> remap;
remap.resize(p.size()); remap.resize(p.size());
U32 stream_count = w.empty() ? 5 : 7; size_t 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->mNormals.resize(vert_count);
prim->mTangents.resize(vert_count); prim->mTangents.resize(vert_count);
prim->mPositions.resize(vert_count); prim->mPositions.resize(vert_count);
@ -166,7 +237,11 @@ struct MikktMesh
prim->mWeights.resize(vert_count); prim->mWeights.resize(vert_count);
prim->mJoints.resize(vert_count); prim->mJoints.resize(vert_count);
} }
if (!tc1.empty())
{
prim->mTexCoords1.resize(vert_count);
}
prim->mIndexArray.resize(remap.size()); prim->mIndexArray.resize(remap.size());
for (int i = 0; i < remap.size(); ++i) for (int i = 0; i < remap.size(); ++i)
@ -178,7 +253,7 @@ struct MikktMesh
prim->mPositions[dst_idx].load3(p[src_idx].mV); prim->mPositions[dst_idx].load3(p[src_idx].mV);
prim->mNormals[dst_idx].load3(n[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->mTangents[dst_idx].loadua(t[src_idx].mV);
prim->mColors[dst_idx] = c[src_idx]; prim->mColors[dst_idx] = c[src_idx];
@ -187,6 +262,11 @@ struct MikktMesh
prim->mWeights[dst_idx].loadua(w[src_idx].mV); prim->mWeights[dst_idx].loadua(w[src_idx].mV);
prim->mJoints[dst_idx] = j[src_idx]; prim->mJoints[dst_idx] = j[src_idx];
} }
if (!tc1.empty())
{
prim->mTexCoords1[dst_idx] = tc1[src_idx];
}
} }
prim->mGLMode = LLRender::TRIANGLES; prim->mGLMode = LLRender::TRIANGLES;
@ -210,8 +290,8 @@ struct MikktMesh
mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num) mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)
{ {
F32* uv = tc[face_num * 3 + vert_num].mV; F32* uv = tc0[face_num * 3 + vert_num].mV;
return mikk::float3(uv[0], uv[1], 1.0f); return mikk::float3(uv[0], 1.f-uv[1], 1.0f);
} }
mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num)
@ -228,6 +308,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) bool Primitive::prep(Asset& asset)
{ {
// allocate vertex buffer // allocate vertex buffer
@ -261,7 +349,11 @@ bool Primitive::prep(Asset& asset)
} }
else if (attribName == "TEXCOORD_0") 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") else if (attribName == "JOINTS_0")
{ {
@ -297,24 +389,28 @@ bool Primitive::prep(Asset& asset)
mask |= LLVertexBuffer::MAP_JOINT; 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; mask |= LLVertexBuffer::MAP_TEXCOORD0;
if (!mTexCoords1.empty())
{
mask |= LLVertexBuffer::MAP_TEXCOORD1;
}
if (mColors.empty()) if (mColors.empty())
{ {
mColors.resize(mPositions.size(), LLColor4U::white); mColors.resize(mPositions.size(), LLColor4U::white);
} }
mShaderVariant = 0;
// TODO: support colorless vertex buffers // TODO: support colorless vertex buffers
mask |= LLVertexBuffer::MAP_COLOR; mask |= LLVertexBuffer::MAP_COLOR;
mShaderVariant = 0;
bool unlit = false; bool unlit = false;
// bake material basecolor into color array // bake material basecolor into color array
@ -332,6 +428,11 @@ bool Primitive::prep(Asset& asset)
mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT; mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;
unlit = true; unlit = true;
} }
if (material.isMultiUV())
{
mShaderVariant |= LLGLSLShader::GLTFVariant::MULTI_UV;
}
} }
if (mNormals.empty() && !unlit) if (mNormals.empty() && !unlit)
@ -411,7 +512,10 @@ bool Primitive::prep(Asset& asset)
} }
mVertexBuffer = new LLVertexBuffer(mask); mVertexBuffer = new LLVertexBuffer(mask);
mVertexBuffer->allocateBuffer(mPositions.size(), mIndexArray.size() * 2); // double the size of the index buffer for 32-bit indices // we store these buffer sizes as S32 elsewhere
llassert(mPositions.size() <= size_t(S32_MAX));
llassert(mIndexArray.size() <= size_t(S32_MAX / 2));
mVertexBuffer->allocateBuffer(U32(mPositions.size()), U32(mIndexArray.size() * 2)); // double the size of the index buffer for 32-bit indices
mVertexBuffer->setBuffer(); mVertexBuffer->setBuffer();
mVertexBuffer->setPositionData(mPositions.data()); mVertexBuffer->setPositionData(mPositions.data());
@ -434,16 +538,18 @@ bool Primitive::prep(Asset& asset)
} }
// flip texcoord y, upload, then flip back (keep the off-spec data in vram only) // flip texcoord y, upload, then flip back (keep the off-spec data in vram only)
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());
mVertexBuffer->setTexCoordData(mTexCoords.data()); vertical_flip(mTexCoords1);
for (auto& tc : mTexCoords)
{
tc[1] = 1.f - tc[1];
} }
if (!mIndexArray.empty()) if (!mIndexArray.empty())
{ {
mVertexBuffer->setIndexData(mIndexArray.data()); mVertexBuffer->setIndexData(mIndexArray.data());
@ -453,10 +559,13 @@ bool Primitive::prep(Asset& asset)
mVertexBuffer->unbind(); mVertexBuffer->unbind();
Material& material = asset.mMaterials[mMaterial]; if (mMaterial != INVALID_INDEX)
if (material.mAlphaMode == Material::AlphaMode::BLEND)
{ {
mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND; Material& material = asset.mMaterials[mMaterial];
if (material.mAlphaMode == Material::AlphaMode::BLEND)
{
mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND;
}
} }
return true; return true;
@ -614,13 +723,13 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,
//create a proxy LLVolumeFace for the raycast //create a proxy LLVolumeFace for the raycast
LLVolumeFace face; LLVolumeFace face;
face.mPositions = mPositions.data(); face.mPositions = mPositions.data();
face.mTexCoords = mTexCoords.data(); face.mTexCoords = mTexCoords0.data();
face.mNormals = mNormals.data(); face.mNormals = mNormals.data();
face.mTangents = mTangents.data(); face.mTangents = mTangents.data();
face.mIndices = nullptr; // unreferenced face.mIndices = nullptr; // unreferenced
face.mNumIndices = (S32)mIndexArray.size(); face.mNumIndices = S32(mIndexArray.size());
face.mNumVertices = (S32)mPositions.size(); face.mNumVertices = S32(mPositions.size());
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out);
intersect.traverse(mOctree); intersect.traverse(mOctree);

View File

@ -58,7 +58,8 @@ namespace LL
LLPointer<LLVertexBuffer> mVertexBuffer; LLPointer<LLVertexBuffer> mVertexBuffer;
// CPU copy of mesh data, keep these as LLVector types for compatibility with raycasting code // 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> mNormals;
std::vector<LLVector4a> mTangents; std::vector<LLVector4a> mTangents;
std::vector<LLVector4a> mPositions; std::vector<LLVector4a> mPositions;

View File

@ -244,7 +244,8 @@ void GLTFSceneManager::uploadSelection()
LLFileSystem cache(assetId, LLAssetType::AT_GLTF_BIN, LLFileSystem::WRITE); LLFileSystem cache(assetId, LLAssetType::AT_GLTF_BIN, LLFileSystem::WRITE);
auto& data = mUploadingAsset->mBuffers[idx].mData; auto& data = mUploadingAsset->mBuffers[idx].mData;
cache.write((const U8*)data.data(), data.size()); llassert(data.size() <= size_t(S32_MAX));
cache.write((const U8 *) data.data(), S32(data.size()));
} }
}; };
#if GLTF_SIM_SUPPORT #if GLTF_SIM_SUPPORT
@ -399,8 +400,9 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a
{ {
LLFileSystem file(id, asset_type, LLFileSystem::READ); LLFileSystem file(id, asset_type, LLFileSystem::READ);
std::string data; std::string data;
data.resize(file.getSize()); S32 file_size = file.getSize();
file.read((U8*)data.data(), data.size()); data.resize(file_size);
file.read((U8*)data.data(), file_size);
boost::json::value json = boost::json::parse(data); boost::json::value json = boost::json::parse(data);
@ -479,7 +481,8 @@ void GLTFSceneManager::update()
LLFileSystem cache(assetId, LLAssetType::AT_GLTF, LLFileSystem::WRITE); LLFileSystem cache(assetId, LLAssetType::AT_GLTF, LLFileSystem::WRITE);
LL_INFOS("GLTF") << "Uploaded GLTF json: " << assetId << LL_ENDL; LL_INFOS("GLTF") << "Uploaded GLTF json: " << assetId << LL_ENDL;
cache.write((const U8 *) buffer.c_str(), buffer.size()); llassert(buffer.size() <= size_t(S32_MAX));
cache.write((const U8 *) buffer.c_str(), S32(buffer.size()));
mUploadingAsset = nullptr; mUploadingAsset = nullptr;
} }
@ -549,10 +552,16 @@ void GLTFSceneManager::render(bool opaque, bool rigged, bool unlit)
void GLTFSceneManager::render(U8 variant) void GLTFSceneManager::render(U8 variant)
{ {
// for debugging, just render the whole scene as opaque // just render the whole scene by traversing the whole scenegraph
// by traversing the whole scenegraph // Assumes camera transform is already set and appropriate shader is already bound.
// Assumes camera transform is already set and // Eventually we'll want a smarter render pipe that has pre-sorted the scene graph
// appropriate shader is already boundd // 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); gGL.matrixMode(LLRender::MM_MODELVIEW);
@ -663,11 +672,30 @@ static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info,
{ {
if (info.mIndex != INVALID_INDEX) 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) if (tex)
{ {
tex->addTextureStats(2048.f * 2048.f); 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 else
{ {
@ -710,10 +738,10 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)
bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, material.mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep); bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, material.mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep);
F32 base_color_packed[8]; F32 tf[8];
//mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed); material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf);
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed); shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf);
shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed); shader->uniform1i(LLShaderMgr::BASE_COLOR_TEXCOORD, material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord());
if (!LLPipeline::sShadowRender) if (!LLPipeline::sShadowRender)
{ {
@ -728,20 +756,21 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)
shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, material.mPbrMetallicRoughness.mMetallicFactor); shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, material.mPbrMetallicRoughness.mMetallicFactor);
shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(material.mEmissiveFactor)); shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(material.mEmissiveFactor));
F32 normal_packed[8]; material.mNormalTexture.mTextureTransform.getPacked(tf);
//mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf);
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); shader->uniform1i(LLShaderMgr::NORMAL_TEXCOORD, material.mNormalTexture.getTexCoord());
shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed);
F32 metallic_roughness_packed[8]; material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf);
//mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed); shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf);
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed); shader->uniform1i(LLShaderMgr::METALLIC_ROUGHNESS_TEXCOORD, material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord());
shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed);
F32 emissive_packed[8]; material.mOcclusionTexture.mTextureTransform.getPacked(tf);
//mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed); shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf);
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed); shader->uniform1i(LLShaderMgr::OCCLUSION_TEXCOORD, material.mOcclusionTexture.getTexCoord());
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());
} }
} }

View File

@ -220,8 +220,8 @@ bool LLViewerDynamicTexture::updateAllInstances()
if (dynamicTexture->needsRender()) if (dynamicTexture->needsRender())
{ {
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("needsRender"); LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("needsRender");
llassert(dynamicTexture->getFullWidth() <= (S32)LLPipeline::MAX_BAKE_WIDTH); llassert(dynamicTexture->getFullWidth() <= S32(LLPipeline::MAX_BAKE_WIDTH));
llassert(dynamicTexture->getFullHeight() <= (S32)LLPipeline::MAX_BAKE_WIDTH); llassert(dynamicTexture->getFullHeight() <= S32(LLPipeline::MAX_BAKE_WIDTH));
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);

View File

@ -1973,7 +1973,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
LL_DEBUGS() << "no region set" << LL_ENDL; LL_DEBUGS() << "no region set" << LL_ENDL;
getChild<LLUICtrl>("region_text")->setValue(LLSD("")); getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
} }
// Update visibility of terrain swatches, etc // Update visibility of terrain swatches, etc
refresh(); refresh();
@ -2115,7 +2115,7 @@ bool LLPanelRegionTerrainInfo::sendUpdate()
for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
{ {
LLPointer<LLGLTFMaterial> mat_override = new LLGLTFMaterial(); LLPointer<LLGLTFMaterial> mat_override = new LLGLTFMaterial();
const bool transform_controls_valid = mMaterialScaleUCtrl[i] && mMaterialScaleVCtrl[i] && mMaterialRotationCtrl[i] && mMaterialOffsetUCtrl[i] && mMaterialOffsetVCtrl[i]; const bool transform_controls_valid = mMaterialScaleUCtrl[i] && mMaterialScaleVCtrl[i] && mMaterialRotationCtrl[i] && mMaterialOffsetUCtrl[i] && mMaterialOffsetVCtrl[i];
if (transform_controls_valid) if (transform_controls_valid)
{ {

View File

@ -1,4 +1,4 @@
/** /**
* @file llfloaterregioninfo.h * @file llfloaterregioninfo.h
* @author Aaron Brashears * @author Aaron Brashears
* @brief Declaration of the region info and controls floater and panels. * @brief Declaration of the region info and controls floater and panels.
@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2004&license=viewerlgpl$ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2010, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -108,14 +108,14 @@ public:
// from LLPanel // from LLPanel
void refresh() override; void refresh() override;
void onRegionChanged(); void onRegionChanged();
void requestRegionInfo(); void requestRegionInfo();
void enableTopButtons(); void enableTopButtons();
void disableTopButtons(); void disableTopButtons();
private: private:
LLFloaterRegionInfo(const LLSD& seed); LLFloaterRegionInfo(const LLSD& seed);
~LLFloaterRegionInfo(); ~LLFloaterRegionInfo();
@ -144,31 +144,31 @@ class LLPanelRegionInfo : public LLPanel
{ {
public: public:
LLPanelRegionInfo(); LLPanelRegionInfo();
void onBtnSet(); void onBtnSet();
void onChangeChildCtrl(LLUICtrl* ctrl); void onChangeChildCtrl(LLUICtrl* ctrl);
void onChangeAnything(); void onChangeAnything();
static void onChangeText(LLLineEditor* caller, void* user_data); static void onChangeText(LLLineEditor* caller, void* user_data);
virtual bool refreshFromRegion(LLViewerRegion* region); virtual bool refreshFromRegion(LLViewerRegion* region);
virtual bool estateUpdate(LLMessageSystem* msg) { return true; } virtual bool estateUpdate(LLMessageSystem* msg) { return true; }
bool postBuild() override; bool postBuild() override;
virtual void updateChild(LLUICtrl* child_ctrl); virtual void updateChild(LLUICtrl* child_ctrl);
void enableButton(const std::string& btn_name, bool enable = true); void enableButton(const std::string& btn_name, bool enable = true);
void disableButton(const std::string& btn_name); void disableButton(const std::string& btn_name);
void onClickManageTelehub(); void onClickManageTelehub();
protected: protected:
void initCtrl(const std::string& name); void initCtrl(const std::string& name);
template<typename CTRL> void initAndSetCtrl(CTRL*& ctrl, const std::string& name); template<typename CTRL> void initAndSetCtrl(CTRL*& ctrl, const std::string& name);
// Returns true if update sent and apply button should be // Returns true if update sent and apply button should be
// disabled. // disabled.
virtual bool sendUpdate() { return true; } virtual bool sendUpdate() { return true; }
typedef std::vector<std::string> strings_t; typedef std::vector<std::string> strings_t;
//typedef std::vector<U32> integers_t; //typedef std::vector<U32> integers_t;
void sendEstateOwnerMessage( void sendEstateOwnerMessage(
@ -176,8 +176,8 @@ protected:
const std::string& request, const std::string& request,
const LLUUID& invoice, const LLUUID& invoice,
const strings_t& strings); const strings_t& strings);
// member data // member data
LLHost mHost; LLHost mHost;
}; };
@ -208,16 +208,16 @@ protected:
class LLPanelRegionGeneralInfo : public LLPanelRegionInfo class LLPanelRegionGeneralInfo : public LLPanelRegionInfo
{ {
public: public:
LLPanelRegionGeneralInfo() LLPanelRegionGeneralInfo()
: LLPanelRegionInfo() {} : LLPanelRegionInfo() {}
~LLPanelRegionGeneralInfo() {} ~LLPanelRegionGeneralInfo() {}
bool refreshFromRegion(LLViewerRegion* region) override; bool refreshFromRegion(LLViewerRegion* region) override;
bool postBuild() override; bool postBuild() override;
void onBtnSet(); void onBtnSet();
void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;} void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;}
@ -245,9 +245,9 @@ public:
~LLPanelRegionDebugInfo() {} ~LLPanelRegionDebugInfo() {}
bool postBuild() override; bool postBuild() override;
bool refreshFromRegion(LLViewerRegion* region) override; bool refreshFromRegion(LLViewerRegion* region) override;
protected: protected:
bool sendUpdate() override; bool sendUpdate() override;
@ -261,7 +261,7 @@ protected:
bool callbackRestart(const LLSD& notification, const LLSD& response, const LLSD& seconds); // Ansariel, added seconds for FIRE-1073 bool callbackRestart(const LLSD& notification, const LLSD& response, const LLSD& seconds); // Ansariel, added seconds for FIRE-1073
static void onClickCancelRestart(void* data); static void onClickCancelRestart(void* data);
static void onClickDebugConsole(void* data); static void onClickDebugConsole(void* data);
private: private:
LLUUID mTargetAvatar; LLUUID mTargetAvatar;
}; };
@ -275,9 +275,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
public: public:
LLPanelRegionTerrainInfo(); LLPanelRegionTerrainInfo();
~LLPanelRegionTerrainInfo() {} ~LLPanelRegionTerrainInfo() {}
bool postBuild() override; bool postBuild() override;
bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator
void setEnvControls(bool available); // Whether environment settings are available for this region void setEnvControls(bool available); // Whether environment settings are available for this region
@ -286,7 +286,7 @@ public:
bool validateTextureHeights(); bool validateTextureHeights();
//static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button
void onSelectMaterialType(); void onSelectMaterialType();
void updateForMaterialType(); void updateForMaterialType();
@ -326,13 +326,13 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
{ {
public: public:
static void initDispatch(LLDispatcher& dispatch); static void initDispatch(LLDispatcher& dispatch);
void onChangeFixedSun(); void onChangeFixedSun();
void onChangeUseGlobalTime(); void onChangeUseGlobalTime();
void onChangeAccessOverride(); void onChangeAccessOverride();
void onClickEditSky(); void onClickEditSky();
void onClickEditSkyHelp(); void onClickEditSkyHelp();
void onClickEditDayCycle(); void onClickEditDayCycle();
void onClickEditDayCycleHelp(); void onClickEditDayCycleHelp();
@ -344,26 +344,26 @@ public:
void onKickUserCommit(const uuid_vec_t& ids); void onKickUserCommit(const uuid_vec_t& ids);
static void onClickMessageEstate(void* data); static void onClickMessageEstate(void* data);
bool onMessageCommit(const LLSD& notification, const LLSD& response); bool onMessageCommit(const LLSD& notification, const LLSD& response);
LLPanelEstateInfo(); LLPanelEstateInfo();
~LLPanelEstateInfo() {} ~LLPanelEstateInfo() {}
void updateControls(LLViewerRegion* region); void updateControls(LLViewerRegion* region);
static void updateEstateName(const std::string& name); static void updateEstateName(const std::string& name);
static void updateEstateOwnerName(const std::string& name); static void updateEstateOwnerName(const std::string& name);
bool refreshFromRegion(LLViewerRegion* region) override; bool refreshFromRegion(LLViewerRegion* region) override;
bool estateUpdate(LLMessageSystem* msg) override; bool estateUpdate(LLMessageSystem* msg) override;
bool postBuild() override; bool postBuild() override;
void updateChild(LLUICtrl* child_ctrl) override; void updateChild(LLUICtrl* child_ctrl) override;
void refresh() override; void refresh() override;
void refreshFromEstate(); void refreshFromEstate();
static bool isLindenEstate(); static bool isLindenEstate();
const std::string getOwnerName() const; const std::string getOwnerName() const;
void setOwnerName(const std::string& name); void setOwnerName(const std::string& name);
@ -374,7 +374,7 @@ protected:
void commitEstateAccess(); void commitEstateAccess();
void commitEstateManagers(); void commitEstateManagers();
bool checkSunHourSlider(LLUICtrl* child_ctrl); bool checkSunHourSlider(LLUICtrl* child_ctrl);
U32 mEstateID; U32 mEstateID;
@ -387,7 +387,7 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo
public: public:
LLPanelEstateCovenant(); LLPanelEstateCovenant();
~LLPanelEstateCovenant() {} ~LLPanelEstateCovenant() {}
bool postBuild() override; bool postBuild() override;
void updateChild(LLUICtrl* child_ctrl) override; void updateChild(LLUICtrl* child_ctrl) override;
bool refreshFromRegion(LLViewerRegion* region) override; bool refreshFromRegion(LLViewerRegion* region) override;
@ -450,7 +450,7 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
public: public:
LLPanelRegionExperiences(){} LLPanelRegionExperiences(){}
bool postBuild() override; bool postBuild() override;
static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response);
static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id);
@ -515,7 +515,7 @@ private:
void onAllowedSearchEdit(const std::string& search_string); void onAllowedSearchEdit(const std::string& search_string);
void onAllowedGroupsSearchEdit(const std::string& search_string); void onAllowedGroupsSearchEdit(const std::string& search_string);
void onBannedSearchEdit(const std::string& search_string); void onBannedSearchEdit(const std::string& search_string);
// Group picker callback is different, can't use core methods below // Group picker callback is different, can't use core methods below
bool addAllowedGroup(const LLSD& notification, const LLSD& response); bool addAllowedGroup(const LLSD& notification, const LLSD& response);
void addAllowedGroup2(LLUUID id); void addAllowedGroup2(LLUUID id);

View File

@ -359,7 +359,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
res /= 2; res /= 2;
S32 mip = i - ((S32)mMipChain.size() - mips); llassert(mMipChain.size() <= size_t(S32_MAX));
GLint mip = i - (S32(mMipChain.size()) - mips);
if (mip >= 0) if (mip >= 0)
{ {
@ -487,7 +488,8 @@ void LLHeroProbeManager::updateUniforms()
mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius; mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius;
} }
mHeroData.heroMipCount = (GLint)mMipChain.size(); llassert(mMipChain.size() <= size_t(S32_MAX));
mHeroData.heroMipCount = S32(mMipChain.size());
} }
void LLHeroProbeManager::renderDebug() void LLHeroProbeManager::renderDebug()

View File

@ -2398,7 +2398,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
message_data["region_id"].asUUID(), message_data["region_id"].asUUID(),
position, position,
local_bin_bucket.data(), local_bin_bucket.data(),
local_bin_bucket.size(), S32(local_bin_bucket.size()),
local_sender, local_sender,
message_data["asset_id"].asUUID()); message_data["asset_id"].asUUID());
}); });

View File

@ -957,11 +957,11 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
else if (root_id.notNull()) else if (root_id.notNull())
{ {
cat_array_t* cats = get_ptr_in_map(mParentChildCategoryTree, root_id); cat_array_t* cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
if (cats) if(cats)
{ {
for (auto& p_cat : *cats) for (auto& p_cat : *cats)
{ {
if (p_cat && p_cat->getPreferredType() == preferred_type) if(p_cat && p_cat->getPreferredType() == preferred_type)
{ {
const LLUUID& folder_id = p_cat->getUUID(); const LLUUID& folder_id = p_cat->getUUID();
if (rv.isNull() || folder_id < rv) if (rv.isNull() || folder_id < rv)

View File

@ -264,12 +264,12 @@ bool LLTinyGLTFHelper::saveModel(const std::string& filename, tinygltf::Model& m
std::string filename_lc = filename; std::string filename_lc = filename;
LLStringUtil::toLower(filename_lc); LLStringUtil::toLower(filename_lc);
bool embed_images = false; bool embed_images = false;
bool embed_buffers = false; bool embed_buffers = false;
bool pretty_print = true; bool pretty_print = true;
bool write_binary = false; bool write_binary = false;
if (std::string::npos == filename_lc.rfind(".gltf")) if (std::string::npos == filename_lc.rfind(".gltf"))
{ // file is binary { // file is binary

View File

@ -2768,7 +2768,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventory(
// *HACK: In order to resolve SL-22177, we need to block drags // *HACK: In order to resolve SL-22177, we need to block drags
// from notecards and objects onto other objects. // from notecards and objects onto other objects.
if ((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
{ {
return ACCEPT_NO; return ACCEPT_NO;
} }

View File

@ -253,7 +253,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.mName = shader.mName.c_str();
variant.mFeatures = shader.mFeatures; variant.mFeatures = shader.mFeatures;
@ -275,6 +275,11 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool
variant.addPermutation("UNLIT", "1"); variant.addPermutation("UNLIT", "1");
} }
if (multi_uv)
{
variant.addPermutation("MULTI_UV", "1");
}
if (alpha_blend) if (alpha_blend)
{ {
variant.addPermutation("ALPHA_BLEND", "1"); variant.addPermutation("ALPHA_BLEND", "1");
@ -321,8 +326,9 @@ static bool make_gltf_variants(LLGLSLShader& shader, bool use_sun_shadow)
bool alpha_blend = i & LLGLSLShader::GLTFVariant::ALPHA_BLEND; bool alpha_blend = i & LLGLSLShader::GLTFVariant::ALPHA_BLEND;
bool rigged = i & LLGLSLShader::GLTFVariant::RIGGED; bool rigged = i & LLGLSLShader::GLTFVariant::RIGGED;
bool unlit = i & LLGLSLShader::GLTFVariant::UNLIT; 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; return false;
} }

View File

@ -349,7 +349,7 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const s
return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id);
} }
//static //static
LLImageRaw* LLViewerTextureManager::getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype) LLImageRaw* LLViewerTextureManager::getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype)
{ {
return gTextureList.getRawImageFromMemory(data, size, mimetype); return gTextureList.getRawImageFromMemory(data, size, mimetype);

View File

@ -197,7 +197,7 @@ private: // PoundLife - Improved Object Inspect
LLGLenum primary_format = 0, LLGLenum primary_format = 0,
const LLUUID& force_id = LLUUID::null const LLUUID& force_id = LLUUID::null
); );
LLImageRaw* getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype); LLImageRaw* getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype);
LLViewerFetchedTexture* getImageFromMemory(const U8* data, U32 size, std::string_view mimetype); LLViewerFetchedTexture* getImageFromMemory(const U8* data, U32 size, std::string_view mimetype);

View File

@ -1,25 +1,25 @@
/** /**
* @file llvlcomposition.cpp * @file llvlcomposition.cpp
* @brief Viewer-side representation of a composition layer... * @brief Viewer-side representation of a composition layer...
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2010, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -428,8 +428,7 @@ const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT]
LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
LLTerrainMaterials(), LLTerrainMaterials(),
LLViewerLayer(width, scale), LLViewerLayer(width, scale)
mParamsReady(false)
{ {
// Load Terrain Textures - Original ones // Load Terrain Textures - Original ones
const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures(); const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures();
@ -471,7 +470,7 @@ bool LLVLComposition::generateHeights(const F32 x, const F32 y,
llassert(mSurfacep); llassert(mSurfacep);
if (!mSurfacep || !mSurfacep->getRegion()) if (!mSurfacep || !mSurfacep->getRegion())
{ {
// We don't always have the region yet here.... // We don't always have the region yet here....
return false; return false;
@ -542,7 +541,7 @@ bool LLVLComposition::generateHeights(const F32 x, const F32 y,
vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv; vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv;
vec[2] = height*zScaleInv; vec[2] = height*zScaleInv;
// //
// Choose material value by adding to the exact height a random value // Choose material value by adding to the exact height a random value
// //
vec1[0] = vec[0]*(0.2222222222f); vec1[0] = vec[0]*(0.2222222222f);
vec1[1] = vec[1]*(0.2222222222f); vec1[1] = vec[1]*(0.2222222222f);
@ -989,7 +988,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
{ {
unboost_minimap_material(mDetailMaterials[i]); unboost_minimap_material(mDetailMaterials[i]);
} }
return true; return true;
} }

View File

@ -1,25 +1,25 @@
/** /**
* @file llvlcomposition.h * @file llvlcomposition.h
* @brief Viewer-side representation of a composition layer... * @brief Viewer-side representation of a composition layer...
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2010, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -115,8 +115,7 @@ public:
bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height); bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
bool generateComposition(); bool generateComposition();
// Generate texture from composition values. // Generate texture from composition values.
bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height); bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
bool generateTexture(const F32 x, const F32 y, const F32 width, const F32 height);
// Use these as indeces ito the get/setters below that use 'corner' // Use these as indeces ito the get/setters below that use 'corner'
enum ECorner enum ECorner

View File

@ -1982,9 +1982,8 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL
LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle); LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle);
U32 num_entries = 0; U32 num_entries = 0;
U32 inmem_entries = 0;
U32 skipped = 0; U32 skipped = 0;
inmem_entries = (U32)cache_extras_entry_map.size(); size_t inmem_entries = cache_extras_entry_map.size();
for (auto [local_id, entry] : cache_extras_entry_map) for (auto [local_id, entry] : cache_extras_entry_map)
{ {
// Only write out GLTFOverrides that we can actually apply again on import. // Only write out GLTFOverrides that we can actually apply again on import.

View File

@ -4865,6 +4865,7 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const
bool LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp, bool LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, bool pick_transparent, bool pick_rigged, bool pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{ {
if (!mbCanSelect if (!mbCanSelect
|| mDrawable->isDead() || mDrawable->isDead()

View File

@ -3,7 +3,6 @@
border="true" border="true"
follows="top|left" follows="top|left"
height="460" height="460"
help_topic="panel_region_terrain_tab"
label="Terrain" label="Terrain"
layout="topleft" layout="topleft"
left="0" left="0"
@ -225,13 +224,12 @@
left="0" left="0"
name="terrain_tabs" name="terrain_tabs"
tab_position="top" tab_position="top"
tab_width="100" tab_width="110"
tab_padding_right="3" tab_padding_right="3"
top_pad="0" top_pad="0"
width="700"> width="700">
<panel <panel
border="true" border="true"
class="panel_settings_terrain_elevation"
filename="panel_settings_terrain_elevation.xml" filename="panel_settings_terrain_elevation.xml"
label="Elevation" label="Elevation"
layout="topleft" layout="topleft"
@ -240,7 +238,6 @@
name="terrain_elevation_panel" /> name="terrain_elevation_panel" />
<panel <panel
border="true" border="true"
class="panel_settings_terrain_transform"
filename="panel_settings_terrain_transform.xml" filename="panel_settings_terrain_transform.xml"
label="Transforms" label="Transforms"
layout="topleft" layout="topleft"
@ -256,8 +253,8 @@
height="20" height="20"
label="Apply" label="Apply"
layout="topleft" layout="topleft"
left="353" left="351"
name="apply_btn" name="apply_btn"
top_delta="290" top_delta="310"
width="100" /> width="100" />
</panel> </panel>

View File

@ -7,6 +7,62 @@
left="0" left="0"
name="panel_settings_terrain_transform" name="panel_settings_terrain_transform"
top="0"> top="0">
<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 <text
type="string" type="string"
length="1" length="1"
@ -17,19 +73,10 @@
layout="topleft" layout="topleft"
name="terrain0ScaleU_label" name="terrain0ScaleU_label"
left="10" left="10"
top_pad="3" top_pad="0"
width="170"> width="170">
Scale u Scale u
</text> </text>
<view_border
bevel_style="none"
follows="top|left"
height="0"
layout="topleft"
left="8"
top_pad="-2"
name="terrain0ScaleU_horizontal"
width="430" />
<spinner <spinner
follows="left|top" follows="left|top"
height="19" height="19"
@ -37,7 +84,7 @@
label="Scale u" label="Scale u"
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left="10" left="46"
min_val="-100" min_val="-100"
max_val="100" max_val="100"
name="terrain0ScaleU" name="terrain0ScaleU"
@ -78,6 +125,15 @@
max_val="100" max_val="100"
name="terrain3ScaleU" name="terrain3ScaleU"
width="64" /> 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 <text
type="string" type="string"
length="1" length="1"
@ -88,19 +144,10 @@
layout="topleft" layout="topleft"
name="terrain0ScaleV_label" name="terrain0ScaleV_label"
left="10" left="10"
top_pad="3" top_pad="0"
width="170"> width="170">
Scale v Scale v
</text> </text>
<view_border
bevel_style="none"
follows="top|left"
height="0"
layout="topleft"
left="8"
top_pad="-2"
name="terrain0ScaleV_horizontal"
width="430" />
<spinner <spinner
follows="left|top" follows="left|top"
height="19" height="19"
@ -108,7 +155,7 @@
label="Scale v" label="Scale v"
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left="10" left="46"
min_val="-100" min_val="-100"
max_val="100" max_val="100"
name="terrain0ScaleV" name="terrain0ScaleV"
@ -149,6 +196,15 @@
max_val="100" max_val="100"
name="terrain3ScaleV" name="terrain3ScaleV"
width="64" /> 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 <text
type="string" type="string"
length="1" length="1"
@ -159,19 +215,10 @@
layout="topleft" layout="topleft"
name="terrain0Rotation_label" name="terrain0Rotation_label"
left="10" left="10"
top_pad="3" top_pad="0"
width="170"> width="170">
Rotation Rotation
</text> </text>
<view_border
bevel_style="none"
follows="top|left"
height="0"
layout="topleft"
left="8"
top_pad="-2"
name="terrain0Rotation_horizontal"
width="430" />
<spinner <spinner
follows="left|top" follows="left|top"
height="19" height="19"
@ -179,7 +226,7 @@
label="Rotation" label="Rotation"
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left="10" left="46"
min_val="-360" min_val="-360"
max_val="360" max_val="360"
name="terrain0Rotation" name="terrain0Rotation"
@ -192,8 +239,8 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-360"
max_val="100" max_val="360"
name="terrain1Rotation" name="terrain1Rotation"
width="64" /> width="64" />
<spinner <spinner
@ -204,8 +251,8 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-360"
max_val="100" max_val="360"
name="terrain2Rotation" name="terrain2Rotation"
width="64" /> width="64" />
<spinner <spinner
@ -216,10 +263,19 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-360"
max_val="100" max_val="360"
name="terrain3Rotation" name="terrain3Rotation"
width="64" /> 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 <text
type="string" type="string"
length="1" length="1"
@ -230,19 +286,10 @@
layout="topleft" layout="topleft"
name="terrain0OffsetU_label" name="terrain0OffsetU_label"
left="10" left="10"
top_pad="3" top_pad="0"
width="170"> width="170">
Offset y Offset y
</text> </text>
<view_border
bevel_style="none"
follows="top|left"
height="0"
layout="topleft"
left="8"
top_pad="-2"
name="terrain0OffsetU_horizontal"
width="430" />
<spinner <spinner
follows="left|top" follows="left|top"
height="19" height="19"
@ -250,7 +297,7 @@
label="Offset u" label="Offset u"
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left="10" left="46"
min_val="-999" min_val="-999"
max_val="999" max_val="999"
name="terrain0OffsetU" name="terrain0OffsetU"
@ -263,8 +310,8 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-999"
max_val="100" max_val="999"
name="terrain1OffsetU" name="terrain1OffsetU"
width="64" /> width="64" />
<spinner <spinner
@ -275,8 +322,8 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-999"
max_val="100" max_val="999"
name="terrain2OffsetU" name="terrain2OffsetU"
width="64" /> width="64" />
<spinner <spinner
@ -287,10 +334,19 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-999"
max_val="100" max_val="999"
name="terrain3OffsetU" name="terrain3OffsetU"
width="64" /> 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 <text
type="string" type="string"
length="1" length="1"
@ -301,19 +357,10 @@
layout="topleft" layout="topleft"
name="terrain0OffsetV_label" name="terrain0OffsetV_label"
left="10" left="10"
top_pad="3" top_pad="0"
width="170"> width="170">
Offset v Offset v
</text> </text>
<view_border
bevel_style="none"
follows="top|left"
height="0"
layout="topleft"
left="8"
top_pad="-2"
name="terrain0OffsetV_horizontal"
width="430" />
<spinner <spinner
follows="left|top" follows="left|top"
height="19" height="19"
@ -321,7 +368,7 @@
label="Offset v" label="Offset v"
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left="10" left="46"
min_val="-999" min_val="-999"
max_val="999" max_val="999"
name="terrain0OffsetV" name="terrain0OffsetV"
@ -334,8 +381,8 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-999"
max_val="100" max_val="999"
name="terrain1OffsetV" name="terrain1OffsetV"
width="64" /> width="64" />
<spinner <spinner
@ -346,8 +393,8 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-999"
max_val="100" max_val="999"
name="terrain2OffsetV" name="terrain2OffsetV"
width="64" /> width="64" />
<spinner <spinner
@ -358,8 +405,17 @@
label_width="0" label_width="0"
layout="topleft" layout="topleft"
left_delta="110" left_delta="110"
min_val="-100" min_val="-999"
max_val="100" max_val="999"
name="terrain3OffsetV" name="terrain3OffsetV"
width="64" /> 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> </panel>