Merge branch 'DRTVWR-559' of https://bitbucket.org/lindenlab/viewer
commit
8e4abf8ea3
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
use_prebuilt_binary(tinygltf)
|
||||
|
||||
set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf)
|
||||
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ private:
|
|||
};
|
||||
|
||||
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
|
||||
: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
|
||||
: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL)
|
||||
{
|
||||
mMP = mp;
|
||||
mLOD = lod;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ¢er)
|
|||
{
|
||||
}
|
||||
|
||||
void LLViewerObjectList::generatePickList(LLCamera &camera)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
|
||||
|
||||
LLViewerObject *objectp;
|
||||
S32 i;
|
||||
// Reset all of the GL names to zero.
|
||||
for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
|
||||
{
|
||||
(*iter)->mGLName = 0;
|
||||
}
|
||||
|
||||
mSelectPickList.clear();
|
||||
|
||||
std::vector<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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ public:
|
|||
S32 face,
|
||||
BOOL pick_transparent,
|
||||
BOOL pick_rigged,
|
||||
BOOL pick_unselectable,
|
||||
S32* face_hit,
|
||||
LLVector4a* intersection,
|
||||
LLVector2* tex_coord,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
Loading…
Reference in New Issue