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.cppmaster
commit
050d2fefab
|
|
@ -2,6 +2,7 @@
|
|||
1b68f71348ecf3983b76b40d7940da8377f049b7
|
||||
# Trim trailing whitespace
|
||||
a0b3021bdcf76859054fda8e30abb3ed47749e83
|
||||
8444cd9562a6a7b755fcb075864e205122354192
|
||||
# Wrong line endings
|
||||
1b67dd855c41f5a0cda7ec2a68d98071986ca703
|
||||
6cc7dd09d5e69cf57e6de7fb568a0ad2693f9c9a
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
# 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).
|
||||
|
||||
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 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 two PBR terrain regions (except due to movement of the avatar, which is not covered by this test plan)
|
||||
|
||||
## Feature Gating
|
||||
|
||||
|
|
@ -35,3 +36,17 @@ Availability of PBR textures varies by machine and graphics setting:
|
|||
### 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 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.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ All tests in this section assume the PBR terrain feature flag is enabled, and th
|
|||
|
||||
### 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.
|
||||
|
||||
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 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
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -61,14 +61,14 @@
|
|||
#include <excpt.h>
|
||||
#endif
|
||||
|
||||
// static
|
||||
// static
|
||||
bool LLCoros::on_main_coro()
|
||||
{
|
||||
if (!LLCoros::instanceExists() || LLCoros::getName().empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,25 +3,25 @@
|
|||
* @author Nat Goodspeed
|
||||
* @date 2009-06-02
|
||||
* @brief Manage running boost::coroutine instances
|
||||
*
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
|
@ -100,7 +100,7 @@ public:
|
|||
static bool on_main_coro();
|
||||
|
||||
// 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())
|
||||
static bool on_main_thread_main_coro();
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ public:
|
|||
* LLCoros::launch()).
|
||||
*/
|
||||
static std::string getName();
|
||||
|
||||
|
||||
/**
|
||||
* rethrow() is called by the thread's main fiber to propagate an
|
||||
* exception from any coroutine into the main fiber, where it can engage
|
||||
|
|
|
|||
|
|
@ -3,25 +3,25 @@
|
|||
* @author Nat Goodspeed
|
||||
* @date 2008-09-12
|
||||
* @brief Implementation for llevents.
|
||||
*
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
|
@ -423,8 +423,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
|
|||
|
||||
float nodePosition = 1.0;
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// listener. We'll just tack it on to the end.
|
||||
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,
|
||||
// connect it.
|
||||
LLBoundListener bound = mSignal->connect(nodePosition, listener);
|
||||
|
||||
|
||||
if (!name.empty())
|
||||
{ // note that we are not tracking anonymous listeners here either.
|
||||
// This means that it is the caller's responsibility to either assign
|
||||
// to a TempBoundListerer (scoped_connection) or manually disconnect
|
||||
// when done.
|
||||
// This means that it is the caller's responsibility to either assign
|
||||
// to a TempBoundListerer (scoped_connection) or manually disconnect
|
||||
// when done.
|
||||
mConnections[name] = bound;
|
||||
}
|
||||
return bound;
|
||||
|
|
@ -641,9 +641,9 @@ bool LLEventMailDrop::post(const LLSD& event)
|
|||
{
|
||||
// forward the call to our base class
|
||||
bool posted = LLEventStream::post(event);
|
||||
|
||||
|
||||
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.
|
||||
mEventHistory.push_back(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ public:
|
|||
F32 mAlphaCutoff;
|
||||
|
||||
AlphaMode mAlphaMode;
|
||||
|
||||
|
||||
bool mDoubleSided = false;
|
||||
|
||||
// Override specific flags for state that can't use off-by-epsilon or UUID
|
||||
|
|
|
|||
|
|
@ -1276,7 +1276,7 @@ bool LLGLManager::initGL()
|
|||
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
|
||||
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
|
||||
mMaxUniformBlockSize = llmin(mMaxUniformBlockSize, 65536);
|
||||
|
||||
|
|
|
|||
|
|
@ -172,11 +172,11 @@ void clear_glerror();
|
|||
# define llglassertok() assert_glerror()
|
||||
|
||||
// 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
|
||||
#if LL_DARWIN && !LL_RELEASE_FOR_DOWNLOAD
|
||||
#define STOP_GLERROR stop_glerror()
|
||||
#else
|
||||
#else
|
||||
#define STOP_GLERROR
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ void LLGLSLShader::unloadInternal()
|
|||
bool LLGLSLShader::createShader()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
||||
unloadInternal();
|
||||
|
||||
sInstances.insert(this);
|
||||
|
|
@ -968,7 +968,7 @@ bool LLGLSLShader::mapUniforms()
|
|||
glUniformBlockBinding(mProgramObject, UBOBlockIndex, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unbind();
|
||||
|
||||
LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -328,14 +328,16 @@ public:
|
|||
// bit 0 = alpha mode blend (1) or opaque (0)
|
||||
// bit 1 = rigged (1) or static (0)
|
||||
// bit 2 = unlit (1) or lit (0)
|
||||
// bit 3 = single (0) or multi (1) uv coordinates
|
||||
struct GLTFVariant
|
||||
{
|
||||
constexpr static U8 ALPHA_BLEND = 1;
|
||||
constexpr static U8 RIGGED = 2;
|
||||
constexpr static U8 UNLIT = 4;
|
||||
constexpr static U8 MULTI_UV = 8;
|
||||
};
|
||||
|
||||
constexpr static U8 NUM_GLTF_VARIANTS = 8;
|
||||
constexpr static U8 NUM_GLTF_VARIANTS = 16;
|
||||
|
||||
std::vector<LLGLSLShader> mGLTFVariants;
|
||||
|
||||
|
|
|
|||
|
|
@ -1731,7 +1731,7 @@ void LLRender::flush()
|
|||
|
||||
if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
|
||||
{
|
||||
vb->setTexCoordData(mTexcoordsp.get());
|
||||
vb->setTexCoord0Data(mTexcoordsp.get());
|
||||
}
|
||||
|
||||
if (attribute_mask & LLVertexBuffer::MAP_COLOR)
|
||||
|
|
|
|||
|
|
@ -1184,7 +1184,13 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_normal_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_occlusion_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("base_color_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("emissive_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("normal_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("metallic_roughness_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("occlusion_texcoord"); // (GLTF)
|
||||
|
||||
mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,13 @@ public:
|
|||
TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF)
|
||||
TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF)
|
||||
TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF)
|
||||
TEXTURE_OCCLUSION_TRANSFORM, // "texture_occlusion_transform" (GLTF)
|
||||
TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF)
|
||||
BASE_COLOR_TEXCOORD, // "base_color_texcoord" (GLTF)
|
||||
EMISSIVE_TEXCOORD, // "emissive_texcoord" (GLTF)
|
||||
NORMAL_TEXCOORD, // "normal_texcoord" (GLTF)
|
||||
METALLIC_ROUGHNESS_TEXCOORD, // "metallic_roughness_texcoord" (GLTF)
|
||||
OCCLUSION_TEXCOORD, // "occlusion_texcoord" (GLTF)
|
||||
|
||||
TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF)
|
||||
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ public:
|
|||
|
||||
{ //allocate a new buffer
|
||||
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
|
||||
data = (U8*) ll_aligned_malloc_16(size);
|
||||
STOP_GLERROR;
|
||||
|
|
@ -329,12 +329,12 @@ public:
|
|||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
|
||||
llassert(size >= 2);
|
||||
|
||||
|
||||
if (data)
|
||||
{
|
||||
ll_aligned_free_16(data);
|
||||
}
|
||||
|
||||
|
||||
mAllocated -= size;
|
||||
STOP_GLERROR;
|
||||
if (name)
|
||||
|
|
@ -1517,7 +1517,7 @@ void LLVertexBuffer::setBuffer()
|
|||
// no data may be pending
|
||||
llassert(mMappedVertexRegions.empty());
|
||||
llassert(mMappedIndexRegions.empty());
|
||||
|
||||
|
||||
// a shader must be bound
|
||||
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);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setTexCoordData(const LLVector2* data)
|
||||
void LLVertexBuffer::setTexCoord0Data(const LLVector2* data)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
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);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setTexCoord1Data(const LLVector2* data)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
llassert(sGLRenderBuffer == mGLBuffer);
|
||||
#endif
|
||||
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + sTypeSize[TYPE_TEXCOORD1] * getNumVerts() - 1, (U8*)data, mMappedData);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setColorData(const LLColor4U* data)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public:
|
|||
TYPE_WEIGHT, // "weight"
|
||||
TYPE_WEIGHT4, // "weight4"
|
||||
TYPE_CLOTHWEIGHT, // "clothing"
|
||||
TYPE_JOINT, // "joint"
|
||||
TYPE_JOINT, // "joint"
|
||||
TYPE_TEXTURE_INDEX, // "texture_index"
|
||||
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
|
||||
|
|
@ -200,7 +200,8 @@ public:
|
|||
void setTangentData(const LLVector4a* data);
|
||||
void setWeight4Data(const LLVector4a* data);
|
||||
void setJointData(const U64* data);
|
||||
void setTexCoordData(const LLVector2* data);
|
||||
void setTexCoord0Data(const LLVector2* data);
|
||||
void setTexCoord1Data(const LLVector2* data);
|
||||
void setColorData(const LLColor4U* data);
|
||||
void setIndexData(const U16* data);
|
||||
void setIndexData(const U32* data);
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ float terrain_mix(TerrainMix tm, vec4 tms4);
|
|||
vec3 mikktspace(vec3 vNt, vec3 vT)
|
||||
{
|
||||
vec3 vN = vary_normal;
|
||||
|
||||
|
||||
vec3 vB = vary_sign * cross(vN, vT);
|
||||
vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ uniform sampler2D emissiveMap;
|
|||
uniform vec3 emissiveColor;
|
||||
in vec3 vary_position;
|
||||
in vec4 vertex_color;
|
||||
in vec2 base_color_texcoord;
|
||||
in vec2 emissive_texcoord;
|
||||
in vec2 base_color_uv;
|
||||
in vec2 emissive_uv;
|
||||
uniform float minimum_alpha;
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
|
@ -59,8 +59,9 @@ uniform float roughnessFactor;
|
|||
in vec3 vary_normal;
|
||||
in vec3 vary_tangent;
|
||||
flat in float vary_sign;
|
||||
in vec2 normal_texcoord;
|
||||
in vec2 metallic_roughness_texcoord;
|
||||
in vec2 normal_uv;
|
||||
in vec2 metallic_roughness_uv;
|
||||
in vec2 occlusion_uv;
|
||||
#endif
|
||||
// ==================================
|
||||
|
||||
|
|
@ -164,7 +165,7 @@ void main()
|
|||
vec3 pos = vary_position;
|
||||
mirrorClip(pos);
|
||||
|
||||
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
|
||||
vec4 basecolor = texture(diffuseMap, base_color_uv.xy).rgba;
|
||||
basecolor.rgb = srgb_to_linear(basecolor.rgb);
|
||||
basecolor *= vertex_color;
|
||||
|
||||
|
|
@ -174,7 +175,7 @@ void main()
|
|||
}
|
||||
|
||||
vec3 emissive = emissiveColor;
|
||||
emissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb);
|
||||
emissive *= srgb_to_linear(texture(emissiveMap, emissive_uv.xy).rgb);
|
||||
// ==================================
|
||||
|
||||
// ==================================
|
||||
|
|
@ -184,7 +185,7 @@ void main()
|
|||
// ==================================
|
||||
#ifndef UNLIT
|
||||
// from mikktspace.com
|
||||
vec3 vNt = texture(normalMap, normal_texcoord.xy).xyz*2.0-1.0;
|
||||
vec3 vNt = texture(normalMap, normal_uv.xy).xyz*2.0-1.0;
|
||||
float sign = vary_sign;
|
||||
vec3 vN = vary_normal;
|
||||
vec3 vT = vary_tangent.xyz;
|
||||
|
|
@ -198,8 +199,8 @@ void main()
|
|||
// occlusion 1.0
|
||||
// roughness 0.0
|
||||
// metal 0.0
|
||||
vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb;
|
||||
orm.r = texture(occlusionMap, metallic_roughness_texcoord.xy).r;
|
||||
vec3 orm = texture(metallicRoughnessMap, metallic_roughness_uv.xy).rgb;
|
||||
orm.r = texture(occlusionMap, occlusion_uv.xy).r;
|
||||
orm.g *= roughnessFactor;
|
||||
orm.b *= metallicFactor;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,33 +33,97 @@ uniform mat4 projection_matrix;
|
|||
uniform mat3 normal_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
#endif
|
||||
uniform mat4 texture_matrix0;
|
||||
|
||||
uniform vec4[2] texture_base_color_transform;
|
||||
uniform vec4[2] texture_normal_transform;
|
||||
uniform vec4[2] texture_metallic_roughness_transform;
|
||||
uniform vec4[2] texture_emissive_transform;
|
||||
uniform vec4[2] texture_occlusion_transform;
|
||||
|
||||
in vec3 position;
|
||||
in vec4 diffuse_color;
|
||||
in vec2 texcoord0;
|
||||
out vec2 base_color_texcoord;
|
||||
out vec2 emissive_texcoord;
|
||||
out vec2 base_color_uv;
|
||||
out vec2 emissive_uv;
|
||||
out vec4 vertex_color;
|
||||
out vec3 vary_position;
|
||||
|
||||
#ifndef UNLIT
|
||||
in vec3 normal;
|
||||
in vec4 tangent;
|
||||
out vec2 normal_texcoord;
|
||||
out vec2 metallic_roughness_texcoord;
|
||||
out vec2 normal_uv;
|
||||
out vec2 metallic_roughness_uv;
|
||||
out vec2 occlusion_uv;
|
||||
out vec3 vary_tangent;
|
||||
flat out float vary_sign;
|
||||
out vec3 vary_normal;
|
||||
vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
|
||||
#endif
|
||||
|
||||
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
|
||||
#ifdef MULTI_UV
|
||||
in vec2 texcoord1;
|
||||
uniform int base_color_texcoord;
|
||||
uniform int emissive_texcoord;
|
||||
#ifndef UNLIT
|
||||
uniform int normal_texcoord;
|
||||
uniform int metallic_roughness_texcoord;
|
||||
uniform int occlusion_texcoord;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p)
|
||||
{
|
||||
texcoord.y = 1.0 - texcoord.y;
|
||||
|
||||
vec2 Scale = p[0].xy;
|
||||
float Rotation = -p[0].z;
|
||||
vec2 Offset = vec2(p[0].w, p[1].x);
|
||||
|
||||
mat3 translation = mat3(1,0,0, 0,1,0, Offset.x, Offset.y, 1);
|
||||
mat3 rotation = mat3(
|
||||
cos(Rotation), sin(Rotation), 0,
|
||||
-sin(Rotation), cos(Rotation), 0,
|
||||
0, 0, 1);
|
||||
|
||||
mat3 scale = mat3(Scale.x,0,0, 0,Scale.y,0, 0,0,1);
|
||||
|
||||
mat3 matrix = translation * rotation * scale;
|
||||
|
||||
vec2 uvTransformed = ( matrix * vec3(texcoord.xy, 1) ).xy;
|
||||
|
||||
uvTransformed.y = 1.0 - uvTransformed.y;
|
||||
|
||||
return uvTransformed;
|
||||
}
|
||||
|
||||
#ifndef UNLIT
|
||||
vec3 gltf_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform)
|
||||
{ //derived from tangent_space_transform in textureUtilV.glsl
|
||||
vec2 weights = vec2(0, 1);
|
||||
|
||||
// Convert to left-handed coordinate system
|
||||
weights.y = -weights.y;
|
||||
|
||||
// Apply KHR_texture_transform (rotation only)
|
||||
float khr_rotation = khr_gltf_transform[0].z;
|
||||
mat2 khr_rotation_mat = mat2(
|
||||
cos(khr_rotation),-sin(khr_rotation),
|
||||
sin(khr_rotation), cos(khr_rotation)
|
||||
);
|
||||
weights = khr_rotation_mat * weights;
|
||||
|
||||
// Convert back to right-handed coordinate system
|
||||
weights.y = -weights.y;
|
||||
|
||||
// Similar to the MikkTSpace-compatible method of extracting the binormal
|
||||
// from the normal and tangent, as seen in the fragment shader
|
||||
vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz);
|
||||
|
||||
return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz);
|
||||
|
||||
return vertex_tangent.xyz;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef ALPHA_BLEND
|
||||
|
|
@ -136,14 +200,41 @@ void main()
|
|||
gl_Position = vert;
|
||||
#endif
|
||||
|
||||
base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0);
|
||||
emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0);
|
||||
vec2 bcuv;
|
||||
vec2 emuv;
|
||||
|
||||
#ifdef MULTI_UV
|
||||
vec2 uv[2];
|
||||
uv[0] = texcoord0;
|
||||
uv[1] = texcoord1;
|
||||
|
||||
bcuv = uv[base_color_texcoord];
|
||||
emuv = uv[emissive_texcoord];
|
||||
#else
|
||||
bcuv = texcoord0;
|
||||
emuv = texcoord0;
|
||||
#endif
|
||||
|
||||
base_color_uv = gltf_texture_transform(bcuv, texture_base_color_transform);
|
||||
emissive_uv = gltf_texture_transform(emuv, texture_emissive_transform);
|
||||
|
||||
#ifndef UNLIT
|
||||
normal_texcoord = texture_transform(texcoord0, texture_normal_transform, texture_matrix0);
|
||||
metallic_roughness_texcoord = texture_transform(texcoord0, texture_metallic_roughness_transform, texture_matrix0);
|
||||
vec2 normuv;
|
||||
vec2 rmuv;
|
||||
vec2 ouv;
|
||||
#ifdef MULTI_UV
|
||||
normuv = uv[normal_texcoord];
|
||||
rmuv = uv[metallic_roughness_texcoord];
|
||||
ouv = uv[occlusion_texcoord];
|
||||
#else
|
||||
normuv = texcoord0;
|
||||
rmuv = texcoord0;
|
||||
ouv = texcoord0;
|
||||
#endif
|
||||
normal_uv = gltf_texture_transform(normuv, texture_normal_transform);
|
||||
metallic_roughness_uv = gltf_texture_transform(rmuv, texture_metallic_roughness_transform);
|
||||
occlusion_uv = gltf_texture_transform(ouv, texture_occlusion_transform);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef UNLIT
|
||||
#ifdef HAS_SKIN
|
||||
|
|
@ -155,7 +246,7 @@ void main()
|
|||
#endif
|
||||
|
||||
n = normalize(n);
|
||||
vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform, texture_matrix0));
|
||||
vary_tangent = normalize(gltf_tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform));
|
||||
vary_sign = tangent.w;
|
||||
vary_normal = n;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -108,7 +108,8 @@ void Buffer::erase(Asset& asset, S32 offset, S32 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)
|
||||
{
|
||||
|
|
@ -141,7 +142,7 @@ bool Buffer::prep(Asset& asset)
|
|||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -189,16 +189,15 @@ void Animation::Sampler::getFrameInfo(Asset& asset, F32 time, U32& frameIndex, F
|
|||
|
||||
if (mFrameTimes.size() > 1)
|
||||
{
|
||||
llassert(mFrameTimes.size() <= size_t(U32_MAX));
|
||||
frameIndex = U32(mFrameTimes.size()) - 2;
|
||||
t = 1.f;
|
||||
|
||||
if (time > mMaxTime)
|
||||
{
|
||||
frameIndex = (U32)mFrameTimes.size() - 2;
|
||||
t = 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
frameIndex = (U32)mFrameTimes.size() - 2;
|
||||
t = 1.f;
|
||||
|
||||
for (U32 i = 0; i < (U32)mFrameTimes.size() - 1; i++)
|
||||
{
|
||||
if (time >= mFrameTimes[i] && time < mFrameTimes[i + 1])
|
||||
|
|
@ -382,7 +381,7 @@ void Skin::uploadMatrixPalette(Asset& asset)
|
|||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ namespace LL
|
|||
namespace GLTF
|
||||
{
|
||||
static std::unordered_set<std::string> ExtensionsSupported = {
|
||||
"KHR_materials_unlit"
|
||||
"KHR_materials_unlit",
|
||||
"KHR_texture_transform"
|
||||
};
|
||||
|
||||
Material::AlphaMode gltf_alpha_mode_to_enum(const std::string& alpha_mode)
|
||||
|
|
@ -906,6 +907,25 @@ void Material::TextureInfo::serialize(object& dst) const
|
|||
{
|
||||
write(mIndex, "index", dst, INVALID_INDEX);
|
||||
write(mTexCoord, "texCoord", dst, 0);
|
||||
write_extensions(dst, &mTextureTransform, "KHR_texture_transform");
|
||||
}
|
||||
|
||||
S32 Material::TextureInfo::getTexCoord() const
|
||||
{
|
||||
if (mTextureTransform.mPresent && mTextureTransform.mTexCoord != INVALID_INDEX)
|
||||
{
|
||||
return mTextureTransform.mTexCoord;
|
||||
}
|
||||
return mTexCoord;
|
||||
}
|
||||
|
||||
bool Material::isMultiUV() const
|
||||
{
|
||||
return mPbrMetallicRoughness.mBaseColorTexture.getTexCoord() != 0 ||
|
||||
mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord() != 0 ||
|
||||
mNormalTexture.getTexCoord() != 0 ||
|
||||
mOcclusionTexture.getTexCoord() != 0 ||
|
||||
mEmissiveTexture.getTexCoord() != 0;
|
||||
}
|
||||
|
||||
const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)
|
||||
|
|
@ -914,6 +934,7 @@ const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)
|
|||
{
|
||||
copy(src, "index", mIndex);
|
||||
copy(src, "texCoord", mTexCoord);
|
||||
copy_extensions(src, "KHR_texture_transform", &mTextureTransform);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
|
@ -931,17 +952,16 @@ bool Material::TextureInfo::operator!=(const Material::TextureInfo& rhs) const
|
|||
|
||||
void Material::OcclusionTextureInfo::serialize(object& dst) const
|
||||
{
|
||||
write(mIndex, "index", dst, INVALID_INDEX);
|
||||
write(mTexCoord, "texCoord", dst, 0);
|
||||
TextureInfo::serialize(dst);
|
||||
write(mStrength, "strength", dst, 1.f);
|
||||
}
|
||||
|
||||
const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(const Value& src)
|
||||
{
|
||||
TextureInfo::operator=(src);
|
||||
|
||||
if (src.is_object())
|
||||
{
|
||||
copy(src, "index", mIndex);
|
||||
copy(src, "texCoord", mTexCoord);
|
||||
copy(src, "strength", mStrength);
|
||||
}
|
||||
|
||||
|
|
@ -950,13 +970,13 @@ const Material::OcclusionTextureInfo& Material::OcclusionTextureInfo::operator=(
|
|||
|
||||
void Material::NormalTextureInfo::serialize(object& dst) const
|
||||
{
|
||||
write(mIndex, "index", dst, INVALID_INDEX);
|
||||
write(mTexCoord, "texCoord", dst, 0);
|
||||
TextureInfo::serialize(dst);
|
||||
write(mScale, "scale", dst, 1.f);
|
||||
}
|
||||
|
||||
const Material::NormalTextureInfo& Material::NormalTextureInfo::operator=(const Value& src)
|
||||
{
|
||||
TextureInfo::operator=(src);
|
||||
if (src.is_object())
|
||||
{
|
||||
copy(src, "index", mIndex);
|
||||
|
|
@ -1015,6 +1035,41 @@ void Material::Unlit::serialize(object& dst) const
|
|||
// no members and object has already been created, nothing to do
|
||||
}
|
||||
|
||||
void TextureTransform::getPacked(F32* packed) const
|
||||
{
|
||||
packed[0] = mScale.x;
|
||||
packed[1] = mScale.y;
|
||||
packed[2] = mRotation;
|
||||
packed[3] = mOffset.x;
|
||||
packed[4] = mOffset.y;
|
||||
|
||||
packed[5] = packed[6] = packed[7] = 0.f;
|
||||
}
|
||||
|
||||
|
||||
const TextureTransform& TextureTransform::operator=(const Value& src)
|
||||
{
|
||||
mPresent = true;
|
||||
if (src.is_object())
|
||||
{
|
||||
copy(src, "offset", mOffset);
|
||||
copy(src, "rotation", mRotation);
|
||||
copy(src, "scale", mScale);
|
||||
copy(src, "texCoord", mTexCoord);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void TextureTransform::serialize(object& dst) const
|
||||
{
|
||||
write(mOffset, "offset", dst, vec2(0.f, 0.f));
|
||||
write(mRotation, "rotation", dst, 0.f);
|
||||
write(mScale, "scale", dst, vec2(1.f, 1.f));
|
||||
write(mTexCoord, "texCoord", dst, -1);
|
||||
}
|
||||
|
||||
|
||||
void Material::serialize(object& dst) const
|
||||
{
|
||||
write(mName, "name", dst);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,21 @@ namespace LL
|
|||
bool mPresent = false;
|
||||
};
|
||||
|
||||
class TextureTransform : public Extension // KHR_texture_transform implementation
|
||||
{
|
||||
public:
|
||||
vec2 mOffset = vec2(0.f, 0.f);
|
||||
F32 mRotation = 0.f;
|
||||
vec2 mScale = vec2(1.f, 1.f);
|
||||
S32 mTexCoord = INVALID_INDEX;
|
||||
|
||||
// get the texture transform as a packed array of floats
|
||||
// dst MUST point to at least 8 floats
|
||||
void getPacked(F32* dst) const;
|
||||
|
||||
const TextureTransform& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
|
|
@ -82,9 +97,15 @@ namespace LL
|
|||
S32 mIndex = INVALID_INDEX;
|
||||
S32 mTexCoord = 0;
|
||||
|
||||
TextureTransform mTextureTransform;
|
||||
|
||||
bool operator==(const TextureInfo& rhs) const;
|
||||
bool operator!=(const TextureInfo& rhs) const;
|
||||
|
||||
// get the UV channel that should be used for sampling this texture
|
||||
// returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord
|
||||
S32 getTexCoord() const;
|
||||
|
||||
const TextureInfo& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
};
|
||||
|
|
@ -135,6 +156,8 @@ namespace LL
|
|||
bool mDoubleSided = false;
|
||||
Unlit mUnlit;
|
||||
|
||||
bool isMultiUV() const;
|
||||
|
||||
const Material& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -590,8 +590,8 @@ namespace LL
|
|||
// Write all extensions to dst.extensions
|
||||
// Usage:
|
||||
// write_extensions(dst,
|
||||
// "KHR_materials_unlit", mUnlit,
|
||||
// "KHR_materials_pbrSpecularGlossiness", mPbrSpecularGlossiness);
|
||||
// mUnlit, "KHR_materials_unlit",
|
||||
// mPbrSpecularGlossiness, "KHR_materials_pbrSpecularGlossiness");
|
||||
// returns true if any of the extensions are written
|
||||
template<class... Types>
|
||||
inline bool write_extensions(boost::json::object& dst, Types... args)
|
||||
|
|
@ -816,6 +816,39 @@ namespace LL
|
|||
return true;
|
||||
}
|
||||
|
||||
// vec2
|
||||
template<>
|
||||
inline bool copy(const Value& src, vec2& dst)
|
||||
{
|
||||
if (src.is_array())
|
||||
{
|
||||
const boost::json::array& arr = src.as_array();
|
||||
if (arr.size() == 2)
|
||||
{
|
||||
std::error_code ec;
|
||||
vec2 t;
|
||||
t.x = arr[0].to_number<F32>(ec); if (ec) return false;
|
||||
t.y = arr[1].to_number<F32>(ec); if (ec) return false;
|
||||
|
||||
dst = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool write(const vec2& src, Value& dst)
|
||||
{
|
||||
dst = boost::json::array();
|
||||
boost::json::array& arr = dst.as_array();
|
||||
arr.resize(2);
|
||||
arr[0] = src.x;
|
||||
arr[1] = src.y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// bool
|
||||
template<>
|
||||
inline bool copy(const Value& src, bool& dst)
|
||||
|
|
|
|||
|
|
@ -42,30 +42,45 @@ using namespace boost::json;
|
|||
// Mesh data useful for Mikktspace tangent generation (and flat normal generation)
|
||||
struct MikktMesh
|
||||
{
|
||||
std::vector<LLVector3> p;
|
||||
std::vector<LLVector3> n;
|
||||
std::vector<LLVector2> tc;
|
||||
std::vector<LLVector4> w;
|
||||
std::vector<LLVector4> t;
|
||||
std::vector<LLColor4U> c;
|
||||
std::vector<U64> j;
|
||||
std::vector<LLVector3> p; //positions
|
||||
std::vector<LLVector3> n; //normals
|
||||
std::vector<LLVector4> t; //tangents
|
||||
std::vector<LLVector2> tc0; //texcoords 0
|
||||
std::vector<LLVector2> tc1; //texcoords 1
|
||||
std::vector<LLColor4U> c; //colors
|
||||
std::vector<LLVector4> w; //weights
|
||||
std::vector<U64> j; //joints
|
||||
|
||||
// initialize from src primitive and make an unrolled triangle list
|
||||
// returns false if the Primitive cannot be converted to a triangle list
|
||||
bool copy(const Primitive* prim)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
n.resize(vert_count);
|
||||
tc.resize(vert_count);
|
||||
tc0.resize(vert_count);
|
||||
c.resize(vert_count);
|
||||
|
||||
bool has_normals = !prim->mNormals.empty();
|
||||
|
|
@ -78,6 +93,7 @@ struct MikktMesh
|
|||
{
|
||||
t.resize(vert_count);
|
||||
}
|
||||
|
||||
bool rigged = !prim->mWeights.empty();
|
||||
if (rigged)
|
||||
{
|
||||
|
|
@ -85,23 +101,69 @@ struct MikktMesh
|
|||
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());
|
||||
tc[i].set(prim->mTexCoords[idx]);
|
||||
c[i] = prim->mColors[idx];
|
||||
for (U32 tri_idx = 0; tri_idx < U32(triangle_count); ++tri_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());
|
||||
j[i] = prim->mJoints[idx];
|
||||
idx[0] = prim->mIndexArray[idx[0]];
|
||||
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()
|
||||
{
|
||||
U32 tri_count = p.size() / 3;
|
||||
for (U32 i = 0; i < tri_count; ++i)
|
||||
size_t tri_count = p.size() / 3;
|
||||
for (size_t i = 0; i < tri_count; ++i)
|
||||
{
|
||||
LLVector3 v0 = p[i * 3];
|
||||
LLVector3 v1 = p[i * 3 + 1];
|
||||
|
|
@ -138,25 +200,34 @@ struct MikktMesh
|
|||
void write(Primitive* prim) const
|
||||
{
|
||||
//re-weld
|
||||
meshopt_Stream mos[] =
|
||||
std::vector<meshopt_Stream> mos =
|
||||
{
|
||||
{ &p[0], sizeof(LLVector3), sizeof(LLVector3) },
|
||||
{ &n[0], sizeof(LLVector3), sizeof(LLVector3) },
|
||||
{ &t[0], sizeof(LLVector4), sizeof(LLVector4) },
|
||||
{ &tc[0], sizeof(LLVector2), sizeof(LLVector2) },
|
||||
{ &c[0], sizeof(LLColor4U), sizeof(LLColor4U) },
|
||||
{ w.empty() ? nullptr : &w[0], sizeof(LLVector4), sizeof(LLVector4) },
|
||||
{ j.empty() ? nullptr : &j[0], sizeof(U64), sizeof(U64) }
|
||||
{ &tc0[0], sizeof(LLVector2), sizeof(LLVector2) },
|
||||
{ &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }
|
||||
};
|
||||
|
||||
if (!w.empty())
|
||||
{
|
||||
mos.push_back({ &w[0], sizeof(LLVector4), sizeof(LLVector4) });
|
||||
mos.push_back({ &j[0], sizeof(U64), sizeof(U64) });
|
||||
}
|
||||
|
||||
if (!tc1.empty())
|
||||
{
|
||||
mos.push_back({ &tc1[0], sizeof(LLVector2), sizeof(LLVector2) });
|
||||
}
|
||||
|
||||
std::vector<U32> remap;
|
||||
remap.resize(p.size());
|
||||
|
||||
U32 stream_count = w.empty() ? 5 : 7;
|
||||
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->mTangents.resize(vert_count);
|
||||
prim->mPositions.resize(vert_count);
|
||||
|
|
@ -166,7 +237,11 @@ struct MikktMesh
|
|||
prim->mWeights.resize(vert_count);
|
||||
prim->mJoints.resize(vert_count);
|
||||
}
|
||||
|
||||
if (!tc1.empty())
|
||||
{
|
||||
prim->mTexCoords1.resize(vert_count);
|
||||
}
|
||||
|
||||
prim->mIndexArray.resize(remap.size());
|
||||
|
||||
for (int i = 0; i < remap.size(); ++i)
|
||||
|
|
@ -178,7 +253,7 @@ struct MikktMesh
|
|||
|
||||
prim->mPositions[dst_idx].load3(p[src_idx].mV);
|
||||
prim->mNormals[dst_idx].load3(n[src_idx].mV);
|
||||
prim->mTexCoords[dst_idx] = tc[src_idx];
|
||||
prim->mTexCoords0[dst_idx] = tc0[src_idx];
|
||||
prim->mTangents[dst_idx].loadua(t[src_idx].mV);
|
||||
prim->mColors[dst_idx] = c[src_idx];
|
||||
|
||||
|
|
@ -187,6 +262,11 @@ struct MikktMesh
|
|||
prim->mWeights[dst_idx].loadua(w[src_idx].mV);
|
||||
prim->mJoints[dst_idx] = j[src_idx];
|
||||
}
|
||||
|
||||
if (!tc1.empty())
|
||||
{
|
||||
prim->mTexCoords1[dst_idx] = tc1[src_idx];
|
||||
}
|
||||
}
|
||||
|
||||
prim->mGLMode = LLRender::TRIANGLES;
|
||||
|
|
@ -210,8 +290,8 @@ struct MikktMesh
|
|||
|
||||
mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)
|
||||
{
|
||||
F32* uv = tc[face_num * 3 + vert_num].mV;
|
||||
return mikk::float3(uv[0], uv[1], 1.0f);
|
||||
F32* uv = tc0[face_num * 3 + vert_num].mV;
|
||||
return mikk::float3(uv[0], 1.f-uv[1], 1.0f);
|
||||
}
|
||||
|
||||
mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num)
|
||||
|
|
@ -228,6 +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)
|
||||
{
|
||||
// allocate vertex buffer
|
||||
|
|
@ -261,7 +349,11 @@ bool Primitive::prep(Asset& asset)
|
|||
}
|
||||
else if (attribName == "TEXCOORD_0")
|
||||
{
|
||||
copy(asset, accessor, mTexCoords);
|
||||
copy(asset, accessor, mTexCoords0);
|
||||
}
|
||||
else if (attribName == "TEXCOORD_1")
|
||||
{
|
||||
copy(asset, accessor, mTexCoords1);
|
||||
}
|
||||
else if (attribName == "JOINTS_0")
|
||||
{
|
||||
|
|
@ -297,24 +389,28 @@ bool Primitive::prep(Asset& asset)
|
|||
mask |= LLVertexBuffer::MAP_JOINT;
|
||||
}
|
||||
|
||||
if (mTexCoords.empty())
|
||||
if (mTexCoords0.empty())
|
||||
{
|
||||
mTexCoords.resize(mPositions.size());
|
||||
mTexCoords0.resize(mPositions.size());
|
||||
}
|
||||
|
||||
// TODO: support more than one texcoord set (or no texcoords)
|
||||
mask |= LLVertexBuffer::MAP_TEXCOORD0;
|
||||
|
||||
if (!mTexCoords1.empty())
|
||||
{
|
||||
mask |= LLVertexBuffer::MAP_TEXCOORD1;
|
||||
}
|
||||
|
||||
if (mColors.empty())
|
||||
{
|
||||
mColors.resize(mPositions.size(), LLColor4U::white);
|
||||
}
|
||||
|
||||
mShaderVariant = 0;
|
||||
|
||||
// TODO: support colorless vertex buffers
|
||||
mask |= LLVertexBuffer::MAP_COLOR;
|
||||
|
||||
mShaderVariant = 0;
|
||||
|
||||
bool unlit = false;
|
||||
|
||||
// bake material basecolor into color array
|
||||
|
|
@ -332,6 +428,11 @@ bool Primitive::prep(Asset& asset)
|
|||
mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;
|
||||
unlit = true;
|
||||
}
|
||||
|
||||
if (material.isMultiUV())
|
||||
{
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::MULTI_UV;
|
||||
}
|
||||
}
|
||||
|
||||
if (mNormals.empty() && !unlit)
|
||||
|
|
@ -411,7 +512,10 @@ bool Primitive::prep(Asset& asset)
|
|||
}
|
||||
|
||||
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->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)
|
||||
for (auto& tc : mTexCoords)
|
||||
vertical_flip(mTexCoords0);
|
||||
mVertexBuffer->setTexCoord0Data(mTexCoords0.data());
|
||||
vertical_flip(mTexCoords0);
|
||||
|
||||
if (!mTexCoords1.empty())
|
||||
{
|
||||
tc[1] = 1.f - tc[1];
|
||||
}
|
||||
mVertexBuffer->setTexCoordData(mTexCoords.data());
|
||||
for (auto& tc : mTexCoords)
|
||||
{
|
||||
tc[1] = 1.f - tc[1];
|
||||
vertical_flip(mTexCoords1);
|
||||
mVertexBuffer->setTexCoord1Data(mTexCoords1.data());
|
||||
vertical_flip(mTexCoords1);
|
||||
}
|
||||
|
||||
|
||||
if (!mIndexArray.empty())
|
||||
{
|
||||
mVertexBuffer->setIndexData(mIndexArray.data());
|
||||
|
|
@ -453,10 +559,13 @@ bool Primitive::prep(Asset& asset)
|
|||
|
||||
mVertexBuffer->unbind();
|
||||
|
||||
Material& material = asset.mMaterials[mMaterial];
|
||||
if (material.mAlphaMode == Material::AlphaMode::BLEND)
|
||||
if (mMaterial != INVALID_INDEX)
|
||||
{
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND;
|
||||
Material& material = asset.mMaterials[mMaterial];
|
||||
if (material.mAlphaMode == Material::AlphaMode::BLEND)
|
||||
{
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -614,13 +723,13 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,
|
|||
//create a proxy LLVolumeFace for the raycast
|
||||
LLVolumeFace face;
|
||||
face.mPositions = mPositions.data();
|
||||
face.mTexCoords = mTexCoords.data();
|
||||
face.mTexCoords = mTexCoords0.data();
|
||||
face.mNormals = mNormals.data();
|
||||
face.mTangents = mTangents.data();
|
||||
face.mIndices = nullptr; // unreferenced
|
||||
|
||||
face.mNumIndices = (S32)mIndexArray.size();
|
||||
face.mNumVertices = (S32)mPositions.size();
|
||||
face.mNumIndices = S32(mIndexArray.size());
|
||||
face.mNumVertices = S32(mPositions.size());
|
||||
|
||||
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out);
|
||||
intersect.traverse(mOctree);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ namespace LL
|
|||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
|
||||
// CPU copy of mesh data, keep these as LLVector types for compatibility with raycasting code
|
||||
std::vector<LLVector2> mTexCoords;
|
||||
std::vector<LLVector2> mTexCoords0;
|
||||
std::vector<LLVector2> mTexCoords1;
|
||||
std::vector<LLVector4a> mNormals;
|
||||
std::vector<LLVector4a> mTangents;
|
||||
std::vector<LLVector4a> mPositions;
|
||||
|
|
|
|||
|
|
@ -244,7 +244,8 @@ void GLTFSceneManager::uploadSelection()
|
|||
LLFileSystem cache(assetId, LLAssetType::AT_GLTF_BIN, LLFileSystem::WRITE);
|
||||
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
|
||||
|
|
@ -399,8 +400,9 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a
|
|||
{
|
||||
LLFileSystem file(id, asset_type, LLFileSystem::READ);
|
||||
std::string data;
|
||||
data.resize(file.getSize());
|
||||
file.read((U8*)data.data(), data.size());
|
||||
S32 file_size = file.getSize();
|
||||
data.resize(file_size);
|
||||
file.read((U8*)data.data(), file_size);
|
||||
|
||||
boost::json::value json = boost::json::parse(data);
|
||||
|
||||
|
|
@ -479,7 +481,8 @@ void GLTFSceneManager::update()
|
|||
LLFileSystem cache(assetId, LLAssetType::AT_GLTF, LLFileSystem::WRITE);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -549,10 +552,16 @@ void GLTFSceneManager::render(bool opaque, bool rigged, bool unlit)
|
|||
|
||||
void GLTFSceneManager::render(U8 variant)
|
||||
{
|
||||
// for debugging, just render the whole scene as opaque
|
||||
// by traversing the whole scenegraph
|
||||
// Assumes camera transform is already set and
|
||||
// appropriate shader is already boundd
|
||||
// just render the whole scene by traversing the whole scenegraph
|
||||
// Assumes camera transform is already set and appropriate shader is already bound.
|
||||
// Eventually we'll want a smarter render pipe that has pre-sorted the scene graph
|
||||
// into buckets by material and shader.
|
||||
|
||||
// HACK -- implicitly render multi-uv variant
|
||||
if (!(variant & LLGLSLShader::GLTFVariant::MULTI_UV))
|
||||
{
|
||||
render((U8) (variant | LLGLSLShader::GLTFVariant::MULTI_UV));
|
||||
}
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
|
||||
|
|
@ -663,11 +672,30 @@ static void bindTexture(Asset& asset, S32 uniform, Material::TextureInfo& info,
|
|||
{
|
||||
if (info.mIndex != INVALID_INDEX)
|
||||
{
|
||||
LLViewerTexture* tex = asset.mImages[asset.mTextures[info.mIndex].mSource].mTexture;
|
||||
Texture& texture = asset.mTextures[info.mIndex];
|
||||
|
||||
LLViewerTexture* tex = asset.mImages[texture.mSource].mTexture;
|
||||
if (tex)
|
||||
{
|
||||
tex->addTextureStats(2048.f * 2048.f);
|
||||
LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex);
|
||||
S32 channel = LLGLSLShader::sCurBoundShaderPtr->bindTexture(uniform, tex);
|
||||
|
||||
if (channel != -1 && texture.mSampler != -1)
|
||||
{ // set sampler state
|
||||
Sampler& sampler = asset.mSamplers[texture.mSampler];
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sampler.mWrapS);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, sampler.mWrapT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler.mMagFilter);
|
||||
|
||||
// NOTE: do not set min filter. Always respect client preference for min filter
|
||||
}
|
||||
else
|
||||
{
|
||||
// set default sampler state
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -710,10 +738,10 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)
|
|||
|
||||
bindTexture(asset, LLShaderMgr::DIFFUSE_MAP, material.mPbrMetallicRoughness.mBaseColorTexture, LLViewerFetchedTexture::sWhiteImagep);
|
||||
|
||||
F32 base_color_packed[8];
|
||||
//mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
|
||||
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].getPacked(base_color_packed);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed);
|
||||
F32 tf[8];
|
||||
material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::BASE_COLOR_TEXCOORD, material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord());
|
||||
|
||||
if (!LLPipeline::sShadowRender)
|
||||
{
|
||||
|
|
@ -728,20 +756,21 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)
|
|||
shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, material.mPbrMetallicRoughness.mMetallicFactor);
|
||||
shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, glm::value_ptr(material.mEmissiveFactor));
|
||||
|
||||
F32 normal_packed[8];
|
||||
//mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
|
||||
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, (F32*)normal_packed);
|
||||
material.mNormalTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::NORMAL_TEXCOORD, material.mNormalTexture.getTexCoord());
|
||||
|
||||
F32 metallic_roughness_packed[8];
|
||||
//mTextureTransform[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
|
||||
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].getPacked(metallic_roughness_packed);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, (F32*)metallic_roughness_packed);
|
||||
material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::METALLIC_ROUGHNESS_TEXCOORD, material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord());
|
||||
|
||||
F32 emissive_packed[8];
|
||||
//mTextureTransform[GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
|
||||
LLGLTFMaterial::sDefault.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].getPacked(emissive_packed);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, (F32*)emissive_packed);
|
||||
material.mOcclusionTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::OCCLUSION_TEXCOORD, material.mOcclusionTexture.getTexCoord());
|
||||
|
||||
material.mEmissiveTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::EMISSIVE_TEXCOORD, material.mEmissiveTexture.getTexCoord());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -220,8 +220,8 @@ bool LLViewerDynamicTexture::updateAllInstances()
|
|||
if (dynamicTexture->needsRender())
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("needsRender");
|
||||
llassert(dynamicTexture->getFullWidth() <= (S32)LLPipeline::MAX_BAKE_WIDTH);
|
||||
llassert(dynamicTexture->getFullHeight() <= (S32)LLPipeline::MAX_BAKE_WIDTH);
|
||||
llassert(dynamicTexture->getFullWidth() <= S32(LLPipeline::MAX_BAKE_WIDTH));
|
||||
llassert(dynamicTexture->getFullHeight() <= S32(LLPipeline::MAX_BAKE_WIDTH));
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
|
|
|||
|
|
@ -1973,7 +1973,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
|
|||
LL_DEBUGS() << "no region set" << LL_ENDL;
|
||||
getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
|
||||
}
|
||||
|
||||
|
||||
// Update visibility of terrain swatches, etc
|
||||
refresh();
|
||||
|
||||
|
|
@ -2115,7 +2115,7 @@ bool LLPanelRegionTerrainInfo::sendUpdate()
|
|||
for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i)
|
||||
{
|
||||
LLPointer<LLGLTFMaterial> mat_override = new LLGLTFMaterial();
|
||||
|
||||
|
||||
const bool transform_controls_valid = mMaterialScaleUCtrl[i] && mMaterialScaleVCtrl[i] && mMaterialRotationCtrl[i] && mMaterialOffsetUCtrl[i] && mMaterialOffsetVCtrl[i];
|
||||
if (transform_controls_valid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file llfloaterregioninfo.h
|
||||
* @author Aaron Brashears
|
||||
* @brief Declaration of the region info and controls floater and panels.
|
||||
|
|
@ -6,21 +6,21 @@
|
|||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
|
@ -108,14 +108,14 @@ public:
|
|||
|
||||
// from LLPanel
|
||||
void refresh() override;
|
||||
|
||||
|
||||
void onRegionChanged();
|
||||
void requestRegionInfo();
|
||||
void enableTopButtons();
|
||||
void disableTopButtons();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
LLFloaterRegionInfo(const LLSD& seed);
|
||||
~LLFloaterRegionInfo();
|
||||
|
||||
|
|
@ -144,31 +144,31 @@ class LLPanelRegionInfo : public LLPanel
|
|||
{
|
||||
public:
|
||||
LLPanelRegionInfo();
|
||||
|
||||
|
||||
void onBtnSet();
|
||||
void onChangeChildCtrl(LLUICtrl* ctrl);
|
||||
void onChangeAnything();
|
||||
static void onChangeText(LLLineEditor* caller, void* user_data);
|
||||
|
||||
|
||||
virtual bool refreshFromRegion(LLViewerRegion* region);
|
||||
virtual bool estateUpdate(LLMessageSystem* msg) { return true; }
|
||||
|
||||
|
||||
bool postBuild() override;
|
||||
virtual void updateChild(LLUICtrl* child_ctrl);
|
||||
|
||||
|
||||
void enableButton(const std::string& btn_name, bool enable = true);
|
||||
void disableButton(const std::string& btn_name);
|
||||
|
||||
|
||||
void onClickManageTelehub();
|
||||
|
||||
|
||||
protected:
|
||||
void initCtrl(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
|
||||
// disabled.
|
||||
virtual bool sendUpdate() { return true; }
|
||||
|
||||
|
||||
typedef std::vector<std::string> strings_t;
|
||||
//typedef std::vector<U32> integers_t;
|
||||
void sendEstateOwnerMessage(
|
||||
|
|
@ -176,8 +176,8 @@ protected:
|
|||
const std::string& request,
|
||||
const LLUUID& invoice,
|
||||
const strings_t& strings);
|
||||
|
||||
|
||||
|
||||
|
||||
// member data
|
||||
LLHost mHost;
|
||||
};
|
||||
|
|
@ -208,16 +208,16 @@ protected:
|
|||
|
||||
class LLPanelRegionGeneralInfo : public LLPanelRegionInfo
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
LLPanelRegionGeneralInfo()
|
||||
: LLPanelRegionInfo() {}
|
||||
~LLPanelRegionGeneralInfo() {}
|
||||
|
||||
|
||||
bool refreshFromRegion(LLViewerRegion* region) override;
|
||||
|
||||
|
||||
bool postBuild() override;
|
||||
|
||||
|
||||
void onBtnSet();
|
||||
void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;}
|
||||
|
||||
|
|
@ -245,9 +245,9 @@ public:
|
|||
~LLPanelRegionDebugInfo() {}
|
||||
|
||||
bool postBuild() override;
|
||||
|
||||
|
||||
bool refreshFromRegion(LLViewerRegion* region) override;
|
||||
|
||||
|
||||
protected:
|
||||
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
|
||||
static void onClickCancelRestart(void* data);
|
||||
static void onClickDebugConsole(void* data);
|
||||
|
||||
|
||||
private:
|
||||
LLUUID mTargetAvatar;
|
||||
};
|
||||
|
|
@ -275,9 +275,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
|
|||
public:
|
||||
LLPanelRegionTerrainInfo();
|
||||
~LLPanelRegionTerrainInfo() {}
|
||||
|
||||
|
||||
bool postBuild() override;
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ public:
|
|||
bool validateTextureHeights();
|
||||
|
||||
//static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button
|
||||
|
||||
|
||||
void onSelectMaterialType();
|
||||
void updateForMaterialType();
|
||||
|
||||
|
|
@ -326,13 +326,13 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
|
|||
{
|
||||
public:
|
||||
static void initDispatch(LLDispatcher& dispatch);
|
||||
|
||||
|
||||
void onChangeFixedSun();
|
||||
void onChangeUseGlobalTime();
|
||||
void onChangeAccessOverride();
|
||||
|
||||
|
||||
void onClickEditSky();
|
||||
void onClickEditSkyHelp();
|
||||
void onClickEditSkyHelp();
|
||||
void onClickEditDayCycle();
|
||||
void onClickEditDayCycleHelp();
|
||||
|
||||
|
|
@ -344,26 +344,26 @@ public:
|
|||
void onKickUserCommit(const uuid_vec_t& ids);
|
||||
static void onClickMessageEstate(void* data);
|
||||
bool onMessageCommit(const LLSD& notification, const LLSD& response);
|
||||
|
||||
|
||||
LLPanelEstateInfo();
|
||||
~LLPanelEstateInfo() {}
|
||||
|
||||
|
||||
void updateControls(LLViewerRegion* region);
|
||||
|
||||
|
||||
static void updateEstateName(const std::string& name);
|
||||
static void updateEstateOwnerName(const std::string& name);
|
||||
|
||||
bool refreshFromRegion(LLViewerRegion* region) override;
|
||||
bool estateUpdate(LLMessageSystem* msg) override;
|
||||
|
||||
|
||||
bool postBuild() override;
|
||||
void updateChild(LLUICtrl* child_ctrl) override;
|
||||
void refresh() override;
|
||||
|
||||
void refreshFromEstate();
|
||||
|
||||
|
||||
static bool isLindenEstate();
|
||||
|
||||
|
||||
const std::string getOwnerName() const;
|
||||
void setOwnerName(const std::string& name);
|
||||
|
||||
|
|
@ -374,7 +374,7 @@ protected:
|
|||
|
||||
void commitEstateAccess();
|
||||
void commitEstateManagers();
|
||||
|
||||
|
||||
bool checkSunHourSlider(LLUICtrl* child_ctrl);
|
||||
|
||||
U32 mEstateID;
|
||||
|
|
@ -387,7 +387,7 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo
|
|||
public:
|
||||
LLPanelEstateCovenant();
|
||||
~LLPanelEstateCovenant() {}
|
||||
|
||||
|
||||
bool postBuild() override;
|
||||
void updateChild(LLUICtrl* child_ctrl) override;
|
||||
bool refreshFromRegion(LLViewerRegion* region) override;
|
||||
|
|
@ -450,7 +450,7 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
|
|||
public:
|
||||
LLPanelRegionExperiences(){}
|
||||
bool postBuild() override;
|
||||
|
||||
|
||||
static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response);
|
||||
static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id);
|
||||
|
||||
|
|
@ -515,7 +515,7 @@ private:
|
|||
void onAllowedSearchEdit(const std::string& search_string);
|
||||
void onAllowedGroupsSearchEdit(const std::string& search_string);
|
||||
void onBannedSearchEdit(const std::string& search_string);
|
||||
|
||||
|
||||
// Group picker callback is different, can't use core methods below
|
||||
bool addAllowedGroup(const LLSD& notification, const LLSD& response);
|
||||
void addAllowedGroup2(LLUUID id);
|
||||
|
|
|
|||
|
|
@ -359,7 +359,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool
|
|||
|
||||
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)
|
||||
{
|
||||
|
|
@ -487,7 +488,8 @@ void LLHeroProbeManager::updateUniforms()
|
|||
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()
|
||||
|
|
|
|||
|
|
@ -2398,7 +2398,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
|
|||
message_data["region_id"].asUUID(),
|
||||
position,
|
||||
local_bin_bucket.data(),
|
||||
local_bin_bucket.size(),
|
||||
S32(local_bin_bucket.size()),
|
||||
local_sender,
|
||||
message_data["asset_id"].asUUID());
|
||||
});
|
||||
|
|
|
|||
|
|
@ -957,11 +957,11 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
|
|||
else if (root_id.notNull())
|
||||
{
|
||||
cat_array_t* cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
|
||||
if (cats)
|
||||
if(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();
|
||||
if (rv.isNull() || folder_id < rv)
|
||||
|
|
|
|||
|
|
@ -264,12 +264,12 @@ bool LLTinyGLTFHelper::saveModel(const std::string& filename, tinygltf::Model& m
|
|||
std::string filename_lc = filename;
|
||||
LLStringUtil::toLower(filename_lc);
|
||||
|
||||
|
||||
|
||||
bool embed_images = false;
|
||||
bool embed_buffers = false;
|
||||
bool pretty_print = true;
|
||||
bool write_binary = false;
|
||||
|
||||
|
||||
|
||||
if (std::string::npos == filename_lc.rfind(".gltf"))
|
||||
{ // file is binary
|
||||
|
|
|
|||
|
|
@ -2768,7 +2768,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventory(
|
|||
|
||||
// *HACK: In order to resolve SL-22177, we need to block drags
|
||||
// from notecards and objects onto other objects.
|
||||
if ((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
|
||||
if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
|
||||
{
|
||||
return ACCEPT_NO;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.mFeatures = shader.mFeatures;
|
||||
|
|
@ -275,6 +275,11 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool
|
|||
variant.addPermutation("UNLIT", "1");
|
||||
}
|
||||
|
||||
if (multi_uv)
|
||||
{
|
||||
variant.addPermutation("MULTI_UV", "1");
|
||||
}
|
||||
|
||||
if (alpha_blend)
|
||||
{
|
||||
variant.addPermutation("ALPHA_BLEND", "1");
|
||||
|
|
@ -321,8 +326,9 @@ static bool make_gltf_variants(LLGLSLShader& shader, bool use_sun_shadow)
|
|||
bool alpha_blend = i & LLGLSLShader::GLTFVariant::ALPHA_BLEND;
|
||||
bool rigged = i & LLGLSLShader::GLTFVariant::RIGGED;
|
||||
bool unlit = i & LLGLSLShader::GLTFVariant::UNLIT;
|
||||
bool multi_uv = i & LLGLSLShader::GLTFVariant::MULTI_UV;
|
||||
|
||||
if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, use_sun_shadow))
|
||||
if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, multi_uv, use_sun_shadow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
//static
|
||||
//static
|
||||
LLImageRaw* LLViewerTextureManager::getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype)
|
||||
{
|
||||
return gTextureList.getRawImageFromMemory(data, size, mimetype);
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ private: // PoundLife - Improved Object Inspect
|
|||
LLGLenum primary_format = 0,
|
||||
const LLUUID& force_id = LLUUID::null
|
||||
);
|
||||
|
||||
|
||||
LLImageRaw* getRawImageFromMemory(const U8* data, U32 size, std::string_view mimetype);
|
||||
LLViewerFetchedTexture* getImageFromMemory(const U8* data, U32 size, std::string_view mimetype);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
/**
|
||||
/**
|
||||
* @file llvlcomposition.cpp
|
||||
* @brief Viewer-side representation of a composition layer...
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
|
@ -428,8 +428,7 @@ const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT]
|
|||
|
||||
LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) :
|
||||
LLTerrainMaterials(),
|
||||
LLViewerLayer(width, scale),
|
||||
mParamsReady(false)
|
||||
LLViewerLayer(width, scale)
|
||||
{
|
||||
// Load Terrain Textures - Original ones
|
||||
const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures();
|
||||
|
|
@ -471,7 +470,7 @@ bool LLVLComposition::generateHeights(const F32 x, const F32 y,
|
|||
|
||||
llassert(mSurfacep);
|
||||
|
||||
if (!mSurfacep || !mSurfacep->getRegion())
|
||||
if (!mSurfacep || !mSurfacep->getRegion())
|
||||
{
|
||||
// We don't always have the region yet here....
|
||||
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[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[1] = vec[1]*(0.2222222222f);
|
||||
|
|
@ -989,7 +988,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
|||
{
|
||||
unboost_minimap_material(mDetailMaterials[i]);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
/**
|
||||
/**
|
||||
* @file llvlcomposition.h
|
||||
* @brief Viewer-side representation of a composition layer...
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
|
@ -115,8 +115,7 @@ public:
|
|||
bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
|
||||
bool generateComposition();
|
||||
// Generate texture from composition values.
|
||||
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);
|
||||
bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
|
||||
|
||||
// Use these as indeces ito the get/setters below that use 'corner'
|
||||
enum ECorner
|
||||
|
|
|
|||
|
|
@ -1982,9 +1982,8 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL
|
|||
LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle);
|
||||
|
||||
U32 num_entries = 0;
|
||||
U32 inmem_entries = 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)
|
||||
{
|
||||
// Only write out GLTFOverrides that we can actually apply again on import.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
|
||||
|
||||
{
|
||||
if (!mbCanSelect
|
||||
|| mDrawable->isDead()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
border="true"
|
||||
follows="top|left"
|
||||
height="460"
|
||||
help_topic="panel_region_terrain_tab"
|
||||
label="Terrain"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
|
|
@ -225,13 +224,12 @@
|
|||
left="0"
|
||||
name="terrain_tabs"
|
||||
tab_position="top"
|
||||
tab_width="100"
|
||||
tab_width="110"
|
||||
tab_padding_right="3"
|
||||
top_pad="0"
|
||||
width="700">
|
||||
<panel
|
||||
border="true"
|
||||
class="panel_settings_terrain_elevation"
|
||||
filename="panel_settings_terrain_elevation.xml"
|
||||
label="Elevation"
|
||||
layout="topleft"
|
||||
|
|
@ -240,7 +238,6 @@
|
|||
name="terrain_elevation_panel" />
|
||||
<panel
|
||||
border="true"
|
||||
class="panel_settings_terrain_transform"
|
||||
filename="panel_settings_terrain_transform.xml"
|
||||
label="Transforms"
|
||||
layout="topleft"
|
||||
|
|
@ -256,8 +253,8 @@
|
|||
height="20"
|
||||
label="Apply"
|
||||
layout="topleft"
|
||||
left="353"
|
||||
left="351"
|
||||
name="apply_btn"
|
||||
top_delta="290"
|
||||
top_delta="310"
|
||||
width="100" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,62 @@
|
|||
left="0"
|
||||
name="panel_settings_terrain_transform"
|
||||
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
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -17,19 +73,10 @@
|
|||
layout="topleft"
|
||||
name="terrain0ScaleU_label"
|
||||
left="10"
|
||||
top_pad="3"
|
||||
top_pad="0"
|
||||
width="170">
|
||||
Scale u
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="-2"
|
||||
name="terrain0ScaleU_horizontal"
|
||||
width="430" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -37,7 +84,7 @@
|
|||
label="Scale u"
|
||||
label_width="0"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
left="46"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
name="terrain0ScaleU"
|
||||
|
|
@ -78,6 +125,15 @@
|
|||
max_val="100"
|
||||
name="terrain3ScaleU"
|
||||
width="64" />
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="8"
|
||||
name="terrainScaleU_horizontal"
|
||||
width="432" />
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -88,19 +144,10 @@
|
|||
layout="topleft"
|
||||
name="terrain0ScaleV_label"
|
||||
left="10"
|
||||
top_pad="3"
|
||||
top_pad="0"
|
||||
width="170">
|
||||
Scale v
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="-2"
|
||||
name="terrain0ScaleV_horizontal"
|
||||
width="430" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -108,7 +155,7 @@
|
|||
label="Scale v"
|
||||
label_width="0"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
left="46"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
name="terrain0ScaleV"
|
||||
|
|
@ -149,6 +196,15 @@
|
|||
max_val="100"
|
||||
name="terrain3ScaleV"
|
||||
width="64" />
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="8"
|
||||
name="terrainScaleV_horizontal"
|
||||
width="432" />
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -159,19 +215,10 @@
|
|||
layout="topleft"
|
||||
name="terrain0Rotation_label"
|
||||
left="10"
|
||||
top_pad="3"
|
||||
top_pad="0"
|
||||
width="170">
|
||||
Rotation
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="-2"
|
||||
name="terrain0Rotation_horizontal"
|
||||
width="430" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -179,7 +226,7 @@
|
|||
label="Rotation"
|
||||
label_width="0"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
left="46"
|
||||
min_val="-360"
|
||||
max_val="360"
|
||||
name="terrain0Rotation"
|
||||
|
|
@ -192,8 +239,8 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-360"
|
||||
max_val="360"
|
||||
name="terrain1Rotation"
|
||||
width="64" />
|
||||
<spinner
|
||||
|
|
@ -204,8 +251,8 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-360"
|
||||
max_val="360"
|
||||
name="terrain2Rotation"
|
||||
width="64" />
|
||||
<spinner
|
||||
|
|
@ -216,10 +263,19 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-360"
|
||||
max_val="360"
|
||||
name="terrain3Rotation"
|
||||
width="64" />
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="8"
|
||||
name="terrainRotation_horizontal"
|
||||
width="432" />
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -230,19 +286,10 @@
|
|||
layout="topleft"
|
||||
name="terrain0OffsetU_label"
|
||||
left="10"
|
||||
top_pad="3"
|
||||
top_pad="0"
|
||||
width="170">
|
||||
Offset y
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="-2"
|
||||
name="terrain0OffsetU_horizontal"
|
||||
width="430" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -250,7 +297,7 @@
|
|||
label="Offset u"
|
||||
label_width="0"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
left="46"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain0OffsetU"
|
||||
|
|
@ -263,8 +310,8 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain1OffsetU"
|
||||
width="64" />
|
||||
<spinner
|
||||
|
|
@ -275,8 +322,8 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain2OffsetU"
|
||||
width="64" />
|
||||
<spinner
|
||||
|
|
@ -287,10 +334,19 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain3OffsetU"
|
||||
width="64" />
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="8"
|
||||
name="terrainOffsetU_horizontal"
|
||||
width="432" />
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -301,19 +357,10 @@
|
|||
layout="topleft"
|
||||
name="terrain0OffsetV_label"
|
||||
left="10"
|
||||
top_pad="3"
|
||||
top_pad="0"
|
||||
width="170">
|
||||
Offset v
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="-2"
|
||||
name="terrain0OffsetV_horizontal"
|
||||
width="430" />
|
||||
<spinner
|
||||
follows="left|top"
|
||||
height="19"
|
||||
|
|
@ -321,7 +368,7 @@
|
|||
label="Offset v"
|
||||
label_width="0"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
left="46"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain0OffsetV"
|
||||
|
|
@ -334,8 +381,8 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain1OffsetV"
|
||||
width="64" />
|
||||
<spinner
|
||||
|
|
@ -346,8 +393,8 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain2OffsetV"
|
||||
width="64" />
|
||||
<spinner
|
||||
|
|
@ -358,8 +405,17 @@
|
|||
label_width="0"
|
||||
layout="topleft"
|
||||
left_delta="110"
|
||||
min_val="-100"
|
||||
max_val="100"
|
||||
min_val="-999"
|
||||
max_val="999"
|
||||
name="terrain3OffsetV"
|
||||
width="64" />
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="top|left"
|
||||
height="0"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
top_pad="8"
|
||||
name="terrainOffsetV_horizontal"
|
||||
width="432" />
|
||||
</panel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue