master
Ansariel 2022-06-10 13:52:52 +02:00
commit 8e4abf8ea3
63 changed files with 1861 additions and 771 deletions

View File

@ -3407,6 +3407,66 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>0.132.2</string>
</map>
<key>tinygltf</key>
<map>
<key>canonical_repo</key>
<string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
<key>copyright</key>
<string>// Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many contributors.</string>
<key>description</key>
<string>tinygltf import library</string>
<key>license</key>
<string>MIT</string>
<key>license_file</key>
<string>LICENSES/tinygltf_license.txt</string>
<key>name</key>
<string>tinygltf</string>
<key>platforms</key>
<map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>7fd9a99cea31809c89759905fbba30c9</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>7fd9a99cea31809c89759905fbba30c9</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>7fd9a99cea31809c89759905fbba30c9</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>source</key>
<string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
<key>source_type</key>
<string>git</string>
<key>version</key>
<string>v2.5.0</string>
</map>
<key>tracy</key>
<map>
<key>canonical_repo</key>

View File

@ -0,0 +1,7 @@
# -*- cmake -*-
include(Prebuilt)
use_prebuilt_binary(tinygltf)
set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf)

View File

@ -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<F32>(vec[VX]);
mV[VY] = static_cast<F32>(vec[VY]);
mV[VZ] = static_cast<F32>(vec[VZ]);
mV[VW] = static_cast<F32>(vec[VW]);
return (*this);
}
// deprecated
inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
{

View File

@ -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

View File

@ -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<LLModel*>& 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;
}

View File

@ -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

View File

@ -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 <boost/lexical_cast.hpp>
#include "llsdserialize.h"
#include "lljoint.h"
#include "glh/glh_linear.h"
#include "llmatrix4a.h"
#include <boost/regex.hpp>
#include <boost/algorithm/string/replace.hpp>
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<std::string, std::string> &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;
}

View File

@ -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<std::string, LLImportMaterial> 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<std::string, std::string> &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<gltf_mesh> mMeshes;
std::vector<gltf_render_material> mMaterials;
std::vector<gltf_texture> mTextures;
std::vector<gltf_image> mImages;
std::vector<gltf_sampler> 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<std::string, LLMatrix4> &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<LLModel *> &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

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -41,8 +41,10 @@
<string>RenderLocalLights</string>
<string>RenderMaxPartCount</string>
<string>RenderObjectBump</string>
<string>RenderPBR</string>
<string>RenderQualityPerformance</string>
<string>RenderReflectionDetail</string>
<string>RenderReflectionProbeDetail</string>
<string>RenderShaderLightingMaxLevel</string>
<string>RenderShadowDetail</string>
<string>RenderShadowResolutionScale</string>

View File

@ -13366,6 +13366,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>2</integer>
</map>
<key>RenderReflectionProbeDetail</key>
<map>
<key>Comment</key>
<string>Detail of reflections.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderReflectionProbeDrawDistance</key>
<map>
@ -14382,6 +14393,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>0</integer>
</map>
<key>SelectInvisibleObjects</key>
<map>
<key>Comment</key>
<string>Select invisible objects</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>SelectOwnedOnly</key>
<map>
<key>Comment</key>

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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<LLVOVolume*>::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)

View File

@ -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

View File

@ -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();

View File

@ -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"
// <FS:CR> 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<std::string>* 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
// <FS:TS> 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:

View File

@ -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,

View File

@ -98,7 +98,7 @@ private:
};
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL)
{
mMP = mp;
mLOD = lod;

View File

@ -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) // <FS:Ansariel> 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)
{

View File

@ -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<LLViewerTexture> mImagep;
LLFrameTimer mAnimTimer;
LLFrameTimer mLifeTimer;
F32 mDistance;
S32 mPickID;
F32 mScale;
BOOL mHidden;

View File

@ -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<std::string, std::string> joint_alias_map;
getJointAliases(joint_alias_map);
std::array<std::string,LLModel::NUM_LODS> 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"))
{
// <FS> allow LOD suffix configuration
std::array<std::string, LLModel::NUM_LODS> lod_suffix;
for (int i = 0; i < LLModel::NUM_LODS; i++)
{
lod_suffix[i] = gSavedSettings.getString(sSuffixVarNames[i]);
}
// </FS>
mModelLoader = new LLDAELoader(
filename,
lod,
&LLModelPreview::loadedCallback,
&LLModelPreview::lookupJointByName,
&LLModelPreview::loadTextures,
&LLModelPreview::stateChangedCallback,
this,
mJointTransformMap,
mJointsFromNode,
joint_alias_map,
LLSkinningUtil::getMaxJointCount(),
gSavedSettings.getU32("ImporterModelLimit"),
// <FS:Beq> 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"),
// <FS:Beq> 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)
{

View File

@ -145,6 +145,15 @@ BOOL LLPanelVolume::postBuild()
getChild<LLUICtrl>("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<LLUICtrl>("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<LLComboBox>("Probe Volume Type", true)->clear();
getChild<LLSpinCtrl>("Probe Ambiance", true)->clear();
getChild<LLSpinCtrl>("Probe Near Clip", true)->clear();
getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->clear();
}
else
{
std::string volume_type;
if (volobjp->getReflectionProbeIsBox())
{
volume_type = "Box";
}
else
{
volume_type = "Sphere";
}
getChild<LLComboBox>("Probe Volume Type", true)->setValue(volume_type);
getChild<LLSpinCtrl>("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
getChild<LLSpinCtrl>("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic());
}
// Animated Mesh
BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject();
getChild<LLUICtrl>("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<LLUICtrl>("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<LLUICtrl>("Probe Ambiance")->getValue().asReal());
volobjp->setReflectionProbeNearClip((F32)self->getChild<LLUICtrl>("Probe Near Clip")->getValue().asReal());
volobjp->setReflectionProbeIsDynamic(self->getChild<LLUICtrl>("Probe Dynamic")->getValue().asBoolean());
std::string shape_type = self->getChild<LLUICtrl>("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 )
{

View File

@ -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);

View File

@ -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<F32> 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));

View File

@ -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;
};

View File

@ -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()
// <FS:Ansariel> 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<F32> 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");

View File

@ -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<LLPointer<LLReflectionMap> > mProbes;
@ -133,6 +143,5 @@ private:
LLReflectionMap* mUpdatingProbe = nullptr;
U32 mUpdatingFace = 0;
};

View File

@ -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;

View File

@ -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)
{
// <FS:Ansariel> 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;

View File

@ -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

View File

@ -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);

View File

@ -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
// <FS:Ansariel> 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);

View File

@ -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;

View File

@ -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))

View File

@ -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");

View File

@ -285,9 +285,6 @@ void LLMediaFilePicker::notify(const std::vector<std::string>& 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:

View File

@ -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:
{

View File

@ -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<LLViewerTexture> *mTENormalMaps;
LLPointer<LLViewerTexture> *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

View File

@ -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);
// <FS:Beq> 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 &center)
{
}
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<LLDrawable*> 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<LLDrawable*>::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<LLCharacter*>::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;
// <FS:Ansariel> Possible crash fix
//if (attachment->getIsHUDAttachment())
if (attachment && attachment->getIsHUDAttachment())
// </FS:Ansariel>
{
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<LLViewerObject*>::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<LLViewerObject*>::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,

View File

@ -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<U64, LLUUID> sIndexAndLocalIDToUUID;
std::set<LLViewerObject *> mSelectPickList;
friend class LLViewerObject;
private:

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -74,6 +74,7 @@ public:
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,

View File

@ -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)
{

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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<std::string> 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<std::string> 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);

View File

@ -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;

View File

@ -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<<type);
if (gPipeline.hasRenderType(type))
{
LL_INFOS() << "Toggling render type mask " << std::hex << bit << " off" << std::dec << LL_ENDL;
}
else
{
LL_INFOS() << "Toggling render type mask " << std::hex << bit << " on" << std::dec << LL_ENDL;
}
gPipeline.toggleRenderType(type);
}
@ -7201,7 +7209,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start,
LLSpatialPartition* part = region->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();
}
}
}

View File

@ -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];

View File

@ -864,8 +864,42 @@
name="2"
value="2"/>
</combo_box>
<!-- End of Advanced Settings block -->
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="480"
name="RenderReflectionDetailText"
text_readonly_color="LabelDisabledColor"
top_delta="16"
width="128">
Reflections:
</text>
<combo_box
control_name="RenderReflectionProbeDetail"
height="18"
layout="topleft"
left_delta="130"
top_delta="0"
name="ReflectionDetial"
width="150">
<combo_box.item
label="Static Only"
name="0"
value="0"/>
<combo_box.item
label="Static+Dynamic"
name="1"
value="1"/>
<combo_box.item
label="Realtime"
name="2"
value="2"/>
</combo_box>
<!-- End of Advanced Settings block -->
<view_border
bevel_style="in"
height="0"

View File

@ -2913,7 +2913,7 @@ Low ↔ Lwst
left="10"
name="Light Checkbox Ctrl"
tool_tip="Causes object to emit light"
top_pad="15"
top_pad="10"
width="60" />
<color_swatch
can_apply_immediately="true"
@ -2949,7 +2949,7 @@ Low ↔ Lwst
layout="topleft"
left="10"
name="Light Intensity"
top_pad="3"
top_delta="32"
width="128" />
<spinner bottom_delta="0"
decimal_digits="3"
@ -3016,6 +3016,70 @@ Low ↔ Lwst
mouse_opaque="true"
name="Light Ambiance"
width="120" />
<check_box
height="16"
label="Reflection Probe"
layout="topleft"
left="10"
name="Reflection Probe"
tool_tip="Adjusts how objects within this volume receive reflections when PBR is enabled"
top_pad="9"
width="60" />
<combo_box
height="19"
top_delta="0"
left="144"
follows="left|top"
name="Probe Volume Type"
tool_tip="Choose the probe influence volume"
width="108">
<combo_box.item
label="Sphere"
name="Sphere"
value="Sphere" />
<combo_box.item
label="Box"
name="Box"
value="Box"/>
</combo_box>
<check_box
height="16"
label="Dynamic"
layout="topleft"
follows="left|top"
left="10"
name="Probe Dynamic"
tool_tip="When enabled, Avatars will appear in reflections within this probe's influence volume."
top_delta="17"
width="60" />
<spinner top_pad="0"
decimal_digits="3"
follows="left|top"
height="16"
increment="0.05"
initial_value="0"
label="Ambiance"
label_width="55"
left="10"
max_val="1"
min_val="0"
mouse_opaque="true"
name="Probe Ambiance"
width="120" />
<spinner top_delta="0"
decimal_digits="3"
follows="left|top"
height="16"
increment="0.05"
initial_value="0"
label="Near Clip"
label_width="55"
left="144"
max_val="1024"
min_val="0"
mouse_opaque="true"
name="Probe Near Clip"
width="120" />
<text
type="string"
length="1"

View File

@ -1987,6 +1987,15 @@
function="Tools.SelectOnlyMovableObjects"
parameter="movable" />
</menu_item_check>
<menu_item_check
label="Select Invisible Objects"
name="Select Invisible Objects">
<menu_item_check.on_check
control="SelectInvisibleObjects" />
<menu_item_check.on_click
function="Tools.SelectInvisibleObjects"
parameter="invisible" />
</menu_item_check>
<menu_item_check
label="Select Only Locked Objects"
name="Select Only Locked Objects">