diff --git a/autobuild.xml b/autobuild.xml
index 9a9cd133f0..3394878f08 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -3407,6 +3407,66 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
version
0.132.2
+ tinygltf
+
tracy
canonical_repo
diff --git a/indra/cmake/TinyGLTF.cmake b/indra/cmake/TinyGLTF.cmake
new file mode 100644
index 0000000000..bb731637a0
--- /dev/null
+++ b/indra/cmake/TinyGLTF.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+use_prebuilt_binary(tinygltf)
+
+set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf)
+
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index d4f2ca7389..20a16fa94b 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -88,7 +88,8 @@ class LLColor4
const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec
- const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec
+ const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
const LLColor4& setAlpha(F32 a);
@@ -337,6 +338,15 @@ inline const LLColor4& LLColor4::set(const F32 *vec)
return (*this);
}
+inline const LLColor4& LLColor4::set(const F64 *vec)
+{
+ mV[VX] = static_cast(vec[VX]);
+ mV[VY] = static_cast(vec[VY]);
+ mV[VZ] = static_cast(vec[VZ]);
+ mV[VW] = static_cast(vec[VW]);
+ return (*this);
+}
+
// deprecated
inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
{
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index 792892f024..b63bda7b0b 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -10,6 +10,8 @@ include(LLCoreHttp)
include(LLXML)
include(LLPhysicsExtensions)
include(LLCharacter)
+include(LLRender)
+include(TinyGLTF)
include(ColladaDom)
include_directories(
@@ -17,10 +19,12 @@ include_directories(
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
# ${LIBS_PREBUILT_DIR}/include/collada
# ${LIBS_PREBUILT_DIR}/include/collada/1.4
${COLLADA_INCLUDE_DIRS}
${LLCHARACTER_INCLUDE_DIRS}
+ ${TINYGLTF_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -34,6 +38,7 @@ include_directories(SYSTEM
set(llprimitive_SOURCE_FILES
lldaeloader.cpp
+ llgltfloader.cpp
llmaterialid.cpp
llmaterial.cpp
llmaterialtable.cpp
@@ -52,6 +57,7 @@ set(llprimitive_SOURCE_FILES
set(llprimitive_HEADER_FILES
CMakeLists.txt
lldaeloader.h
+ llgltfloader.h
legacy_object_types.h
llmaterial.h
llmaterialid.h
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 47c5fb7924..5276316914 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2639,20 +2639,6 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD&
return (status == LLModel::NO_ERRORS);
}
-//static
-LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
-{
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
- LLModel* ret = new LLModel(volume_params, 0.f);
- createVolumeFacesFromDomMesh(ret, mesh);
- if (ret->mLabel.empty())
- {
- ret->mLabel = getElementLabel(mesh);
- }
- return ret;
-}
-
//static diff version supports creating multiple models when material counts spill
// over the 8 face server-side limit
//
@@ -2755,31 +2741,3 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& mo
return true;
}
-
-bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh)
-{
- if (mesh)
- {
- pModel->ClearFacesAndMaterials();
-
- LLSD placeholder;
- addVolumeFacesFromDomMesh(pModel, mesh, placeholder);
-
- if (pModel->getNumVolumeFaces() > 0)
- {
- pModel->normalizeVolumeFaces();
- pModel->optimizeVolumeFaces();
-
- if (pModel->getNumVolumeFaces() > 0)
- {
- return true;
- }
- }
- }
- else
- {
- LL_WARNS() << "no mesh found" << LL_ENDL;
- }
-
- return false;
-}
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 7ed1ea787a..acc7a4900a 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -95,9 +95,6 @@ protected:
bool verifyController( domController* pController );
static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg);
- static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
-
- static LLModel* loadModelFromDomMesh(domMesh* mesh);
// Loads a mesh breaking it into one or more models as necessary
// to get around volume face limitations while retaining >8 materials
diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp
new file mode 100644
index 0000000000..3ec11f70c6
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.cpp
@@ -0,0 +1,404 @@
+/**
+ * @file LLGLTFLoader.cpp
+ * @brief LLGLTFLoader class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "LLGLTFLoader.h"
+
+// Import & define single-header gltf import/export lib
+#define TINYGLTF_IMPLEMENTATION
+#define TINYGLTF_USE_CPP14 // default is C++ 11
+
+// tinygltf by default loads image files using STB
+#define STB_IMAGE_IMPLEMENTATION
+// to use our own image loading:
+// 1. replace this definition with TINYGLTF_NO_STB_IMAGE
+// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)
+
+// tinygltf saves image files using STB
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data)
+
+// Additionally, disable inclusion of STB header files entirely with
+// TINYGLTF_NO_INCLUDE_STB_IMAGE
+// TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
+#include "tinygltf\tiny_gltf.h"
+
+
+// TODO: includes inherited from dae loader. Validate / prune
+
+#include
+
+#include "llsdserialize.h"
+#include "lljoint.h"
+
+#include "glh/glh_linear.h"
+#include "llmatrix4a.h"
+
+#include
+#include
+
+static const std::string lod_suffix[LLModel::NUM_LODS] =
+{
+ "_LOD0",
+ "_LOD1",
+ "_LOD2",
+ "",
+ "_PHYS",
+};
+
+const U32 LIMIT_MATERIALS_OUTPUT = 12;
+
+LLGLTFLoader::LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit) //,
+ //bool preprocess)
+ : LLModelLoader( filename,
+ lod,
+ load_cb,
+ joint_lookup_func,
+ texture_load_func,
+ state_cb,
+ opaque_userdata,
+ jointTransformMap,
+ jointsFromNodes,
+ jointAliasMap,
+ maxJointsPerMesh ),
+ mGeneratedModelLimit(modelLimit),
+ //mPreprocessGLTF(preprocess),
+ mMeshesLoaded(false),
+ mMaterialsLoaded(false)
+{
+}
+
+LLGLTFLoader::~LLGLTFLoader() {}
+
+bool LLGLTFLoader::OpenFile(const std::string &filename)
+{
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename.rfind(".gltf"))
+ { // file is binary
+ mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+
+ if (!mGltfLoaded)
+ {
+ if (!warn_msg.empty())
+ LL_WARNS("GLTF_IMPORT") << "gltf load warning: " << warn_msg.c_str() << LL_ENDL;
+ if (!error_msg.empty())
+ LL_WARNS("GLTF_IMPORT") << "gltf load error: " << error_msg.c_str() << LL_ENDL;
+ return false;
+ }
+
+ mMeshesLoaded = parseMeshes();
+ if (mMeshesLoaded) uploadMeshes();
+
+ mMaterialsLoaded = parseMaterials();
+ if (mMaterialsLoaded) uploadMaterials();
+
+ return (mMeshesLoaded || mMaterialsLoaded);
+}
+
+bool LLGLTFLoader::parseMeshes()
+{
+ if (!mGltfLoaded) return false;
+
+ // 2022-04 DJH Volume params from dae example. TODO understand PCODE
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+
+ for (tinygltf::Mesh mesh : mGltfModel.meshes)
+ {
+ LLModel *pModel = new LLModel(volume_params, 0.f);
+
+ if (populateModelFromMesh(pModel, mesh) &&
+ (LLModel::NO_ERRORS == pModel->getStatus()) &&
+ validate_model(pModel))
+ {
+ mModelList.push_back(pModel);
+ }
+ else
+ {
+ setLoadState(ERROR_MODEL + pModel->getStatus());
+ delete(pModel);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh)
+{
+ pModel->mLabel = mesh.name;
+ int pos_idx, norm_idx, tan_idx, uv0_idx, uv1_idx, color0_idx, color1_idx;
+ tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a;
+
+ auto prims = mesh.primitives;
+ for (auto prim : prims)
+ {
+ if (prim.indices >= 0) indices_a = mGltfModel.accessors[prim.indices];
+
+ pos_idx = (prim.attributes.count("POSITION") > 0) ? prim.attributes.at("POSITION") : -1;
+ if (pos_idx >= 0)
+ {
+ positions_a = mGltfModel.accessors[pos_idx];
+ if (TINYGLTF_COMPONENT_TYPE_FLOAT != positions_a.componentType)
+ continue;
+ auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView];
+ auto positions_buf = mGltfModel.buffers[positions_bv.buffer];
+ //auto type = positions_vb.
+ //if (positions_buf.name
+ }
+
+ norm_idx = (prim.attributes.count("NORMAL") > 0) ? prim.attributes.at("NORMAL") : -1;
+ tan_idx = (prim.attributes.count("TANGENT") > 0) ? prim.attributes.at("TANGENT") : -1;
+ uv0_idx = (prim.attributes.count("TEXCOORDS_0") > 0) ? prim.attributes.at("TEXCOORDS_0") : -1;
+ uv1_idx = (prim.attributes.count("TEXCOORDS_1") > 0) ? prim.attributes.at("TEXCOORDS_1") : -1;
+ color0_idx = (prim.attributes.count("COLOR_0") > 0) ? prim.attributes.at("COLOR_0") : -1;
+ color1_idx = (prim.attributes.count("COLOR_1") > 0) ? prim.attributes.at("COLOR_1") : -1;
+
+ if (prim.mode == TINYGLTF_MODE_TRIANGLES)
+ {
+ //auto pos = mesh. TODO resume here DJH 2022-04
+ }
+ }
+
+ //pModel->addFace()
+ return false;
+}
+
+bool LLGLTFLoader::parseMaterials()
+{
+ if (!mGltfLoaded) return false;
+
+ // fill local texture data structures
+ mSamplers.clear();
+ for (auto in_sampler : mGltfModel.samplers)
+ {
+ gltf_sampler sampler;
+ sampler.magFilter = in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR;
+ sampler.minFilter = in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;;
+ sampler.wrapS = in_sampler.wrapS;
+ sampler.wrapT = in_sampler.wrapT;
+ sampler.name = in_sampler.name; // unused
+ mSamplers.push_back(sampler);
+ }
+
+ mImages.clear();
+ for (auto in_image : mGltfModel.images)
+ {
+ gltf_image image;
+ image.numChannels = in_image.component;
+ image.bytesPerChannel = in_image.bits >> 3; // Convert bits to bytes
+ image.pixelType = in_image.pixel_type; // Maps exactly, i.e. TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc
+ image.size = in_image.image.size();
+ image.height = in_image.height;
+ image.width = in_image.width;
+ image.data = in_image.image.data();
+
+ if (in_image.as_is)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Unsupported image encoding" << LL_ENDL;
+ return false;
+ }
+
+ if (image.size != image.height * image.width * image.numChannels * image.bytesPerChannel)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image size error" << LL_ENDL;
+ return false;
+ }
+
+ mImages.push_back(image);
+ }
+
+ mTextures.clear();
+ for (auto in_tex : mGltfModel.textures)
+ {
+ gltf_texture tex;
+ tex.imageIdx = in_tex.source;
+ tex.samplerIdx = in_tex.sampler;
+ tex.imageUuid.setNull();
+
+ if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size())
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL;
+ return false;
+ }
+
+ mTextures.push_back(tex);
+ }
+
+ // parse each material
+ for (tinygltf::Material gltf_material : mGltfModel.materials)
+ {
+ gltf_render_material mat;
+ mat.name = gltf_material.name;
+
+ tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness;
+ mat.hasPBR = true; // Always true, for now
+
+ mat.baseColor.set(pbr.baseColorFactor.data());
+ mat.hasBaseTex = pbr.baseColorTexture.index >= 0;
+ mat.baseColorTexIdx = pbr.baseColorTexture.index;
+ mat.baseColorTexCoords = pbr.baseColorTexture.texCoord;
+
+ mat.metalness = pbr.metallicFactor;
+ mat.roughness = pbr.roughnessFactor;
+ mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0;
+ mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index;
+ mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord;
+
+ mat.normalScale = gltf_material.normalTexture.scale;
+ mat.hasNormalTex = gltf_material.normalTexture.index >= 0;
+ mat.normalTexIdx = gltf_material.normalTexture.index;
+ mat.normalTexCoords = gltf_material.normalTexture.texCoord;
+
+ mat.occlusionScale = gltf_material.occlusionTexture.strength;
+ mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0;
+ mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
+ mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord;
+
+ mat.emissiveColor.set(gltf_material.emissiveFactor.data());
+ mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0;
+ mat.emissiveTexIdx = gltf_material.emissiveTexture.index;
+ mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord;
+
+ mat.alphaMode = gltf_material.alphaMode;
+ mat.alphaMask = gltf_material.alphaCutoff;
+
+ if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) ||
+ (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) ||
+ (mat.hasEmissiveTex && (mat.emissiveTexIdx >= mTextures.size())) ||
+ (mat.hasBaseTex && (mat.baseColorTexIdx >= mTextures.size())) ||
+ (mat.hasMRTex && (mat.metalRoughTexIdx >= mTextures.size())))
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL;
+ return false;
+ }
+
+ if ((mat.hasNormalTex && (mat.normalTexCoords > 2)) || // mesh can have up to 3 sets of UV
+ (mat.hasOcclusionTex && (mat.occlusionTexCoords > 2)) ||
+ (mat.hasEmissiveTex && (mat.emissiveTexCoords > 2)) ||
+ (mat.hasBaseTex && (mat.baseColorTexCoords > 2)) ||
+ (mat.hasMRTex && (mat.metalRoughTexCoords > 2)))
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL;
+ return false;
+ }
+
+ mMaterials.push_back(mat);
+ }
+
+ return true;
+}
+
+// TODO: convert raw vertex buffers to UUIDs
+void LLGLTFLoader::uploadMeshes()
+{
+ llassert(0);
+}
+
+// convert raw image buffers to texture UUIDs & assemble into a render material
+void LLGLTFLoader::uploadMaterials()
+{
+ for (gltf_render_material mat : mMaterials) // Initially 1 material per gltf file, but design for multiple
+ {
+ if (mat.hasBaseTex)
+ {
+ gltf_texture& gtex = mTextures[mat.baseColorTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasMRTex)
+ {
+ gltf_texture& gtex = mTextures[mat.metalRoughTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasNormalTex)
+ {
+ gltf_texture& gtex = mTextures[mat.normalTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasOcclusionTex)
+ {
+ gltf_texture& gtex = mTextures[mat.occlusionTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasEmissiveTex)
+ {
+ gltf_texture& gtex = mTextures[mat.emissiveTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+ }
+}
+
+LLUUID LLGLTFLoader::imageBufferToTextureUUID(const gltf_texture& tex)
+{
+ //gltf_image& image = mImages[tex.imageIdx];
+ //gltf_sampler& sampler = mSamplers[tex.samplerIdx];
+
+ // fill an LLSD container with image+sampler data
+
+ // upload texture
+
+ // retrieve UUID
+
+ return LLUUID::null;
+}
diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h
new file mode 100644
index 0000000000..91389b5845
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.h
@@ -0,0 +1,207 @@
+/**
+ * @file LLGLTFLoader.h
+ * @brief LLGLTFLoader class definition
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGLTFLoader_H
+#define LL_LLGLTFLoader_H
+
+#include "tinygltf/tiny_gltf.h"
+
+#include "llglheaders.h"
+#include "llmodelloader.h"
+
+// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD
+
+class gltf_sampler
+{
+public:
+ // Uses GL enums
+ S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR
+ S32 magFilter; // GL_NEAREST or GL_LINEAR
+ S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored.
+ std::string name; // optional, currently unused
+ // extensions and extras are sampler optional fields that we don't support - at least initially
+};
+
+class gltf_image
+{
+public:// Note that glTF images are defined with row 0 at the top (opposite of OpenGL)
+ U8* data; // ptr to decoded image data
+ U32 size; // in bytes, regardless of channel width
+ U32 width;
+ U32 height;
+ U32 numChannels; // range 1..4
+ U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input
+ U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT
+};
+
+class gltf_texture
+{
+public:
+ U32 imageIdx;
+ U32 samplerIdx;
+ LLUUID imageUuid = LLUUID::null;
+};
+
+class gltf_render_material
+{
+public:
+ std::string name;
+
+ // scalar values
+ LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present.
+ double metalness;
+ double roughness;
+ double normalScale; // scale applies only to X,Y components of normal
+ double occlusionScale; // strength multiplier for occlusion
+ LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent)
+ std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
+ double alphaMask; // alpha cut-off
+
+ // textures
+ U32 baseColorTexIdx; // always sRGB encoded
+ U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel
+ U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0)
+ U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded
+ U32 emissiveTexIdx; // always stored as sRGB, in nits (candela / meter^2)
+
+ // texture coordinates
+ U32 baseColorTexCoords;
+ U32 metalRoughTexCoords;
+ U32 normalTexCoords;
+ U32 occlusionTexCoords;
+ U32 emissiveTexCoords;
+
+ // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??
+
+ bool hasPBR;
+ bool hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex;
+
+ // This field is populated after upload
+ LLUUID material_uuid = LLUUID::null;
+
+};
+
+class gltf_mesh
+{
+public:
+ std::string name;
+
+ // TODO add mesh import DJH 2022-04
+
+};
+
+class LLGLTFLoader : public LLModelLoader
+{
+ public:
+ typedef std::map material_map;
+
+ LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit); //,
+ //bool preprocess );
+ virtual ~LLGLTFLoader();
+
+ virtual bool OpenFile(const std::string &filename);
+
+protected:
+ tinygltf::Model mGltfModel;
+ bool mGltfLoaded;
+ bool mMeshesLoaded;
+ bool mMaterialsLoaded;
+
+ std::vector mMeshes;
+ std::vector mMaterials;
+
+ std::vector mTextures;
+ std::vector mImages;
+ std::vector mSamplers;
+
+private:
+ bool parseMeshes();
+ void uploadMeshes();
+ bool parseMaterials();
+ void uploadMaterials();
+ bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh);
+ LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
+
+ U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
+ // bool mPreprocessGLTF;
+
+ /* Below inherited from dae loader - unknown if/how useful here
+
+ void processElement(gltfElement *element, bool &badElement, GLTF *gltf);
+ void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin);
+
+ material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf);
+ LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf);
+ LLColor4 getGltfColor(gltfElement *element);
+
+ gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name);
+
+ bool isNodeAJoint(gltfNode *pNode);
+ void processJointNode(gltfNode *pNode, std::map &jointTransforms);
+ void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform);
+ void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform);
+ void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform);
+ void buildJointToNodeMappingFromScene(gltfElement *pRoot);
+ void processJointToNodeMapping(gltfNode *pNode);
+ void processChildJoints(gltfNode *pParentNode);
+
+ bool verifyCount(int expected, int result);
+
+ // Verify that a controller matches vertex counts
+ bool verifyController(gltfController *pController);
+
+ static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg);
+ static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh);
+
+ static LLModel *loadModelFromGltfMesh(gltfMesh *mesh);
+
+ // Loads a mesh breaking it into one or more models as necessary
+ // to get around volume face limitations while retaining >8 materials
+ //
+ bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector &models_out, U32 submodel_limit);
+
+ static std::string getElementLabel(gltfElement *element);
+ static size_t getSuffixPosition(std::string label);
+ static std::string getLodlessLabel(gltfElement *element);
+
+ static std::string preprocessGLTF(std::string filename);
+ */
+
+};
+#endif // LL_LLGLTFLLOADER_H
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 3bacbfc522..17c3242f1e 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -172,7 +172,8 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
std::string::size_type i = model_filename.rfind(".");
if (i != std::string::npos)
{
- slm_filename.replace(i, model_filename.size()-1, ".slm");
+ slm_filename.resize(i, '\0');
+ slm_filename.append(".slm");
return true;
}
else
@@ -184,7 +185,7 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
bool LLModelLoader::doLoadModel()
{
//first, look for a .slm file of the same name that was modified later
- //than the .dae
+ //than the specified model file
if (mTrySLM)
{
@@ -194,13 +195,13 @@ bool LLModelLoader::doLoadModel()
llstat slm_status;
if (LLFile::stat(slm_filename, &slm_status) == 0)
{ //slm file exists
- llstat dae_status;
- if (LLFile::stat(mFilename, &dae_status) != 0 ||
- dae_status.st_mtime < slm_status.st_mtime)
+ llstat model_file_status;
+ if (LLFile::stat(mFilename, &model_file_status) != 0 ||
+ model_file_status.st_mtime < slm_status.st_mtime)
{
if (loadFromSLM(slm_filename))
{ //slm successfully loaded, if this fails, fall through and
- //try loading from dae
+ //try loading from model file
mLod = -1; //successfully loading from an slm implicitly sets all
//LoDs
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index ee4e925495..74f675476f 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -89,6 +89,14 @@ const F32 LIGHT_MIN_CUTOFF = 0.0f;
const F32 LIGHT_DEFAULT_CUTOFF = 0.0f;
const F32 LIGHT_MAX_CUTOFF = 180.f;
+// reflection probes
+const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f;
+const F32 REFLECTION_PROBE_MAX_AMBIANCE = 1.f;
+const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f;
+const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f;
+const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f;
+const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f;
+
// "Tension" => [0,10], increments of 0.1
const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f;
const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f;
@@ -1825,6 +1833,118 @@ bool LLLightParams::fromLLSD(LLSD& sd)
//============================================================================
+//============================================================================
+
+LLReflectionProbeParams::LLReflectionProbeParams()
+{
+ mType = PARAMS_REFLECTION_PROBE;
+}
+
+BOOL LLReflectionProbeParams::pack(LLDataPacker &dp) const
+{
+ dp.packF32(mAmbiance, "ambiance");
+ dp.packF32(mClipDistance, "clip_distance");
+ dp.packU8(mFlags, "flags");
+ return TRUE;
+}
+
+BOOL LLReflectionProbeParams::unpack(LLDataPacker &dp)
+{
+ F32 ambiance;
+ F32 clip_distance;
+
+ dp.unpackF32(ambiance, "ambiance");
+ setAmbiance(ambiance);
+
+ dp.unpackF32(clip_distance, "clip_distance");
+ setClipDistance(clip_distance);
+
+ dp.unpackU8(mFlags, "flags");
+
+ return TRUE;
+}
+
+bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_REFLECTION_PROBE)
+ {
+ return false;
+ }
+ const LLReflectionProbeParams *param = (const LLReflectionProbeParams*)&data;
+ if (param->mAmbiance != mAmbiance)
+ {
+ return false;
+ }
+ if (param->mClipDistance != mClipDistance)
+ {
+ return false;
+ }
+ if (param->mFlags != mFlags)
+ {
+ return false;
+ }
+ return true;
+}
+
+void LLReflectionProbeParams::copy(const LLNetworkData& data)
+{
+ const LLReflectionProbeParams *param = (LLReflectionProbeParams*)&data;
+ mType = param->mType;
+ mAmbiance = param->mAmbiance;
+ mClipDistance = param->mClipDistance;
+ mFlags = param->mFlags;
+}
+
+LLSD LLReflectionProbeParams::asLLSD() const
+{
+ LLSD sd;
+ sd["ambiance"] = getAmbiance();
+ sd["clip_distance"] = getClipDistance();
+ sd["flags"] = mFlags;
+ return sd;
+}
+
+bool LLReflectionProbeParams::fromLLSD(LLSD& sd)
+{
+ if (!sd.has("ambiance") ||
+ !sd.has("clip_distance") ||
+ !sd.has("flags"))
+ {
+ return false;
+ }
+
+ setAmbiance((F32)sd["ambiance"].asReal());
+ setClipDistance((F32)sd["clip_distance"].asReal());
+ mFlags = (U8) sd["flags"].asInteger();
+
+ return true;
+}
+
+void LLReflectionProbeParams::setIsBox(bool is_box)
+{
+ if (is_box)
+ {
+ mFlags |= FLAG_BOX_VOLUME;
+ }
+ else
+ {
+ mFlags &= ~FLAG_BOX_VOLUME;
+ }
+}
+
+void LLReflectionProbeParams::setIsDynamic(bool is_dynamic)
+{
+ if (is_dynamic)
+ {
+ mFlags |= FLAG_DYNAMIC;
+ }
+ else
+ {
+ mFlags &= ~FLAG_DYNAMIC;
+ }
+}
+
+//============================================================================
LLFlexibleObjectData::LLFlexibleObjectData()
{
mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS;
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 211975c1dd..f04cd38d40 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -116,6 +116,7 @@ public:
PARAMS_MESH = 0x60,
PARAMS_EXTENDED_MESH = 0x70,
PARAMS_RENDER_MATERIAL = 0x80,
+ PARAMS_REFLECTION_PROBE = 0x90,
};
public:
@@ -179,6 +180,50 @@ public:
F32 getCutoff() const { return mCutoff; }
};
+extern const F32 REFLECTION_PROBE_MIN_AMBIANCE;
+extern const F32 REFLECTION_PROBE_MAX_AMBIANCE;
+extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE;
+extern const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE;
+extern const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE;
+extern const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
+
+class LLReflectionProbeParams : public LLNetworkData
+{
+public:
+ enum EFlags : U8
+ {
+ FLAG_BOX_VOLUME = 0x01, // use a box influence volume
+ FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe
+ };
+
+protected:
+ F32 mAmbiance = REFLECTION_PROBE_DEFAULT_AMBIANCE;
+ F32 mClipDistance = REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
+ U8 mFlags = 0;
+
+public:
+ LLReflectionProbeParams();
+ /*virtual*/ BOOL pack(LLDataPacker& dp) const;
+ /*virtual*/ BOOL unpack(LLDataPacker& dp);
+ /*virtual*/ bool operator==(const LLNetworkData& data) const;
+ /*virtual*/ void copy(const LLNetworkData& data);
+ // LLSD implementations here are provided by Eddy Stryker.
+ // NOTE: there are currently unused in protocols
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setAmbiance(F32 ambiance) { mAmbiance = llclamp(ambiance, REFLECTION_PROBE_MIN_AMBIANCE, REFLECTION_PROBE_MAX_AMBIANCE); }
+ void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); }
+ void setIsBox(bool is_box);
+ void setIsDynamic(bool is_dynamic);
+
+ F32 getAmbiance() const { return mAmbiance; }
+ F32 getClipDistance() const { return mClipDistance; }
+ bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; }
+ bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; }
+};
+
//-------------------------------------------------
// This structure is also used in the part of the
// code that creates new flexible objects.
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index f95027d4f6..84290b5abc 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -473,6 +473,8 @@ void LLRenderTarget::release()
void LLRenderTarget::bindTarget()
{
+ llassert(mFBO);
+
if (mFBO)
{
stop_glerror();
@@ -514,6 +516,7 @@ void LLRenderTarget::bindTarget()
void LLRenderTarget::clear(U32 mask_in)
{
LL_PROFILE_GPU_ZONE("clear");
+ llassert(mFBO);
U32 mask = GL_COLOR_BUFFER_BIT;
if (mUseDepth)
{
@@ -579,6 +582,7 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
void LLRenderTarget::flush(bool fetch_depth)
{
gGL.flush();
+ llassert(mFBO);
if (!mFBO)
{
gGL.getTexUnit(0)->bind(this);
diff --git a/indra/newview/app_settings/graphic_preset_controls.xml b/indra/newview/app_settings/graphic_preset_controls.xml
index 4f0684945b..4868db86d2 100644
--- a/indra/newview/app_settings/graphic_preset_controls.xml
+++ b/indra/newview/app_settings/graphic_preset_controls.xml
@@ -41,8 +41,10 @@
RenderLocalLights
RenderMaxPartCount
RenderObjectBump
+ RenderPBR
RenderQualityPerformance
RenderReflectionDetail
+ RenderReflectionProbeDetail
RenderShaderLightingMaxLevel
RenderShadowDetail
RenderShadowResolutionScale
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index f2321a6318..8b659ac075 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -13366,6 +13366,17 @@ Change of this parameter will affect the layout of buttons in notification toast
Value
2
+ RenderReflectionProbeDetail
+
+ Comment
+ Detail of reflections.
+ Persist
+ 1
+ Type
+ S32
+ Value
+ 1
+
RenderReflectionProbeDrawDistance
@@ -14382,6 +14393,17 @@ Change of this parameter will affect the layout of buttons in notification toast
Value
0
+ SelectInvisibleObjects
+
+ Comment
+ Select invisible objects
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 1
+
SelectOwnedOnly
Comment
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index 9fcee04c32..f693323d45 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -38,7 +38,7 @@ uniform sampler2D diffuseMap;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_texcoord1;
-VARYING vec4 vary_position;
+VARYING vec3 vary_position;
uniform samplerCube environmentMap;
@@ -74,7 +74,7 @@ void main()
vec3 amblit;
vec3 additive;
vec3 atten;
- vec3 pos = vary_position.xyz/vary_position.w;
+ vec3 pos = vary_position.xyz;
calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 8c1323ba1a..b3396baeba 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -1,5 +1,5 @@
/**
- * @file class2/deferred/reflectionProbeF.glsl
+ * @file class3/deferred/reflectionProbeF.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -42,6 +42,8 @@ layout (std140, binding = 1) uniform ReflectionProbes
mat4 refBox[REFMAP_COUNT];
// list of bounding spheres for reflection probes sorted by distance to camera (closest first)
vec4 refSphere[REFMAP_COUNT];
+ // extra parameters (currently only .x used for probe ambiance)
+ vec4 refParams[REFMAP_COUNT];
// index of cube map in reflectionProbes for a corresponding reflection probe
// e.g. cube map channel of refSphere[2] is stored in refIndex[2]
// refIndex.x - cubemap channel in reflectionProbes
@@ -55,9 +57,6 @@ layout (std140, binding = 1) uniform ReflectionProbes
// number of reflection probes present in refSphere
int refmapCount;
-
- // intensity of ambient light from reflection probes
- float reflectionAmbiance;
};
// Inputs
@@ -75,6 +74,8 @@ bool isAbove(vec3 pos, vec4 plane)
return (dot(plane.xyz, pos) + plane.w) > 0;
}
+int max_priority = 0;
+
// return true if probe at index i influences position pos
bool shouldSampleProbe(int i, vec3 pos)
{
@@ -87,6 +88,8 @@ bool shouldSampleProbe(int i, vec3 pos)
{
return false;
}
+
+ max_priority = max(max_priority, -refIndex[i].w);
}
else
{
@@ -99,6 +102,8 @@ bool shouldSampleProbe(int i, vec3 pos)
{ //outside bounding sphere
return false;
}
+
+ max_priority = max(max_priority, refIndex[i].w);
}
return true;
@@ -335,7 +340,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i)
}
}
-vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
+vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight)
{
float wsum = 0.0;
vec3 col = vec3(0,0,0);
@@ -344,8 +349,13 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
for (int idx = 0; idx < probeInfluences; ++idx)
{
int i = probeIndex[idx];
+ if (refIndex[i].w < max_priority)
+ {
+ continue;
+ }
float r = refSphere[i].w; // radius of sphere volume
float p = float(abs(refIndex[i].w)); // priority
+
float rr = r*r; // radius squred
float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz-refSphere[i].xyz;
@@ -359,8 +369,8 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
float atten = 1.0-max(d2-r2, 0.0)/(rr-r2);
w *= atten;
- w *= p; // boost weight based on priority
- col += refcol*w;
+ //w *= p; // boost weight based on priority
+ col += refcol*w*max(minweight, refParams[i].x);
wsum += w;
}
@@ -383,7 +393,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
float w = 1.0/d2;
w *= w;
- col += refcol*w;
+ col += refcol*w*max(minweight, refParams[i].x);
wsum += w;
}
}
@@ -399,7 +409,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod)
{
- vec3 col = sampleProbes(pos, dir, lod);
+ vec3 col = sampleProbes(pos, dir, lod, 0.f);
//desaturate
vec3 hcol = col *0.5;
@@ -413,7 +423,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod)
col *= 0.333333;
- return col*reflectionAmbiance;
+ return col;
}
@@ -445,12 +455,12 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l
if (glossiness > 0.0)
{
float lod = (1.0-glossiness)*reflection_lods;
- glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
+ glossenv = sampleProbes(pos, normalize(refnormpersp), lod, 1.f);
}
if (envIntensity > 0.0)
{
- legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0);
+ legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, 1.f);
}
}
@@ -473,4 +483,5 @@ void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 no
fresnel = min(fresnel+envIntensity, 1.0);
reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb);
color = mix(color.rgb, reflected_color, envIntensity);
- }
\ No newline at end of file
+ }
+
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 6afff307a1..3ab6fcd9cd 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -613,6 +613,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -630,7 +631,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
{
LLVector4a local_end = end;
LLVector4a local_intersection;
- if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
@@ -647,7 +648,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
for (std::vector::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it)
{
LLVOVolume *volp = *vol_it;
- if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h
index e079db042c..3146fe1bdd 100644
--- a/indra/newview/llcontrolavatar.h
+++ b/indra/newview/llcontrolavatar.h
@@ -68,6 +68,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 5a5dd78754..598311f31d 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -256,12 +256,9 @@ void LLDrawable::cleanupReferences()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
-
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
mFaces.clear();
- gObjectList.removeDrawable(this);
-
gPipeline.unlinkDrawable(this);
removeFromOctree();
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 48ca376a7a..9f308c7f6e 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -61,13 +61,11 @@ LLFilePicker LLFilePicker::sInstance;
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0"
#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
-#ifdef _CORY_TESTING
-#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
-#endif
+#define GLTF_FILTER L"glTF (*.gltf; *.glb)\0*.gltf;*.glb\0"
#define XML_FILTER L"XML files (*.xml)\0*.xml\0"
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
-#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
+#define MODEL_FILTER L"Model files (*.dae; *.gltf; *.glb)\0*.dae;*.gltf;*.glb\0"
#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
// Import filter
@@ -213,16 +211,14 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = ANIM_FILTER \
L"\0";
break;
- case FFLOAD_COLLADA:
+ case FFLOAD_GLTF:
+ mOFN.lpstrFilter = GLTF_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_COLLADA:
mOFN.lpstrFilter = COLLADA_FILTER \
L"\0";
break;
-#ifdef _CORY_TESTING
- case FFLOAD_GEOMETRY:
- mOFN.lpstrFilter = GEOMETRY_FILTER \
- L"\0";
- break;
-#endif
case FFLOAD_XML:
mOFN.lpstrFilter = XML_FILTER \
L"\0";
@@ -506,18 +502,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
L"XAF Anim File (*.xaf)\0*.xaf\0" \
L"\0";
break;
-#ifdef _CORY_TESTING
- case FFSAVE_GEOMETRY:
+ case FFSAVE_GLTF:
if (filename.empty())
{
- wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
- mOFN.lpstrDefExt = L"slg";
+ mOFN.lpstrDefExt = L"glb";
mOFN.lpstrFilter =
- L"SLG SL Geometry File (*.slg)\0*.slg\0" \
+ L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \
L"\0";
break;
-#endif
case FFSAVE_XML:
if (filename.empty())
{
@@ -683,15 +677,14 @@ std::vector* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //
allowedv->push_back("bvh");
allowedv->push_back("anim");
break;
- case FFLOAD_MODEL:
+ case FFLOAD_GLTF:
+ allowedv->push_back("gltf");
+ allowedv->push_back("glb");
+ break;
+ case FFLOAD_MODEL:
case FFLOAD_COLLADA:
allowedv->push_back("dae");
break;
-#ifdef _CORY_TESTING
- case FFLOAD_GEOMETRY:
- allowedv->push_back("slg");
- break;
-#endif
case FFLOAD_XML:
allowedv->push_back("xml");
break;
@@ -797,13 +790,11 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
extension = "xaf";
break;
-#ifdef _CORY_TESTING
- case FFSAVE_GEOMETRY:
+ case FFSAVE_GLTF:
type = "\?\?\?\?";
creator = "\?\?\?\?";
- extension = "slg";
+ extension = "glb";
break;
-#endif
// Compile fix
// case FFSAVE_XML:
// type = "\?\?\?\?";
@@ -1503,10 +1494,13 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
case FFLOAD_XML:
filtername = add_xml_filter_to_gtkchooser(picker);
break;
- case FFLOAD_COLLADA:
- filtername = add_collada_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_IMAGE:
+ case FFLOAD_GLTF:
+ filtername = dead_code_should_blow_up_here(picker);
+ break;
+ case FFLOAD_COLLADA:
+ filtername = add_collada_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_IMAGE:
filtername = add_imageload_filter_to_gtkchooser(picker);
break;
case FFLOAD_SCRIPT:
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 1aa5802d02..3844f5054f 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -84,9 +84,7 @@ public:
FFLOAD_WAV = 2,
FFLOAD_IMAGE = 3,
FFLOAD_ANIM = 4,
-#ifdef _CORY_TESTING
- FFLOAD_GEOMETRY = 5,
-#endif
+ FFLOAD_GLTF = 5,
FFLOAD_XML = 6,
FFLOAD_SLOBJECT = 7,
FFLOAD_RAW = 8,
@@ -109,9 +107,7 @@ public:
FFSAVE_BMP = 5,
FFSAVE_AVI = 6,
FFSAVE_ANIM = 7,
-#ifdef _CORY_TESTING
- FFSAVE_GEOMETRY = 8,
-#endif
+ FFSAVE_GLTF = 8,
FFSAVE_XML = 9,
FFSAVE_COLLADA = 10,
FFSAVE_RAW = 11,
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 428d9921cf..c88517f59b 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -98,7 +98,7 @@ private:
};
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
-: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
+: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL)
{
mMP = mp;
mLOD = lod;
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index 99f454bc7c..b45de1781a 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -68,7 +68,6 @@ LLHUDIcon::icon_instance_t LLHUDIcon::sScriptErrorIconInstances;
LLHUDIcon::LLHUDIcon(const U8 type) :
LLHUDObject(type),
mImagep(NULL),
- mPickID(0),
mScale(0.1f),
mHidden(FALSE),
mScriptError(false) // Mark script error icons
@@ -81,15 +80,11 @@ LLHUDIcon::~LLHUDIcon()
mImagep = NULL;
}
-void LLHUDIcon::renderIcon(BOOL for_select)
+void LLHUDIcon::render()
{
LLGLSUIDefault texture_state;
LLGLDepthTest gls_depth(GL_TRUE);
LLGLDisable gls_stencil(GL_STENCIL_TEST);
- if (for_select)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
if (mHidden)
return;
@@ -121,7 +116,7 @@ void LLHUDIcon::renderIcon(BOOL for_select)
mDistance = dist_vec(icon_position, camera->getOrigin());
- F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
+ F32 alpha_factor = clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
LLVector3 x_pixel_vec;
LLVector3 y_pixel_vec;
@@ -155,13 +150,6 @@ void LLHUDIcon::renderIcon(BOOL for_select)
LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale;
LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale;
- if (for_select)
- {
- // set color to unique color id for picking
- LLColor4U coloru((U8)(mPickID >> 16), (U8)(mPickID >> 8), (U8)mPickID);
- gGL.color4ubv(coloru.mV);
- }
- else
{
LLColor4 icon_color = LLColor4::white;
icon_color.mV[VALPHA] = alpha_factor;
@@ -222,11 +210,6 @@ void LLHUDIcon::markDead()
LLHUDObject::markDead();
}
-void LLHUDIcon::render()
-{
- renderIcon(FALSE);
-}
-
BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection)
{
if (mHidden)
@@ -319,37 +302,6 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
return FALSE;
}
-//static
-S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size)
-{
- S32 cur_id = start_id;
- icon_instance_t::iterator icon_it;
-
- for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
- {
- (*icon_it)->mPickID = cur_id;
- cur_id += step_size;
- }
-
- return cur_id;
-}
-
-//static
-LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id)
-{
- icon_instance_t::iterator icon_it;
-
- for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
- {
- if (pick_id == (*icon_it)->mPickID)
- {
- return *icon_it;
- }
- }
-
- return NULL;
-}
-
//static
LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection)
{
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index 8df1ef133f..1581d80245 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -56,8 +56,6 @@ public:
void restartLifeTimer() { mLifeTimer.reset(); }
- static S32 generatePickIDs(S32 start_id, S32 step_size);
- static LLHUDIcon* handlePick(S32 pick_id);
static LLHUDIcon* lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection);
static void updateAll();
@@ -81,14 +79,11 @@ protected:
LLHUDIcon(const U8 type);
~LLHUDIcon();
- void renderIcon(BOOL for_select); // common render code
-
private:
LLPointer mImagep;
LLFrameTimer mAnimTimer;
LLFrameTimer mLifeTimer;
F32 mDistance;
- S32 mPickID;
F32 mScale;
BOOL mHidden;
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 9786e8f857..7f6af2a6b1 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -30,6 +30,7 @@
#include "llmodelloader.h"
#include "lldaeloader.h"
+#include "llgltfloader.h"
#include "llfloatermodelpreview.h"
#include "llagent.h"
@@ -922,29 +923,52 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
std::map joint_alias_map;
getJointAliases(joint_alias_map);
- std::array lod_suffix;
- for(int i=0; i < LLModel::NUM_LODS; i++)
- {
- lod_suffix[i] = gSavedSettings.getString(sSuffixVarNames[i]);
- }
+ // three possible file extensions, .dae .gltf .glb
+ // check for .dae and if not then assume one of the .gl??
+ if (std::string::npos != filename.rfind(".dae"))
+ {
+ // allow LOD suffix configuration
+ std::array lod_suffix;
+ for (int i = 0; i < LLModel::NUM_LODS; i++)
+ {
+ lod_suffix[i] = gSavedSettings.getString(sSuffixVarNames[i]);
+ }
+ //
- mModelLoader = new LLDAELoader(
- filename,
- lod,
- &LLModelPreview::loadedCallback,
- &LLModelPreview::lookupJointByName,
- &LLModelPreview::loadTextures,
- &LLModelPreview::stateChangedCallback,
- this,
- mJointTransformMap,
- mJointsFromNode,
- joint_alias_map,
- LLSkinningUtil::getMaxJointCount(),
- gSavedSettings.getU32("ImporterModelLimit"),
- // allow LOD suffix configuration
- // gSavedSettings.getBOOL("ImporterPreprocessDAE"));
- gSavedSettings.getBOOL("ImporterPreprocessDAE"),
- lod_suffix);
+ mModelLoader = new LLDAELoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"),
+ // allow LOD suffix configuration
+ //gSavedSettings.getBOOL("ImporterPreprocessDAE"));
+ gSavedSettings.getBOOL("ImporterPreprocessDAE"),
+ lod_suffix);
+ }
+ else
+ {
+ mModelLoader = new LLGLTFLoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"));
+ }
if (force_disable_slm)
{
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 2c2e5b7777..225df53cc3 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -145,6 +145,15 @@ BOOL LLPanelVolume::postBuild()
getChild("Light Ambiance")->setValidateBeforeCommit( precommitValidate);
}
+ // REFLECTION PROBE Parameters
+ {
+ childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this);
+ childSetCommitCallback("Probe Dynamic", onCommitProbe, this);
+ childSetCommitCallback("Probe Volume Type", onCommitProbe, this);
+ childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
+ childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
+ }
+
// PHYSICS Parameters
{
// PhysicsShapeType combobox
@@ -360,6 +369,43 @@ void LLPanelVolume::getState( )
getChildView("Light Ambiance")->setEnabled(false);
}
+ // Reflection Probe
+ BOOL is_probe = volobjp && volobjp->isReflectionProbe();
+ getChild("Reflection Probe")->setValue(is_probe);
+ getChildView("Reflection Probe")->setEnabled(editable && single_volume && volobjp);
+
+ bool probe_enabled = is_probe && editable && single_volume;
+
+ getChildView("Probe Dynamic")->setEnabled(probe_enabled);
+ getChildView("Probe Volume Type")->setEnabled(probe_enabled);
+ getChildView("Probe Ambiance")->setEnabled(probe_enabled);
+ getChildView("Probe Near Clip")->setEnabled(probe_enabled);
+
+ if (!probe_enabled)
+ {
+ getChild("Probe Volume Type", true)->clear();
+ getChild("Probe Ambiance", true)->clear();
+ getChild("Probe Near Clip", true)->clear();
+ getChild("Probe Dynamic", true)->clear();
+ }
+ else
+ {
+ std::string volume_type;
+ if (volobjp->getReflectionProbeIsBox())
+ {
+ volume_type = "Box";
+ }
+ else
+ {
+ volume_type = "Sphere";
+ }
+
+ getChild("Probe Volume Type", true)->setValue(volume_type);
+ getChild("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
+ getChild("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
+ getChild("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic());
+ }
+
// Animated Mesh
BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject();
getChild("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh);
@@ -647,6 +693,11 @@ void LLPanelVolume::clearCtrls()
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
+ getChildView("Reflection Probe")->setEnabled(false);;
+ getChildView("Probe Volume Type")->setEnabled(false);
+ getChildView("Probe Dynamic")->setEnabled(false);
+ getChildView("Probe Ambiance")->setEnabled(false);
+ getChildView("Probe Near Clip")->setEnabled(false);
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
getChildView("FlexNumSections")->setEnabled(false);
@@ -687,6 +738,20 @@ void LLPanelVolume::sendIsLight()
LL_INFOS() << "update light sent" << LL_ENDL;
}
+void LLPanelVolume::sendIsReflectionProbe()
+{
+ LLViewerObject* objectp = mObject;
+ if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume* volobjp = (LLVOVolume*)objectp;
+
+ BOOL value = getChild("Reflection Probe")->getValue();
+ volobjp->setIsReflectionProbe(value);
+ LL_INFOS() << "update reflection probe sent" << LL_ENDL;
+}
+
void LLPanelVolume::sendIsFlexible()
{
LLViewerObject* objectp = mObject;
@@ -930,6 +995,27 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
}
+//static
+void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelVolume* self = (LLPanelVolume*)userdata;
+ LLViewerObject* objectp = self->mObject;
+ if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume* volobjp = (LLVOVolume*)objectp;
+
+
+ volobjp->setReflectionProbeAmbiance((F32)self->getChild("Probe Ambiance")->getValue().asReal());
+ volobjp->setReflectionProbeNearClip((F32)self->getChild("Probe Near Clip")->getValue().asReal());
+ volobjp->setReflectionProbeIsDynamic(self->getChild("Probe Dynamic")->getValue().asBoolean());
+
+ std::string shape_type = self->getChild("Probe Volume Type")->getValue().asString();
+
+ volobjp->setReflectionProbeIsBox(shape_type == "Box");
+}
+
// static
void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
{
@@ -952,6 +1038,15 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item
}
//----------------------------------------------------------------------------
+// static
+void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelVolume* self = (LLPanelVolume*)userdata;
+ self->sendIsReflectionProbe();
+}
+
+//----------------------------------------------------------------------------
+
// static
void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
{
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index 6e49ccb742..16d9ac292d 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -56,12 +56,15 @@ public:
void refresh();
void sendIsLight();
+ void sendIsReflectionProbe();
void sendIsFlexible();
static bool precommitValidate(const LLSD& data);
static void onCommitIsLight( LLUICtrl* ctrl, void* userdata);
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
+ static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata);
+ static void onCommitProbe(LLUICtrl* ctrl, void* userdata);
void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
void onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata);
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
index 54a627efd4..500485fc70 100644
--- a/indra/newview/llreflectionmap.cpp
+++ b/indra/newview/llreflectionmap.cpp
@@ -35,7 +35,6 @@ extern F32SecondsImplicit gFrameTimeSeconds;
LLReflectionMap::LLReflectionMap()
{
- mLastUpdateTime = gFrameTimeSeconds;
}
void LLReflectionMap::update(U32 resolution, U32 face)
@@ -52,29 +51,7 @@ void LLReflectionMap::update(U32 resolution, U32 face)
{
resolution /= 2;
}
- gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face);
-}
-
-bool LLReflectionMap::shouldUpdate()
-{
- const F32 TIMEOUT_INTERVAL = 30.f; // update no less than this often
- const F32 RENDER_TIMEOUT = 1.f; // don't update if hasn't been used for rendering for this long
-
- if (mLastBindTime > gFrameTimeSeconds - RENDER_TIMEOUT)
- {
- if (mLastUpdateTime < gFrameTimeSeconds - TIMEOUT_INTERVAL)
- {
- return true;
- }
- }
-
- return false;
-}
-
-void LLReflectionMap::dirty()
-{
- mDirty = true;
- mLastUpdateTime = gFrameTimeSeconds;
+ gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic());
}
void LLReflectionMap::autoAdjustOrigin()
@@ -140,7 +117,7 @@ void LLReflectionMap::autoAdjustOrigin()
{
int face = -1;
LLVector4a intersection;
- LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, &face, &intersection);
+ LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, true, &face, &intersection);
if (drawable != nullptr)
{
hit = true;
@@ -215,6 +192,47 @@ bool LLReflectionMap::intersects(LLReflectionMap* other)
return dist < r2;
}
+extern LLControlGroup gSavedSettings;
+
+F32 LLReflectionMap::getAmbiance()
+{
+ static LLCachedControl minimum_ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f);
+
+ F32 ret = 0.f;
+ if (mViewerObject && mViewerObject->getVolume())
+ {
+ ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance();
+ }
+
+ return llmax(ret, minimum_ambiance());
+}
+
+F32 LLReflectionMap::getNearClip()
+{
+ const F32 MINIMUM_NEAR_CLIP = 0.1f;
+
+ F32 ret = 0.f;
+
+ if (mViewerObject && mViewerObject->getVolume())
+ {
+ ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeNearClip();
+ }
+
+ return llmax(ret, MINIMUM_NEAR_CLIP);
+}
+
+bool LLReflectionMap::getIsDynamic()
+{
+ if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY &&
+ mViewerObject &&
+ mViewerObject->getVolume())
+ {
+ return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic();
+ }
+
+ return false;
+}
+
bool LLReflectionMap::getBox(LLMatrix4& box)
{
if (mViewerObject)
@@ -224,25 +242,8 @@ bool LLReflectionMap::getBox(LLMatrix4& box)
{
LLVOVolume* vobjp = (LLVOVolume*)mViewerObject;
- U8 profile = volume->getProfileType();
- U8 path = volume->getPathType();
-
- if (profile == LL_PCODE_PROFILE_SQUARE &&
- path == LL_PCODE_PATH_LINE)
+ if (vobjp->getReflectionProbeIsBox())
{
- // nope
- /*box = vobjp->getRelativeXform();
- box *= vobjp->mDrawable->getRenderMatrix();
- LLMatrix4 modelview(gGLModelView);
- box *= modelview;
- box.invert();*/
-
- // nope
- /*box = LLMatrix4(gGLModelView);
- box *= vobjp->mDrawable->getRenderMatrix();
- box *= vobjp->getRelativeXform();
- box.invert();*/
-
glh::matrix4f mv(gGLModelView);
glh::matrix4f scale;
LLVector3 s = vobjp->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index 4f0f124118..cf0bc2ff27 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -43,21 +43,24 @@ public:
// resolution - size of cube map to generate
void update(U32 resolution, U32 face);
- // return true if this probe should update *now*
- bool shouldUpdate();
-
- // Mark this reflection map as needing an update (resets last update time, so spamming this call will cause a cube map to never update)
- void dirty();
-
// for volume partition probes, try to place this probe in the best spot
void autoAdjustOrigin();
// return true if given Reflection Map's influence volume intersect's with this one's
bool intersects(LLReflectionMap* other);
+ // Get the ambiance value to use for this probe
+ F32 getAmbiance();
+
+ // Get the near clip plane distance to use for this probe
+ F32 getNearClip();
+
+ // Return true if this probe should include avatars in its reflection map
+ bool getIsDynamic();
+
// get the encoded bounding box of this probe's influence volume
- // will only return a box if this probe has a volume with a square
- // profile and a linear path
+ // will only return a box if this probe is associated with a VOVolume
+ // with its reflection probe influence volume to to VOLUME_TYPE_BOX
// return false if no bounding box (treat as sphere influence volume)
bool getBox(LLMatrix4& box);
@@ -95,7 +98,5 @@ public:
// what priority should this probe have (higher is higher priority)
U32 mPriority = 1;
-
- bool mDirty = true;
};
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 3037871dbf..3bae000ff8 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -96,11 +96,13 @@ void LLReflectionMapManager::update()
mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_RECT_TEXTURE);
// hack to allocate render targets using gPipeline code
+ gCubeSnapshot = TRUE;
auto* old_rt = gPipeline.mRT;
gPipeline.mRT = &gProbeRT;
gPipeline.allocateScreenBuffer(targetRes, targetRes);
gPipeline.allocateShadowBuffer(targetRes, targetRes);
gPipeline.mRT = old_rt;
+ gCubeSnapshot = FALSE;
}
if (mMipChain.empty())
@@ -127,18 +129,12 @@ void LLReflectionMapManager::update()
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
// process kill list
- for (int i = 0; i < mProbes.size(); )
+ for (auto& probe : mKillList)
{
- auto& iter = std::find(mKillList.begin(), mKillList.end(), mProbes[i]);
- if (iter != mKillList.end())
+ auto& iter = std::find(mProbes.begin(), mProbes.end(), probe);
+ if (iter != mProbes.end())
{
- deleteProbe(i);
- mProbes.erase(mProbes.begin() + i);
- mKillList.erase(iter);
- }
- else
- {
- ++i;
+ deleteProbe(iter - mProbes.begin());
}
}
@@ -160,6 +156,10 @@ void LLReflectionMapManager::update()
bool did_update = false;
+ bool realtime = gSavedSettings.getS32("RenderReflectionProbeDetail") >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
+
+ LLReflectionMap* closestDynamic = nullptr;
+
LLReflectionMap* oldestProbe = nullptr;
if (mUpdatingProbe != nullptr)
@@ -189,11 +189,30 @@ void LLReflectionMapManager::update()
oldestProbe = probe;
}
+ if (realtime &&
+ closestDynamic == nullptr &&
+ probe->mCubeArray.notNull() &&
+ probe->getIsDynamic())
+ {
+ closestDynamic = probe;
+ }
+
d.setSub(camera_pos, probe->mOrigin);
probe->mDistance = d.getLength3().getF32()-probe->mRadius;
}
-#if 1
+ if (realtime && closestDynamic != nullptr)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime");
+ // update the closest dynamic probe realtime
+ closestDynamic->autoAdjustOrigin();
+ for (U32 i = 0; i < 6; ++i)
+ {
+ updateProbeFace(closestDynamic, i);
+ }
+ }
+
+ // switch to updating the next oldest probe
if (!did_update && oldestProbe != nullptr)
{
LLReflectionMap* probe = oldestProbe;
@@ -207,9 +226,7 @@ void LLReflectionMapManager::update()
mUpdatingProbe = probe;
doProbeUpdate();
- probe->mDirty = false;
}
-#endif
// update distance to camera for all probes
std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
@@ -220,7 +237,6 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
LLReflectionMap* probe = new LLReflectionMap();
probe->mGroup = group;
probe->mOrigin = group->getOctreeNode()->getCenter();
- probe->mDirty = true;
if (gCubeSnapshot)
{ //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
@@ -275,7 +291,7 @@ LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* gr
{
OctreeNode* node = group->getOctreeNode();
F32 size = node->getSize().getF32ptr()[0];
- if (size >= 7.f && size <= 17.f)
+ if (size >= 15.f && size <= 17.f)
{
return addProbe(group);
}
@@ -301,7 +317,6 @@ LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vo
LLReflectionMap* probe = new LLReflectionMap();
probe->mViewerObject = vobj;
probe->mOrigin.load3(vobj->getPositionAgent().mV);
- probe->mDirty = true;
if (gCubeSnapshot)
{ //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
@@ -374,10 +389,23 @@ void LLReflectionMapManager::doProbeUpdate()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(mUpdatingProbe != nullptr);
+ updateProbeFace(mUpdatingProbe, mUpdatingFace);
+
+ if (++mUpdatingFace == 6)
+ {
+ updateNeighbors(mUpdatingProbe);
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+}
+
+void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
+{
mRenderTarget.bindTarget();
+ // hacky hot-swap of camera specific render targets
auto* old_rt = gPipeline.mRT;
gPipeline.mRT = &gProbeRT;
- mUpdatingProbe->update(mRenderTarget.getWidth(), mUpdatingFace);
+ probe->update(mRenderTarget.getWidth(), face);
gPipeline.mRT = old_rt;
mRenderTarget.flush();
@@ -396,9 +424,9 @@ void LLReflectionMapManager::doProbeUpdate()
gGL.loadIdentity();
gGL.flush();
- U32 res = LL_REFLECTION_PROBE_RESOLUTION*2;
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2;
- S32 mips = log2((F32) LL_REFLECTION_PROBE_RESOLUTION)+0.5f;
+ S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f;
for (int i = 0; i < mMipChain.size(); ++i)
{
@@ -416,10 +444,10 @@ void LLReflectionMapManager::doProbeUpdate()
// Remove QUADS rendering mode
//gGL.begin(gGL.QUADS);
- //
+
//gGL.texCoord2f(0, 0);
//gGL.vertex2f(-1, -1);
- //
+
//gGL.texCoord2f(res, 0);
//gGL.vertex2f(1, -1);
@@ -455,7 +483,7 @@ void LLReflectionMapManager::doProbeUpdate()
if (mip >= 0)
{
mTexture->bind(0);
- glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, mUpdatingProbe->mCubeIndex * 6 + mUpdatingFace, 0, 0, res, res);
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
mTexture->unbind();
}
mMipChain[i].flush();
@@ -467,13 +495,6 @@ void LLReflectionMapManager::doProbeUpdate()
gReflectionMipProgram.unbind();
}
-
- if (++mUpdatingFace == 6)
- {
- updateNeighbors(mUpdatingProbe);
- mUpdatingProbe = nullptr;
- mUpdatingFace = 0;
- }
}
void LLReflectionMapManager::rebuild()
@@ -532,15 +553,15 @@ void LLReflectionMapManager::updateUniforms()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
// structure for packing uniform buffer object
- // see class2/deferred/softenLightF.glsl
+ // see class3/deferred/reflectionProbeF.glsl
struct ReflectionProbeData
{
LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed
LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space
+ LLVector4 refParams[LL_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance)
GLint refIndex[LL_REFLECTION_PROBE_COUNT][4];
GLint refNeighbor[4096];
GLint refmapCount;
- GLfloat reflectionAmbiance;
};
mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT);
@@ -548,9 +569,6 @@ void LLReflectionMapManager::updateUniforms()
ReflectionProbeData rpd;
- static LLCachedControl ambiance(gSavedSettings, "RenderReflectionProbeAmbiance", 0.f);
- rpd.reflectionAmbiance = ambiance;
-
// load modelview matrix into matrix 4a
LLMatrix4a modelview;
modelview.loadu(gGLModelView);
@@ -591,6 +609,8 @@ void LLReflectionMapManager::updateUniforms()
rpd.refIndex[count][3] = -rpd.refIndex[count][3];
}
+ rpd.refParams[count].set(refmap->getAmbiance(), 0.f, 0.f, 0.f);
+
S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
{
//LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors");
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index bf963f3486..3b5cdc5520 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -46,6 +46,13 @@ class alignas(16) LLReflectionMapManager
{
LL_ALIGN_NEW
public:
+ enum class DetailLevel
+ {
+ STATIC_ONLY = 0,
+ STATIC_AND_DYNAMIC,
+ REALTIME = 2
+ };
+
// allocate an environment map of the given resolution
LLReflectionMapManager();
@@ -115,6 +122,9 @@ private:
// perform an update on the currently updating Probe
void doProbeUpdate();
+
+ // update the specified face of the specified probe
+ void updateProbeFace(LLReflectionMap* probe, U32 face);
// list of active reflection maps
std::vector > mProbes;
@@ -133,6 +143,5 @@ private:
LLReflectionMap* mUpdatingProbe = nullptr;
U32 mUpdatingFace = 0;
-
};
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 72f410c6f4..63030f0486 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1136,8 +1136,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
return;
}
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
- || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())))
+ if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
+ || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())))
{
// only select my own objects
return;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index f2206d70e8..d19d6a3785 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -746,17 +746,8 @@ BOOL LLSpatialGroup::changeLOD()
return FALSE;
}
-void LLSpatialGroup::dirtyReflectionProbe()
-{
- if (mReflectionProbe != nullptr)
- {
- mReflectionProbe->dirty();
- }
-}
-
void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry)
{
- dirtyReflectionProbe();
addObject((LLDrawable*)entry->getDrawable());
unbound();
setState(OBJECT_DIRTY);
@@ -764,7 +755,6 @@ void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry*
void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry)
{
- dirtyReflectionProbe();
removeObject((LLDrawable*)entry->getDrawable(), TRUE);
LLViewerOctreeGroup::handleRemoval(node, entry);
}
@@ -801,8 +791,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL
- dirtyReflectionProbe();
-
if (child->getListenerCount() == 0)
{
new LLSpatialGroup(child, getSpatialPartition());
@@ -817,11 +805,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
assert_states_valid(this);
}
-void LLSpatialGroup::handleChildRemoval(const oct_node* parent, const oct_node* child)
-{
- dirtyReflectionProbe();
-}
-
void LLSpatialGroup::destroyGL(bool keep_occlusion)
{
// Reset VB during TP
@@ -3966,8 +3949,9 @@ public:
LLDrawable* mHit;
BOOL mPickTransparent;
BOOL mPickRigged;
+ BOOL mPickUnselectable;
- LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged,
+ LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable,
S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
: mStart(start),
mEnd(end),
@@ -3978,7 +3962,8 @@ public:
mTangent(tangent),
mHit(NULL),
mPickTransparent(pick_transparent),
- mPickRigged(pick_rigged)
+ mPickRigged(pick_rigged),
+ mPickUnselectable(pick_unselectable)
{
}
@@ -4118,7 +4103,7 @@ public:
LLVOAvatar* avatar = (LLVOAvatar*) vobj;
if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools))))
{
- LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent);
+ LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent);
if (hit)
{
mEnd = intersection;
@@ -4134,7 +4119,7 @@ public:
}
}
- if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent))
+ if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent))
{
mEnd = intersection; // shorten ray so we only find CLOSER hits
if (mIntersection)
@@ -4154,6 +4139,7 @@ public:
LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -4162,7 +4148,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co
)
{
- LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent);
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent);
LLDrawable* drawable = intersect.check(mOctree);
return drawable;
@@ -4171,6 +4157,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co
LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -4179,7 +4166,7 @@ LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const
)
{
- LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent);
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent);
LLDrawable* drawable = intersect.check(getOctreeNode());
return drawable;
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index e5af168e48..9014d44c1d 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -328,6 +328,7 @@ public:
LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -343,7 +344,6 @@ public:
virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face);
virtual void handleDestruction(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
- virtual void handleChildRemoval(const oct_node* parent, const oct_node* child);
public:
LL_ALIGN_16(LLVector4a mViewAngle);
@@ -351,8 +351,6 @@ public:
F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
- void dirtyReflectionProbe();
-
protected:
virtual ~LLSpatialGroup();
@@ -411,6 +409,7 @@ public:
LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index db6de505a6..59c91d59aa 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -3423,6 +3423,7 @@ void LLTextureFetch::sendRequestListToSimulators()
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
}
S32 packet = req->mLastPacket + 1;
+ LL_INFOS() << req->mID << ": " << req->mImagePriority << LL_ENDL;
gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard);
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index 060d9f5696..9619867ca1 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -70,7 +70,8 @@ BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask)
{
// do immediate pick query
BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick");
- mPick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged);
+ BOOL pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects");
+ mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged);
// Pass mousedown to agent
LLTool::handleMouseDown(x, y, mask);
@@ -132,7 +133,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
// FIRE-17696: Option to select only locked objects
BOOL select_locked = gSavedSettings.getBOOL("FSSelectLockedOnly");
- // *NOTE: These settings must be cleaned up at bottom of function.
+ // *NOTE: These settings must be cleaned up at bottom of function.
if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", FALSE);
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 549778a841..b5841772ed 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -47,15 +47,14 @@ public:
typedef enum
{
CAMERA_WORLD = 0,
- CAMERA_SHADOW0,
- CAMERA_SHADOW1,
- CAMERA_SHADOW2,
- CAMERA_SHADOW3,
- CAMERA_SHADOW4,
- CAMERA_SHADOW5,
+ CAMERA_SUN_SHADOW0,
+ CAMERA_SUN_SHADOW1,
+ CAMERA_SUN_SHADOW2,
+ CAMERA_SUN_SHADOW3,
+ CAMERA_SPOT_SHADOW0,
+ CAMERA_SPOT_SHADOW1,
CAMERA_WATER0,
CAMERA_WATER1,
- CAMERA_GI_SOURCE,
NUM_CAMERAS
} eCameraID;
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 8e2ebcf80f..e3a66fb1b4 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1208,7 +1208,6 @@ void display_cube_face()
gPipeline.mBackfaceCull = TRUE;
- LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
gViewerWindow->setup3DViewport();
if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 7a2d65e859..178d0e7189 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -330,16 +330,11 @@ void handle_reset_view();
void handle_duplicate_in_place(void*);
-
void handle_object_owner_self(void*);
void handle_object_owner_permissive(void*);
void handle_object_lock(void*);
void handle_object_asset_ids(void*);
void force_take_copy(void*);
-#ifdef _CORY_TESTING
-void force_export_copy(void*);
-void force_import_geometry(void*);
-#endif
void handle_force_parcel_owner_to_me(void*);
void handle_force_parcel_to_content(void*);
@@ -10279,6 +10274,18 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t
}
};
+class LLToolsSelectInvisibleObjects : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL cur_val = gSavedSettings.getBOOL("SelectInvisibleObjects");
+
+ gSavedSettings.setBOOL("SelectInvisibleObjects", !cur_val);
+
+ return true;
+ }
+};
+
class LLToolsSelectBySurrounding : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -11918,6 +11925,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
+ view_listener_t::addMenu(new LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects");
view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 23c150ae29..14e393ac63 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -285,9 +285,6 @@ void LLMediaFilePicker::notify(const std::vector& filenames)
static std::string SOUND_EXTENSIONS = "wav";
static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png";
static std::string ANIM_EXTENSIONS = "bvh anim";
-#ifdef _CORY_TESTING
-static std::string GEOMETRY_EXTENSIONS = "slg";
-#endif
static std::string XML_EXTENSIONS = "xml";
static std::string SLOBJECT_EXTENSIONS = "slobject";
#endif
@@ -309,10 +306,6 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
return SLOBJECT_EXTENSIONS;
case LLFilePicker::FFLOAD_MODEL:
return MODEL_EXTENSIONS;
-#ifdef _CORY_TESTING
- case LLFilePicker::FFLOAD_GEOMETRY:
- return GEOMETRY_EXTENSIONS;
-#endif
case LLFilePicker::FFLOAD_XML:
return XML_EXTENSIONS;
case LLFilePicker::FFLOAD_ALL:
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 5bd0f28302..1088da323f 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -277,7 +277,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mTEImages(NULL),
mTENormalMaps(NULL),
mTESpecularMaps(NULL),
- mGLName(0),
mbCanSelect(TRUE),
mFlags(0),
mPhysicsShapeType(0),
@@ -4732,6 +4731,7 @@ BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVecto
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -5678,18 +5678,6 @@ S32 LLViewerObject::countInventoryContents(LLAssetType::EType type)
return count;
}
-
-void LLViewerObject::setCanSelect(BOOL canSelect)
-{
- mbCanSelect = canSelect;
- for (child_list_t::iterator iter = mChildList.begin();
- iter != mChildList.end(); iter++)
- {
- LLViewerObject* child = *iter;
- child->mbCanSelect = canSelect;
- }
-}
-
void LLViewerObject::setDebugText(const std::string &utf8text)
{
if (utf8text.empty() && !mText)
@@ -6205,6 +6193,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
{
new_block = new LLRenderMaterialParams();
break;
+ }
+ case LLNetworkData::PARAMS_REFLECTION_PROBE:
+ {
+ new_block = new LLReflectionProbeParams();
+ break;
}
default:
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 6f70982425..489377a67e 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -242,6 +242,7 @@ public:
virtual BOOL isMesh() const { return FALSE; }
virtual BOOL isRiggedMesh() const { return FALSE; }
virtual BOOL hasLightTexture() const { return FALSE; }
+ virtual BOOL isReflectionProbe() const { return FALSE; }
// This method returns true if the object is over land owned by
// the agent, one of its groups, or it encroaches and
@@ -286,6 +287,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -431,8 +433,6 @@ public:
void sendMaterialUpdate() const;
- void setCanSelect(BOOL canSelect);
-
void setDebugText(const std::string &utf8text);
void initHudText();
void restoreHudText();
@@ -693,9 +693,9 @@ public:
LLPointer *mTENormalMaps;
LLPointer *mTESpecularMaps;
- // Selection, picking and rendering variables
- U32 mGLName; // GL "name" used by selection code
- BOOL mbCanSelect; // true if user can select this object by clicking
+ // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true)
+ // can likely be factored out
+ BOOL mbCanSelect;
private:
// Grabbed from UPDATE_FLAGS
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 7bbc41783a..3ecf44d967 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1523,9 +1523,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
}
// Don't clean up mObject references, these will be cleaned up more efficiently later!
- // Also, not cleaned up
- removeDrawable(objectp->mDrawable);
-
+
// FIRE-30694 DeadObject Spam
// if(new_dead_object)
// {
@@ -1533,29 +1531,6 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
// }
}
-void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
-
- if (!drawablep)
- {
- return;
- }
-
- for (S32 i = 0; i < drawablep->getNumFaces(); i++)
- {
- LLFace* facep = drawablep->getFace(i) ;
- if(facep)
- {
- LLViewerObject* objectp = facep->getViewerObject();
- if(objectp)
- {
- mSelectPickList.erase(objectp);
- }
- }
- }
-}
-
BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
{
// Don't ever kill gAgentAvatarp, just force it to the agent's region
@@ -2152,149 +2127,6 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er)
{
}
-void LLViewerObjectList::generatePickList(LLCamera &camera)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
-
- LLViewerObject *objectp;
- S32 i;
- // Reset all of the GL names to zero.
- for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
- {
- (*iter)->mGLName = 0;
- }
-
- mSelectPickList.clear();
-
- std::vector pick_drawables;
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->cull(camera, &pick_drawables, TRUE);
- }
- }
- }
-
- for (std::vector::iterator iter = pick_drawables.begin();
- iter != pick_drawables.end(); iter++)
- {
- LLDrawable* drawablep = *iter;
- if( !drawablep )
- continue;
-
- LLViewerObject* last_objectp = NULL;
- for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
- {
- LLFace * facep = drawablep->getFace(face_num);
- if (!facep) continue;
-
- LLViewerObject* objectp = facep->getViewerObject();
-
- if (objectp && objectp != last_objectp)
- {
- mSelectPickList.insert(objectp);
- last_objectp = objectp;
- }
- }
- }
-
- LLHUDNameTag::addPickable(mSelectPickList);
-
- for (std::vector::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- objectp = (LLVOAvatar*) *iter;
- if (!objectp->isDead())
- {
- if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
- {
- mSelectPickList.insert(objectp);
- }
- }
- }
-
- // add all hud objects to pick list
- if (isAgentAvatarValid())
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- // Possible crash fix
- //if (attachment->getIsHUDAttachment())
- if (attachment && attachment->getIsHUDAttachment())
- //
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- if (LLViewerObject* attached_object = attachment_iter->get())
- {
- mSelectPickList.insert(attached_object);
- LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* childp = *iter;
- if (childp)
- {
- mSelectPickList.insert(childp);
- }
- }
- }
- }
- }
- }
- }
-
- S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
-
- if (num_pickables != 0)
- {
- S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
-
- std::set::iterator pick_it;
- i = 0;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
- {
- LLViewerObject* objp = (*pick_it);
- if (!objp || objp->isDead() || !objp->mbCanSelect)
- {
- mSelectPickList.erase(pick_it++);
- continue;
- }
-
- objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
- i++;
- ++pick_it;
- }
-
- LLHUDIcon::generatePickIDs(i * step, step);
- }
-}
-
-LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
-{
- std::set::iterator pick_it;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it)
- {
- if ((*pick_it)->mGLName == object_id)
- {
- return (*pick_it);
- }
- }
- return NULL;
-}
-
void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
const std::string &string,
const LLColor4 &color,
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 7429497363..82a188a054 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -79,7 +79,6 @@ public:
void killObjects(LLViewerRegion *regionp); // Kill all objects owned by a particular region.
void killAllObjects();
- void removeDrawable(LLDrawable* drawablep);
void cleanDeadObjects(const BOOL use_timer = TRUE); // Clean up the dead object list.
@@ -134,11 +133,6 @@ public:
void updateAvatarVisibility();
- // Selection related stuff
- void generatePickList(LLCamera &camera);
-
- LLViewerObject *getSelectedObject(const U32 object_id);
-
inline S32 getNumObjects() { return (S32) mObjects.size(); }
inline S32 getNumActiveObjects() { return (S32) mActiveObjects.size(); }
@@ -247,8 +241,6 @@ protected:
static std::map sIndexAndLocalIDToUUID;
- std::set mSelectPickList;
-
friend class LLViewerObject;
private:
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 26e50ab74c..cbb064fd61 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -3854,7 +3854,7 @@ void LLViewerWindow::updateUI()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
{
gDebugRaycastFaceHit = -1;
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE,
+ gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE,
&gDebugRaycastFaceHit,
&gDebugRaycastIntersection,
&gDebugRaycastTexCoord,
@@ -5299,13 +5299,16 @@ void LLViewerWindow::pickAsync( S32 x,
BOOL pick_rigged,
BOOL pick_unselectable)
{
- BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = TRUE;
- }
+ // "Show Debug Alpha" means no object actually transparent
+ BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+ if (LLDrawPoolAlpha::sShowDebugAlpha)
+ {
+ pick_transparent = TRUE;
+ }
+ else if (in_build_mode && !gSavedSettings.getBOOL("SelectInvisibleObjects"))
+ {
+ pick_transparent = FALSE;
+ }
LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, TRUE, pick_unselectable, callback);
schedulePick(pick_info);
@@ -5363,10 +5366,10 @@ void LLViewerWindow::returnEmptyPicks()
}
// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle)
+LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle, BOOL pick_unselectable)
{
BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+ if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha)
{
// build mode allows interaction with all transparent objects
// "Show Debug Alpha" means no object actually transparent
@@ -5412,6 +5415,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
S32 this_face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a *intersection,
LLVector2 *uv,
@@ -5482,7 +5486,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
{
if (this_object->isHUDAttachment()) // is a HUD object?
{
- if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged,
+ if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent))
{
found = this_object;
@@ -5490,7 +5494,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
}
else // is a world object
{
- if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged,
+ if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent))
{
found = this_object;
@@ -5511,7 +5515,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
// [/RLVa:KB]
if (!found) // if not found in HUD, look in world:
{
- found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged,
+ found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent);
if (found && !pick_transparent)
{
@@ -6168,8 +6172,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
- gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
// Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen.
// In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y
for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
@@ -6472,7 +6474,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
void display_cube_face();
-BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face)
+BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render)
{
// NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
@@ -6501,19 +6503,37 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
camera->setView(F_PI_BY_TWO);
camera->yaw(0.0);
camera->setOrigin(origin);
+ camera->setNear(near_clip);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ U32 dynamic_render_types[] = {
+ LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
+ LLPipeline::RENDER_TYPE_PARTICLES
+ };
+ constexpr U32 dynamic_render_type_count = sizeof(dynamic_render_types) / sizeof(U32);
+ bool prev_dynamic_render_type[dynamic_render_type_count];
+
+
+ if (!dynamic_render)
+ {
+ for (int i = 0; i < dynamic_render_type_count; ++i)
+ {
+ prev_dynamic_render_type[i] = gPipeline.hasRenderType(dynamic_render_types[i]);
+ if (prev_dynamic_render_type[i])
+ {
+ gPipeline.toggleRenderType(dynamic_render_types[i]);
+ }
+ }
+ }
+
BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
if (prev_draw_ui != false)
{
LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
}
- BOOL prev_draw_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
- if (prev_draw_particles)
- {
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
- }
+
LLPipeline::sShowHUDAttachments = FALSE;
LLRect window_rect = getWorldViewRectRaw();
@@ -6569,9 +6589,15 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
}
}
- if (prev_draw_particles)
+ if (!dynamic_render)
{
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ for (int i = 0; i < dynamic_render_type_count; ++i)
+ {
+ if (prev_dynamic_render_type[i])
+ {
+ gPipeline.toggleRenderType(dynamic_render_types[i]);
+ }
+ }
}
LLPipeline::sShowHUDAttachments = TRUE;
@@ -7378,7 +7404,7 @@ void LLPickInfo::fetchResults()
icon_dist = delta.getLength3().getF32();
}
LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
- NULL, -1, mPickTransparent, mPickRigged, &face_hit,
+ NULL, -1, mPickTransparent, mPickRigged, mPickUnselectable, &face_hit,
&intersection, &uv, &normal, &tangent, &start, &end);
mPickPt = mMousePt;
@@ -7539,7 +7565,7 @@ void LLPickInfo::getSurfaceInfo()
if (objectp)
{
if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f,
- objectp, -1, mPickTransparent, mPickRigged,
+ objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable,
&mObjectFace,
&intersection,
&mSTCoords,
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index de18f8709c..fbadd0ea93 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -369,7 +369,9 @@ public:
// origin - vantage point to take the snapshot from
// cubearray - cubemap array for storing the results
// index - cube index in the array to use (cube index, not face-layer)
- BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face);
+ // face - which cube face to update
+ // near_clip - near clip setting to use
+ BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars);
// special implementation of simpleSnapshot for reflection maps
@@ -404,7 +406,7 @@ public:
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
BOOL pick_unselectable = FALSE);
- LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE);
+ LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE, BOOL pick_unselectable = TRUE);
LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
LLVector4a* intersection);
@@ -413,6 +415,7 @@ public:
S32 this_face = -1,
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL,
LLVector4a *intersection = NULL,
LLVector2 *uv = NULL,
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 1bb601594d..c0eebef131 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1904,6 +1904,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -2017,6 +2018,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -2054,7 +2056,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
{
LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 374f3d4fd3..16a8ecde70 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -165,6 +165,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -175,6 +176,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index ce7f144d35..25aa844998 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -803,7 +803,7 @@ void LLVOGrass::updateDrawable(BOOL force_damped)
}
// virtual
-BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOGrass::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)
{
BOOL ret = FALSE;
diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h
index a0b956796c..fa44dcae04 100644
--- a/indra/newview/llvograss.h
+++ b/indra/newview/llvograss.h
@@ -79,6 +79,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 0dfd2b77c9..3e61bdf5f7 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -499,6 +499,7 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 4e4d6e609d..a45d381dfa 100644
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -74,6 +74,7 @@ public:
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index 104787f988..c915f94e59 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -880,7 +880,7 @@ void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride,
}
}
-BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOSurfacePatch::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)
{
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index 884dbb3be3..aed67162d1 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -85,6 +85,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index fc0b26e7ac..45dac8cec1 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -1181,7 +1181,7 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
mDrawable->setPositionGroup(pos);
}
-BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOTree::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)
{
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index 10b3de1257..8b1ae5c8de 100644
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -113,6 +113,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 8afbb107ea..474539b39f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1131,7 +1131,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
// Add it to the pipeline mLightSet
gPipeline.setLight(mDrawable, TRUE);
}
-
+
+ if (isReflectionProbe())
+ {
+ updateReflectionProbePtr();
+ }
+
updateRadius();
bool force_update = true; // avoid non-alpha mDistance update being optimized away
mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
@@ -3688,6 +3693,143 @@ F32 LLVOVolume::getLightCutoff() const
}
}
+void LLVOVolume::setIsReflectionProbe(BOOL is_probe)
+{
+ BOOL was_probe = isReflectionProbe();
+ if (is_probe != was_probe)
+ {
+ if (is_probe)
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, TRUE, true);
+ }
+ else
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, FALSE, true);
+ }
+ }
+
+ updateReflectionProbePtr();
+}
+
+void LLVOVolume::setReflectionProbeAmbiance(F32 ambiance)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getAmbiance() != ambiance)
+ {
+ param_block->setAmbiance(ambiance);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+void LLVOVolume::setReflectionProbeNearClip(F32 near_clip)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getClipDistance() != near_clip)
+ {
+ param_block->setClipDistance(near_clip);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+void LLVOVolume::setReflectionProbeIsBox(bool is_box)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getIsBox() != is_box)
+ {
+ param_block->setIsBox(is_box);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+void LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getIsDynamic() != is_dynamic)
+ {
+ param_block->setIsDynamic(is_dynamic);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+
+BOOL LLVOVolume::isReflectionProbe() const
+{
+ // HACK - make this object a Reflection Probe if a certain UUID is detected
+ static LLCachedControl reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", "");
+ LLUUID probe_id(reflection_probe_id);
+
+ for (U8 i = 0; i < getNumTEs(); ++i)
+ {
+ if (getTE(i)->getID() == probe_id)
+ {
+ return true;
+ }
+ }
+ // END HACK
+
+ return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
+}
+
+F32 LLVOVolume::getReflectionProbeAmbiance() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getAmbiance();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+F32 LLVOVolume::getReflectionProbeNearClip() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getClipDistance();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+bool LLVOVolume::getReflectionProbeIsBox() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getIsBox();
+ }
+
+ return false;
+}
+
+bool LLVOVolume::getReflectionProbeIsDynamic() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getIsDynamic();
+ }
+
+ return false;
+}
+
U32 LLVOVolume::getVolumeInterfaceID() const
{
if (mVolumeImpl)
@@ -4613,6 +4755,23 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
gPipeline.setLight(mDrawable, is_light);
}
}
+
+ updateReflectionProbePtr();
+}
+
+void LLVOVolume::updateReflectionProbePtr()
+{
+ if (isReflectionProbe())
+ {
+ if (mReflectionProbe.isNull())
+ {
+ mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this);
+ }
+ }
+ else if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe = nullptr;
+ }
}
void LLVOVolume::setSelected(BOOL sel)
@@ -4816,7 +4975,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, 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)
{
if (!mbCanSelect
@@ -4826,6 +4985,14 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
return FALSE;
}
+ if (!pick_unselectable)
+ {
+ if (!LLSelectMgr::instance().canSelectObject(this))
+ {
+ return FALSE;
+ }
+ }
+
BOOL ret = FALSE;
LLVolume* volume = getVolume();
@@ -6011,24 +6178,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
bool is_pbr = false;
#endif
- // HACK - make this object a Reflection Probe if a certain UUID is detected
- static LLCachedControl reflection_probe_id(gSavedSettings, "RenderReflectionProbeTextureHackID", "");
- if (facep->getTextureEntry()->getID() == LLUUID(reflection_probe_id))
- {
- if (!vobj->mIsReflectionProbe)
- {
- vobj->mIsReflectionProbe = true;
- vobj->mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(vobj);
- }
- }
- else
- {
- // not a refleciton probe any more
- vobj->mIsReflectionProbe = false;
- vobj->mReflectionProbe = nullptr;
- }
- // END HACK
-
//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
// batch, it will recover its vertex buffer reference from the spatial group
facep->setVertexBuffer(NULL);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 3925b8a3f7..210fe25efb 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -156,6 +156,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -183,6 +184,9 @@ public:
/*virtual*/ void parameterChanged(U16 param_type, bool local_origin);
/*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin);
+ // update mReflectionProbe based on isReflectionProbe()
+ void updateReflectionProbePtr();
+
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num, const EObjectUpdateType update_type,
@@ -286,6 +290,19 @@ public:
F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
F32 getLightCutoff() const;
+ // Reflection Probes
+ void setIsReflectionProbe(BOOL is_probe);
+ void setReflectionProbeAmbiance(F32 ambiance);
+ void setReflectionProbeNearClip(F32 near_clip);
+ void setReflectionProbeIsBox(bool is_box);
+ void setReflectionProbeIsDynamic(bool is_dynamic);
+
+ BOOL isReflectionProbe() const override;
+ F32 getReflectionProbeAmbiance() const;
+ F32 getReflectionProbeNearClip() const;
+ bool getReflectionProbeIsBox() const;
+ bool getReflectionProbeIsDynamic() const;
+
// Flexible Objects
U32 getVolumeInterfaceID() const;
virtual BOOL isFlexible() const;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index f1f1d4818e..9ac3fa8473 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -806,7 +806,8 @@ void LLPipeline::requestResizeShadowTexture()
void LLPipeline::resizeShadowTexture()
{
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
allocateShadowBuffer(mRT->width, mRT->height);
gResizeShadowTexture = FALSE;
}
@@ -839,7 +840,8 @@ void LLPipeline::resizeScreenTexture()
// [/SL:KB]
{
releaseScreenBuffers();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
allocateScreenBuffer(resX,resY);
gResizeScreenTexture = FALSE;
}
@@ -1020,7 +1022,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
mRT->deferredLight.release();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
mRT->fxaaBuffer.release();
mRT->screen.release();
@@ -1063,66 +1066,66 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0
bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
- if (LLPipeline::sRenderDeferred)
- {
- S32 shadow_detail = RenderShadowDetail;
+ if (LLPipeline::sRenderDeferred)
+ {
+ S32 shadow_detail = RenderShadowDetail;
- const U32 occlusion_divisor = 3;
+ const U32 occlusion_divisor = 3;
- F32 scale = llmax(0.f,RenderShadowResolutionScale);
- U32 sun_shadow_map_width = BlurHappySize(resX, scale);
- U32 sun_shadow_map_height = BlurHappySize(resY, scale);
+ F32 scale = llmax(0.f, RenderShadowResolutionScale);
+ U32 sun_shadow_map_width = BlurHappySize(resX, scale);
+ U32 sun_shadow_map_height = BlurHappySize(resY, scale);
- if (shadow_detail > 0)
- { //allocate 4 sun shadow maps
- for (U32 i = 0; i < 4; i++)
- {
- if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (shadow_detail > 0)
+ { //allocate 4 sun shadow maps
+ for (U32 i = 0; i < 4; i++)
+ {
+ if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width / occlusion_divisor, sun_shadow_map_height / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- }
- }
- else
- {
- for (U32 i = 0; i < 4; i++)
- {
- releaseShadowTarget(i);
- }
- }
-
- U32 width = (U32) (resX*scale);
- U32 height = width;
-
- if (shadow_detail > 1)
- { //allocate two spot shadow maps
- U32 spot_shadow_map_width = width;
- U32 spot_shadow_map_height = height;
- for (U32 i = 4; i < 6; i++)
- {
- if (!mRT->shadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
- {
- return false;
- }
- if (!mRT->shadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
- {
- return false;
- }
- }
+ }
}
- else
- {
- for (U32 i = 4; i < 6; i++)
- {
- releaseShadowTarget(i);
- }
- }
- }
+ else
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ releaseSunShadowTarget(i);
+ }
+ }
+
+ if (!gCubeSnapshot) // hack to not allocate spot shadow maps during ReflectionMapManager init
+ {
+ U32 width = (U32)(resX * scale);
+ U32 height = width;
+
+ if (shadow_detail > 1)
+ { //allocate two spot shadow maps
+ U32 spot_shadow_map_width = width;
+ U32 spot_shadow_map_height = height;
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
+ {
+ return false;
+ }
+ if (!mSpotShadowOcclusion[i].allocate(spot_shadow_map_width / occlusion_divisor, height / occlusion_divisor, 0, TRUE, FALSE))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ releaseSpotShadowTargets();
+ }
+ }
+ }
return true;
}
@@ -1323,7 +1326,8 @@ void LLPipeline::releaseLUTBuffers()
void LLPipeline::releaseShadowBuffers()
{
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
}
void LLPipeline::releaseScreenBuffers()
@@ -1339,20 +1343,33 @@ void LLPipeline::releaseScreenBuffers()
}
-void LLPipeline::releaseShadowTarget(U32 index)
+void LLPipeline::releaseSunShadowTarget(U32 index)
{
+ llassert(index < 4);
mRT->shadow[index].release();
mRT->shadowOcclusion[index].release();
}
-void LLPipeline::releaseShadowTargets()
+void LLPipeline::releaseSunShadowTargets()
{
- for (U32 i = 0; i < 6; i++)
+ for (U32 i = 0; i < 4; i++)
{
- releaseShadowTarget(i);
+ releaseSunShadowTarget(i);
}
}
+void LLPipeline::releaseSpotShadowTargets()
+{
+ if (!gCubeSnapshot) // hack to avoid freeing spot shadows during ReflectionMapManager init
+ {
+ for (U32 i = 0; i < 2; i++)
+ {
+ mSpotShadow[i].release();
+ mSpotShadowOcclusion[i].release();
+ }
+ }
+}
+
void LLPipeline::createGLBuffers()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
@@ -6947,15 +6964,6 @@ void LLPipeline::toggleRenderType(U32 type)
//static
void LLPipeline::toggleRenderTypeControl(U32 type)
{
- U32 bit = (1<getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, TRUE, face_hit, &position, NULL, NULL, NULL);
if (hit)
{
drawable = hit;
@@ -7229,6 +7237,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start,
LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
bool pick_transparent,
bool pick_rigged,
+ bool pick_unselectable,
S32* face_hit,
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -7262,7 +7271,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(j);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent);
if (hit)
{
drawable = hit;
@@ -7319,7 +7328,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent);
if (hit)
{
LLVector4a delta;
@@ -7407,7 +7416,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, c
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
if (part)
{
- LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, TRUE, face_hit, intersection, tex_coord, normal, tangent);
if (hit)
{
drawable = hit;
@@ -7957,7 +7966,7 @@ void LLPipeline::renderFinalize()
LLVector4a result;
result.clear();
- gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
+ gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result);
focus_point.set(result.getF32ptr());
}
@@ -8511,7 +8520,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
for (U32 i = 0; i < 4; i++)
{
- LLRenderTarget* shadow_target = getShadowTarget(i);
+ LLRenderTarget* shadow_target = getSunShadowTarget(i);
if (shadow_target)
{
channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
@@ -8519,7 +8528,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
if (channel > -1)
{
stop_glerror();
- gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE);
+ gGL.getTexUnit(channel)->bind(getSunShadowTarget(i), TRUE);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
@@ -8531,27 +8540,27 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
}
- for (U32 i = 4; i < 6; i++)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- LLRenderTarget* shadow_target = getShadowTarget(i);
- if (shadow_target)
- {
- gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
- }
+ for (U32 i = 4; i < 6; i++)
+ {
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0 + i);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ LLRenderTarget* shadow_target = getSpotShadowTarget(i-4);
+ if (shadow_target)
+ {
+ gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+ }
stop_glerror();
@@ -8662,7 +8671,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight());
- shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mRT->shadow[4].getWidth(), mRT->shadow[4].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight());
shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
@@ -9430,7 +9439,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
- if (!gCubeSnapshot)
+ //if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
//determine if this is a good light for casting shadows
@@ -10021,7 +10030,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gDeferredShadowCubeProgram.bind();
}
- LLRenderTarget& occlusion_target = mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_target = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ?
+ mSpotShadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] :
+ mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0];
occlusion_target.bindTarget();
updateCull(shadow_cam, result);
@@ -10165,7 +10176,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
- LLRenderTarget& occlusion_source = mRT->shadow[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_source = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ?
+ mSpotShadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] :
+ mRT->shadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0];
if (occlude > 1)
{
@@ -10440,11 +10453,18 @@ void LLPipeline::generateHighlight(LLCamera& camera)
}
}
-LLRenderTarget* LLPipeline::getShadowTarget(U32 i)
+LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i)
{
+ llassert(i < 4);
return &mRT->shadow[i];
}
+LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i)
+{
+ llassert(i < 2);
+ return &mSpotShadow[i];
+}
+
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render");
@@ -10724,7 +10744,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowFrustPoints[j].clear();
}
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j);
//restore render matrices
set_current_modelview(saved_view);
@@ -11098,116 +11118,119 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
{
if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
{
- LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
- F32 fade_amt = gFrameIntervalSeconds.value()
- * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
+ LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
+ F32 fade_amt = gFrameIntervalSeconds.value()
+ * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
- //update shadow targets
- for (U32 i = 0; i < 2; i++)
- { //for each current shadow
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i);
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
- if (mShadowSpotLight[i].notNull() &&
- (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
- mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
- { //keep this spotlight
- mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
- }
- else
- { //fade out this light
- mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-
- if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
- { //faded out, grab one of the pending spots (whichever one isn't already taken)
- if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[0];
- }
- else
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[1];
- }
- }
- }
- }
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i] + fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i] - fade_amt, 0.f);
- for (S32 i = 0; i < 2; i++)
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i + 1) % 2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
+ }
+
+ for (S32 i = 0; i < 2; i++)
+ {
+ set_current_modelview(saved_view);
+ set_current_projection(saved_proj);
+
+ if (mShadowSpotLight[i].isNull())
{
- set_current_modelview(saved_view);
- set_current_projection(saved_proj);
+ continue;
+ }
- if (mShadowSpotLight[i].isNull())
- {
- continue;
- }
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- if (!volume)
- {
- mShadowSpotLight[i] = NULL;
- continue;
- }
+ LLDrawable* drawable = mShadowSpotLight[i];
- LLDrawable* drawable = mShadowSpotLight[i];
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
- LLVector3 params = volume->getSpotLightParams();
- F32 fov = params.mV[0];
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
- //get agent->light space matrix (modelview)
- LLVector3 center = drawable->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
+ at_axis *= quat;
- //get near clip plane
- LLVector3 scale = volume->getScale();
- LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
- at_axis *= quat;
+ LLVector3 np = center + at_axis;
+ at_axis.normVec();
- LLVector3 np = center + at_axis;
- at_axis.normVec();
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
+ LLVector3 origin = np - at_axis * dist;
- LLVector3 origin = np - at_axis * dist;
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
- LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+ view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
- view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
+ view[i + 4] = view[i + 4].inverse();
- view[i + 4] = view[i + 4].inverse();
+ //get perspective matrix
+ F32 near_clip = dist + 0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist + volume->getLightRadius() * 1.5f;
- //get perspective matrix
- F32 near_clip = dist + 0.01f;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = dist + volume->getLightRadius() * 1.5f;
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width / height;
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width / height;
+ proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
+ set_current_modelview(view[i + 4]);
+ set_current_projection(proj[i + 4]);
- set_current_modelview(view[i + 4]);
- set_current_projection(proj[i + 4]);
+ mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
- mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
+ for (U32 j = 0; j < 16; j++)
+ {
+ gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
+ }
- for (U32 j = 0; j < 16; j++)
- {
- gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
- gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
- }
-
- mShadowModelview[i + 4] = view[i + 4];
- mShadowProjection[i + 4] = proj[i + 4];
+ mShadowModelview[i + 4] = view[i + 4];
+ mShadowProjection[i + 4] = proj[i + 4];
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
LLCamera shadow_cam = camera;
shadow_cam.setFar(far_clip);
shadow_cam.setOrigin(origin);
@@ -11216,15 +11239,17 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
stop_glerror();
- mRT->shadow[i + 4].bindTarget();
- mRT->shadow[i + 4].getViewport(gGLViewport);
- mRT->shadow[i + 4].clear();
+ //
+
+ mSpotShadow[i].bindTarget();
+ mSpotShadow[i].getViewport(gGLViewport);
+ mSpotShadow[i].clear();
- U32 target_width = mRT->shadow[i + 4].getWidth();
+ U32 target_width = mSpotShadow[i].getWidth();
static LLCullResult result[2];
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
RenderSpotLight = drawable;
@@ -11232,7 +11257,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
RenderSpotLight = nullptr;
- mRT->shadow[i + 4].flush();
+ mSpotShadow[i].flush();
}
}
}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 5f1847985d..7f37bc7cdc 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -188,6 +188,7 @@ public:
LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
bool pick_transparent,
bool pick_rigged,
+ bool pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -217,8 +218,9 @@ public:
U32 addObject(LLViewerObject *obj);
void enableShadows(const bool enable_shadows);
- void releaseShadowTargets();
- void releaseShadowTarget(U32 index);
+ void releaseSpotShadowTargets();
+ void releaseSunShadowTargets();
+ void releaseSunShadowTarget(U32 index);
// void setLocalLighting(const bool local_lighting);
// bool isLocalLightingEnabled() const;
@@ -303,7 +305,8 @@ public:
void generateWaterReflection(LLCamera& camera);
void generateSunShadow(LLCamera& camera);
- LLRenderTarget* getShadowTarget(U32 i);
+ LLRenderTarget* getSunShadowTarget(U32 i);
+ LLRenderTarget* getSpotShadowTarget(U32 i);
void generateHighlight(LLCamera& camera);
void renderHighlight(const LLViewerObject* obj, F32 fade);
@@ -680,12 +683,15 @@ public:
LLRenderTarget deferredLight;
//sun shadow map
- LLRenderTarget shadow[6];
- LLRenderTarget shadowOcclusion[6];
+ LLRenderTarget shadow[4];
+ LLRenderTarget shadowOcclusion[4];
};
RenderTargetPack* mRT;
+ LLRenderTarget mSpotShadow[2];
+ LLRenderTarget mSpotShadowOcclusion[2];
+
LLRenderTarget mHighlight;
LLRenderTarget mPhysicsDisplay;
@@ -711,6 +717,7 @@ public:
LLVector3 mShadowFrustOrigin[4];
LLCamera mShadowCamera[8];
LLVector3 mShadowExtents[4][2];
+ // TODO : separate Sun Shadow and Spot Shadow matrices
glh::matrix4f mSunShadowMatrix[6];
glh::matrix4f mShadowModelview[6];
glh::matrix4f mShadowProjection[6];
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 6d4cf041ec..d3a52db03f 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -864,8 +864,42 @@
name="2"
value="2"/>
-
-
+
+ Reflections:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+