Merge branch 'release/materials_featurette' of https://github.com/secondlife/viewer
# Conflicts: # indra/fix-incredibuild.py # indra/newview/CMakeLists.txt # indra/newview/llagentbenefits.cpp # indra/newview/llgltfmateriallist.cpp # indra/newview/llspatialpartition.cpp # indra/newview/llviewermenu.cpp # indra/newview/llviewerregion.cpp # indra/newview/llvocache.cpp # indra/newview/llvocache.h # indra/newview/llvovolume.cpp # indra/newview/pipeline.cpp # indra/newview/skins/default/xui/en/notifications.xml # indra/newview/viewer_manifest.pymaster
commit
3b902c9f36
|
|
@ -12,14 +12,10 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
runner: [windows-large, macos-12-xl]
|
||||
configuration: [Release, ReleaseOS]
|
||||
python-version: ["3.11"]
|
||||
configuration: [Release]
|
||||
include:
|
||||
- runner: macos-12-xl
|
||||
developer_dir: "/Applications/Xcode_14.0.1.app/Contents/Developer"
|
||||
exclude:
|
||||
- runner: macos-12-xl
|
||||
configuration: ReleaseOS
|
||||
runs-on: ${{ matrix.runner }}
|
||||
outputs:
|
||||
viewer_channel: ${{ steps.build.outputs.viewer_channel }}
|
||||
|
|
@ -67,7 +63,7 @@ jobs:
|
|||
- name: Setup python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Checkout build variables
|
||||
uses: actions/checkout@v4
|
||||
|
|
@ -101,7 +97,7 @@ jobs:
|
|||
|
||||
- name: Determine source branch
|
||||
id: which-branch
|
||||
uses: secondlife/viewer-build-util/which-branch@v1
|
||||
uses: secondlife/viewer-build-util/which-branch@v2
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
|
||||
|
|
@ -271,7 +267,7 @@ jobs:
|
|||
steps:
|
||||
- name: Sign and package Windows viewer
|
||||
if: env.AZURE_KEY_VAULT_URI && env.AZURE_CERT_NAME && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET && env.AZURE_TENANT_ID
|
||||
uses: secondlife/viewer-build-util/sign-pkg-windows@v1
|
||||
uses: secondlife/viewer-build-util/sign-pkg-windows@v2
|
||||
with:
|
||||
vault_uri: "${{ env.AZURE_KEY_VAULT_URI }}"
|
||||
cert_name: "${{ env.AZURE_CERT_NAME }}"
|
||||
|
|
@ -310,7 +306,7 @@ jobs:
|
|||
|
||||
- name: Sign and package Mac viewer
|
||||
if: env.SIGNING_CERT_MACOS && env.SIGNING_CERT_MACOS_IDENTITY && env.SIGNING_CERT_MACOS_PASSWORD && steps.note-creds.outputs.note_user && steps.note-creds.outputs.note_pass && steps.note-creds.outputs.note_team
|
||||
uses: secondlife/viewer-build-util/sign-pkg-mac@v1
|
||||
uses: secondlife/viewer-build-util/sign-pkg-mac@v2
|
||||
with:
|
||||
channel: ${{ needs.build.outputs.viewer_channel }}
|
||||
imagename: ${{ needs.build.outputs.imagename }}
|
||||
|
|
@ -330,7 +326,7 @@ jobs:
|
|||
steps:
|
||||
- name: Post Windows symbols
|
||||
if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
|
||||
uses: secondlife/viewer-build-util/post-bugsplat-windows@v1
|
||||
uses: secondlife/viewer-build-util/post-bugsplat-windows@v2
|
||||
with:
|
||||
username: ${{ env.BUGSPLAT_USER }}
|
||||
password: ${{ env.BUGSPLAT_PASS }}
|
||||
|
|
@ -347,7 +343,7 @@ jobs:
|
|||
steps:
|
||||
- name: Post Mac symbols
|
||||
if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
|
||||
uses: secondlife/viewer-build-util/post-bugsplat-mac@v1
|
||||
uses: secondlife/viewer-build-util/post-bugsplat-mac@v2
|
||||
with:
|
||||
username: ${{ env.BUGSPLAT_USER }}
|
||||
password: ${{ env.BUGSPLAT_PASS }}
|
||||
|
|
@ -360,31 +356,20 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: Windows-installer
|
||||
pattern: "*-installer"
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: macOS-installer
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: Windows-metadata
|
||||
|
||||
- name: Rename windows metadata
|
||||
pattern: "*-metadata"
|
||||
|
||||
- name: Rename metadata
|
||||
run: |
|
||||
mv autobuild-package.xml Windows-autobuild-package.xml
|
||||
mv newview/viewer_version.txt Windows-viewer_version.txt
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: macOS-metadata
|
||||
|
||||
- name: Rename macOS metadata
|
||||
run: |
|
||||
mv autobuild-package.xml macOS-autobuild-package.xml
|
||||
mv newview/viewer_version.txt macOS-viewer_version.txt
|
||||
cp Windows-metadata/autobuild-package.xml Windows-autobuild-package.xml
|
||||
cp Windows-metadata/newview/viewer_version.txt Windows-viewer_version.txt
|
||||
cp macOS-metadata/autobuild-package.xml macOS-autobuild-package.xml
|
||||
cp macOS-metadata/newview/viewer_version.txt macOS-viewer_version.txt
|
||||
|
||||
# forked from softprops/action-gh-release
|
||||
- name: Create GitHub release
|
||||
|
|
@ -407,8 +392,8 @@ jobs:
|
|||
append_body: true
|
||||
fail_on_unmatched_files: true
|
||||
files: |
|
||||
*.dmg
|
||||
*.exe
|
||||
macOS-installer/*.dmg
|
||||
Windows-installer/*.exe
|
||||
*-autobuild-package.xml
|
||||
*-viewer_version.txt
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
PERSONAL_ACCESS_TOKEN: ${{ secrets.SHARED_CLA_TOKEN }}
|
||||
with:
|
||||
branch: main
|
||||
path-to-document: https://github.com/secondlife/cla/blob/master/CLA.md
|
||||
path-to-document: https://github.com/secondlife/cla/blob/main/CLA.md
|
||||
path-to-signatures: signatures.json
|
||||
remote-organization-name: secondlife
|
||||
remote-repository-name: cla-signatures
|
||||
|
|
|
|||
73
BuildParams
73
BuildParams
|
|
@ -1,73 +0,0 @@
|
|||
# BuildParams
|
||||
#
|
||||
# Please refer to:
|
||||
# https://wiki.secondlife.com/wiki/Automated_Build_System
|
||||
|
||||
# Variants (NOTE: 'Release' must be last for uploads to work correctly)
|
||||
variants = "RelWithDebInfo Release"
|
||||
|
||||
# Use Public Upload Locations
|
||||
public_build = true
|
||||
build_docs = true
|
||||
|
||||
# enable Doxygen building on Linux for TeamCity (it can be done manually on any platform)
|
||||
build_Linux_Doxygen = true
|
||||
|
||||
# Need viewer-build-variables as well as other shared repositories
|
||||
buildscripts_shared_more_NAMEs="build_secrets build_variables git_hooks"
|
||||
|
||||
# Python 3 / SL-15742
|
||||
BUILDSCRIPTS_PY3 = "true"
|
||||
|
||||
################################################################
|
||||
#### Examples of how to set the viewer_channel ####
|
||||
#
|
||||
# To build a Release or Release candidate in build bingo:
|
||||
# bingo.viewer_channel = "Second Life Release"
|
||||
#
|
||||
# To build a Beta for the 'Bingo' project in build bingo:
|
||||
# bingo.viewer_channel = "Second Life Beta Bingo"
|
||||
#
|
||||
# To build a Project viewer for the 'Bingo' project in build bingo:
|
||||
# bingo.viewer_channel = "Second Life Project Bingo"
|
||||
#
|
||||
# If left unset, viewer_channel defaults to 'Second Life Test',
|
||||
# which is appropriate for individual developer builds.
|
||||
#
|
||||
# All Linden Lab builds (and only Linden Lab builds)
|
||||
# should use a viewer_channel that begins with "Second Life"
|
||||
################################################################
|
||||
viewer_channel = "Second Life Test"
|
||||
|
||||
|
||||
################################################################
|
||||
# Special packaging parameters.
|
||||
# These parameters can be used to create additional packages
|
||||
# which identify themselves in a distinct way with either
|
||||
# a sourceid (sent to web services) or a channel name (sent to login)
|
||||
# the default sourceid should always be a null string:
|
||||
sourceid = ""
|
||||
# the additional_packages variable is a blank separated list of package prefixes:
|
||||
# additional_packages = ""
|
||||
# to set the special values for a package, create variables using each prefix:
|
||||
# additional_packages = "Foo Bar"
|
||||
# Foo_sourceid = "bingo"
|
||||
# Foo_viewer_channel_suffix = "Foo"
|
||||
# Bar_sourceid = "bongo"
|
||||
# Bar_viewer_channel_suffix = "Bar"
|
||||
# the viewer_channel_suffix is prefixed by a blank and then appended to the viewer_channel
|
||||
# for the package in a setting that overrides the compiled-in value
|
||||
################################################################
|
||||
additional_packages = "EDU"
|
||||
Linux.additional_packages = ""
|
||||
|
||||
# The EDU package allows us to create a separate release channel whose expirations
|
||||
# are synchronized as much as possible with the academic year
|
||||
EDU_sourceid = ""
|
||||
EDU_viewer_channel_suffix = "edu"
|
||||
|
||||
# Notifications - to configure email notices use the TeamCity parameter
|
||||
# setting screen for your project or build configuration to set the
|
||||
# environment variable 'email' to a space-separated list of email addresses
|
||||
email=""
|
||||
|
||||
13
build.sh
13
build.sh
|
|
@ -6,9 +6,6 @@
|
|||
# it relies on the environment that sets up, functions it provides, and
|
||||
# the build result post-processing it does.
|
||||
#
|
||||
# The shared buildscript build.sh invokes this because it is named 'build.sh',
|
||||
# which is the default custom build script name in buildscripts/hg/BuildParams
|
||||
#
|
||||
# PLEASE NOTE:
|
||||
#
|
||||
# * This script is interpreted on three platforms, including windows and cygwin
|
||||
|
|
@ -85,7 +82,7 @@ installer_Linux()
|
|||
{
|
||||
local package_name="$1"
|
||||
local package_dir="$(build_dir_Linux)/newview/"
|
||||
local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_i686\\.tar\\.bz2\$"
|
||||
local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_i686\\.tar\\.xz\$"
|
||||
# since the additional packages are built after the base package,
|
||||
# sorting oldest first ensures that the unqualified package is returned
|
||||
# even if someone makes a qualified name that duplicates the last word of the base name
|
||||
|
|
@ -173,7 +170,7 @@ pre_build()
|
|||
# This name is consumed by indra/newview/CMakeLists.txt. Make it
|
||||
# absolute because we've had troubles with relative pathnames.
|
||||
abs_build_dir="$(cd "$build_dir"; pwd)"
|
||||
VIEWER_SYMBOL_FILE="$(native_path "$abs_build_dir/newview/$variant/secondlife-symbols-$symplat-${AUTOBUILD_ADDRSIZE}.tar.bz2")"
|
||||
VIEWER_SYMBOL_FILE="$(native_path "$abs_build_dir/newview/$variant/secondlife-symbols-$symplat-${AUTOBUILD_ADDRSIZE}.tar.xz")"
|
||||
fi
|
||||
|
||||
# honor autobuild_configure_parameters same as sling-buildscripts
|
||||
|
|
@ -417,10 +414,10 @@ do
|
|||
fi
|
||||
if [ -d "$build_dir/doxygen/html" ]
|
||||
then
|
||||
tar -c -f "$build_dir/viewer-doxygen.tar.bz2" --strip-components 3 "$build_dir/doxygen/html"
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Tarball" "$build_dir/viewer-doxygen.tar.bz2" \
|
||||
tar -cJf "$build_dir/viewer-doxygen.tar.xz" --strip-components 3 "$build_dir/doxygen/html"
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Tarball" "$build_dir/viewer-doxygen.tar.xz" \
|
||||
|| fatal "Upload of doxygen tarball failed"
|
||||
metadata+=("$build_dir/viewer-doxygen.tar.bz2")
|
||||
metadata+=("$build_dir/viewer-doxygen.tar.xz")
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
##
|
||||
## $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
## Second Life Viewer Source Code
|
||||
## Copyright (C) 2011, 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$
|
||||
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
|
||||
def delete_file_types(path, filetypes):
|
||||
if os.path.exists(path):
|
||||
print('Cleaning: ' + path)
|
||||
orig_dir = os.getcwd();
|
||||
os.chdir(path)
|
||||
filelist = []
|
||||
for type in filetypes:
|
||||
filelist.extend(glob.glob(type))
|
||||
for file in filelist:
|
||||
os.remove(file)
|
||||
os.chdir(orig_dir)
|
||||
|
||||
def main():
|
||||
build_types = ['*.exp','*.exe','*.pdb','*.idb',
|
||||
'*.ilk','*.lib','*.obj','*.ib_pdb_index']
|
||||
pch_types = ['*.pch']
|
||||
delete_file_types("build-vc80/newview/Release", build_types)
|
||||
delete_file_types("build-vc80/newview/firestorm-bin.dir/Release/",
|
||||
pch_types)
|
||||
delete_file_types("build-vc80/newview/RelWithDebInfo", build_types)
|
||||
delete_file_types("build-vc80/newview/firestorm-bin.dir/RelWithDebInfo/",
|
||||
pch_types)
|
||||
delete_file_types("build-vc80/newview/Debug", build_types)
|
||||
delete_file_types("build-vc80/newview/firestorm-bin.dir/Debug/",
|
||||
pch_types)
|
||||
|
||||
|
||||
delete_file_types("build-vc80/test/RelWithDebInfo", build_types)
|
||||
delete_file_types("build-vc80/test/test.dir/RelWithDebInfo/",
|
||||
pch_types)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -45,13 +45,13 @@
|
|||
#include "llmatrix3a.h"
|
||||
#include "lloctree.h"
|
||||
#include "llvolume.h"
|
||||
#include "llvolumeoctree.h"
|
||||
#include "llstl.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llvector4a.h"
|
||||
#include "llmatrix4a.h"
|
||||
#include "llmeshoptimizer.h"
|
||||
#include "lltimer.h"
|
||||
#include "llvolumeoctree.h"
|
||||
|
||||
#include "mikktspace/mikktspace.h"
|
||||
#include "mikktspace/mikktspace.c" // insert mikktspace implementation into llvolume object file
|
||||
|
|
@ -394,77 +394,6 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons
|
|||
}
|
||||
}
|
||||
|
||||
class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle, LLVolumeTriangle*>
|
||||
{
|
||||
public:
|
||||
const LLVolumeFace* mFace;
|
||||
|
||||
LLVolumeOctreeRebound(const LLVolumeFace* face)
|
||||
{
|
||||
mFace = face;
|
||||
}
|
||||
|
||||
virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch)
|
||||
{ //this is a depth first traversal, so it's safe to assum all children have complete
|
||||
//bounding data
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME
|
||||
|
||||
LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0);
|
||||
|
||||
LLVector4a& min = node->mExtents[0];
|
||||
LLVector4a& max = node->mExtents[1];
|
||||
|
||||
if (!branch->isEmpty())
|
||||
{ //node has data, find AABB that binds data set
|
||||
const LLVolumeTriangle* tri = *(branch->getDataBegin());
|
||||
|
||||
//initialize min/max to first available vertex
|
||||
min = *(tri->mV[0]);
|
||||
max = *(tri->mV[0]);
|
||||
|
||||
for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter)
|
||||
{ //for each triangle in node
|
||||
|
||||
//stretch by triangles in node
|
||||
tri = *iter;
|
||||
|
||||
min.setMin(min, *tri->mV[0]);
|
||||
min.setMin(min, *tri->mV[1]);
|
||||
min.setMin(min, *tri->mV[2]);
|
||||
|
||||
max.setMax(max, *tri->mV[0]);
|
||||
max.setMax(max, *tri->mV[1]);
|
||||
max.setMax(max, *tri->mV[2]);
|
||||
}
|
||||
}
|
||||
else if (branch->getChildCount() > 0)
|
||||
{ //no data, but child nodes exist
|
||||
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0);
|
||||
|
||||
//initialize min/max to extents of first child
|
||||
min = child->mExtents[0];
|
||||
max = child->mExtents[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(!branch->isLeaf()); // Empty leaf
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < branch->getChildCount(); ++i)
|
||||
{ //stretch by child extents
|
||||
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0);
|
||||
min.setMin(min, child->mExtents[0]);
|
||||
max.setMax(max, child->mExtents[1]);
|
||||
}
|
||||
|
||||
node->mBounds[0].setAdd(min, max);
|
||||
node->mBounds[0].mul(0.5f);
|
||||
|
||||
node->mBounds[1].setSub(max,min);
|
||||
node->mBounds[1].mul(0.5f);
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// statics
|
||||
//-------------------------------------------------------------------
|
||||
|
|
@ -5547,7 +5476,6 @@ struct MikktData
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
bool LLVolumeFace::cacheOptimize(bool gen_tangents)
|
||||
{ //optimize for vertex cache according to Forsyth method:
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
|
||||
|
|
@ -5726,8 +5654,7 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
|
|||
ND_OCTREE_LOG << "Creating octree with scale " << scaler << " mNumIndices " << mNumIndices << ND_OCTREE_LOG_END;
|
||||
llassert(mNumIndices % 3 == 0);
|
||||
|
||||
mOctree = new LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(center, size, NULL);
|
||||
new LLVolumeOctreeListener(mOctree);
|
||||
mOctree = new LLVolumeOctree(center, size);
|
||||
const U32 num_triangles = mNumIndices / 3;
|
||||
// Initialize all the triangles we need
|
||||
mOctreeTriangles = new LLVolumeTriangle[num_triangles];
|
||||
|
|
@ -5790,7 +5717,7 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
|
|||
while (!mOctree->balance()) { }
|
||||
|
||||
//calculate AABB for each node
|
||||
LLVolumeOctreeRebound rebound(this);
|
||||
LLVolumeOctreeRebound rebound;
|
||||
rebound.traverse(mOctree);
|
||||
|
||||
if (gDebugGL)
|
||||
|
|
@ -5803,12 +5730,12 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
|
|||
void LLVolumeFace::destroyOctree()
|
||||
{
|
||||
delete mOctree;
|
||||
mOctree = NULL;
|
||||
mOctree = nullptr;
|
||||
delete[] mOctreeTriangles;
|
||||
mOctreeTriangles = NULL;
|
||||
mOctreeTriangles = nullptr;
|
||||
}
|
||||
|
||||
const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* LLVolumeFace::getOctree() const
|
||||
const LLVolumeOctree* LLVolumeFace::getOctree() const
|
||||
{
|
||||
return mOctree;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ template <class T, typename T_PTR> class LLOctreeNode;
|
|||
class LLVolumeFace;
|
||||
class LLVolume;
|
||||
class LLVolumeTriangle;
|
||||
class LLVolumeOctree;
|
||||
|
||||
#include "lluuid.h"
|
||||
#include "v4color.h"
|
||||
|
|
@ -916,7 +917,7 @@ public:
|
|||
void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
|
||||
void destroyOctree();
|
||||
// Get a reference to the octree, which may be null
|
||||
const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* getOctree() const;
|
||||
const LLVolumeOctree* getOctree() const;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -990,7 +991,7 @@ public:
|
|||
LLVector3 mNormalizedScale = LLVector3(1,1,1);
|
||||
|
||||
private:
|
||||
LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* mOctree;
|
||||
LLVolumeOctree* mOctree;
|
||||
LLVolumeTriangle* mOctreeTriangles;
|
||||
|
||||
BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
|
||||
|
|
|
|||
|
|
@ -92,15 +92,15 @@ void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTria
|
|||
}
|
||||
|
||||
LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,
|
||||
const LLVolumeFace* face, F32* closest_t,
|
||||
LLVolumeFace* face, F32* closest_t,
|
||||
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
|
||||
: mFace(face),
|
||||
mStart(start),
|
||||
: mStart(start),
|
||||
mDir(dir),
|
||||
mIntersection(intersection),
|
||||
mTexCoord(tex_coord),
|
||||
mNormal(normal),
|
||||
mTangent(tangent),
|
||||
mFace(face),
|
||||
mClosestT(closest_t),
|
||||
mHitFace(false)
|
||||
{
|
||||
|
|
@ -139,7 +139,7 @@ void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LL
|
|||
{
|
||||
*mClosestT = t;
|
||||
mHitFace = true;
|
||||
|
||||
mHitTriangle = tri;
|
||||
if (mIntersection != NULL)
|
||||
{
|
||||
LLVector4a intersect = mDir;
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ public:
|
|||
class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle, LLVolumeTriangle*>
|
||||
{
|
||||
public:
|
||||
const LLVolumeFace* mFace;
|
||||
LLVector4a mStart;
|
||||
LLVector4a mDir;
|
||||
LLVector4a mEnd;
|
||||
|
|
@ -121,10 +120,13 @@ public:
|
|||
LLVector4a* mNormal;
|
||||
LLVector4a* mTangent;
|
||||
F32* mClosestT;
|
||||
LLVolumeFace* mFace;
|
||||
bool mHitFace;
|
||||
const LLVolumeTriangle* mHitTriangle = nullptr;
|
||||
|
||||
LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,
|
||||
const LLVolumeFace* face, F32* closest_t,
|
||||
LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,
|
||||
LLVolumeFace* face,
|
||||
F32* closest_t,
|
||||
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent);
|
||||
|
||||
void traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node);
|
||||
|
|
@ -137,4 +139,91 @@ class LLVolumeOctreeValidate : public LLOctreeTraveler<LLVolumeTriangle, LLVolum
|
|||
virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch);
|
||||
};
|
||||
|
||||
class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle, LLVolumeTriangle*>
|
||||
{
|
||||
public:
|
||||
LLVolumeOctreeRebound()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch)
|
||||
{ //this is a depth first traversal, so it's safe to assum all children have complete
|
||||
//bounding data
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME
|
||||
|
||||
LLVolumeOctreeListener* node = (LLVolumeOctreeListener*)branch->getListener(0);
|
||||
|
||||
LLVector4a& min = node->mExtents[0];
|
||||
LLVector4a& max = node->mExtents[1];
|
||||
|
||||
if (!branch->isEmpty())
|
||||
{ //node has data, find AABB that binds data set
|
||||
const LLVolumeTriangle* tri = *(branch->getDataBegin());
|
||||
|
||||
//initialize min/max to first available vertex
|
||||
min = *(tri->mV[0]);
|
||||
max = *(tri->mV[0]);
|
||||
|
||||
for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter)
|
||||
{ //for each triangle in node
|
||||
|
||||
//stretch by triangles in node
|
||||
tri = *iter;
|
||||
|
||||
min.setMin(min, *tri->mV[0]);
|
||||
min.setMin(min, *tri->mV[1]);
|
||||
min.setMin(min, *tri->mV[2]);
|
||||
|
||||
max.setMax(max, *tri->mV[0]);
|
||||
max.setMax(max, *tri->mV[1]);
|
||||
max.setMax(max, *tri->mV[2]);
|
||||
}
|
||||
}
|
||||
else if (branch->getChildCount() > 0)
|
||||
{ //no data, but child nodes exist
|
||||
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*)branch->getChild(0)->getListener(0);
|
||||
|
||||
//initialize min/max to extents of first child
|
||||
min = child->mExtents[0];
|
||||
max = child->mExtents[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(!branch->isLeaf()); // Empty leaf
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < branch->getChildCount(); ++i)
|
||||
{ //stretch by child extents
|
||||
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*)branch->getChild(i)->getListener(0);
|
||||
min.setMin(min, child->mExtents[0]);
|
||||
max.setMax(max, child->mExtents[1]);
|
||||
}
|
||||
|
||||
node->mBounds[0].setAdd(min, max);
|
||||
node->mBounds[0].mul(0.5f);
|
||||
|
||||
node->mBounds[1].setSub(max, min);
|
||||
node->mBounds[1].mul(0.5f);
|
||||
}
|
||||
};
|
||||
|
||||
class LLVolumeOctree : public LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>, public LLRefCount
|
||||
{
|
||||
public:
|
||||
LLVolumeOctree(const LLVector4a& center, const LLVector4a& size)
|
||||
:
|
||||
LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(center, size, nullptr),
|
||||
LLRefCount()
|
||||
{
|
||||
new LLVolumeOctreeListener(this);
|
||||
}
|
||||
|
||||
LLVolumeOctree()
|
||||
: LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(LLVector4a::getZero(), LLVector4a(1.f,1.f,1.f), nullptr),
|
||||
LLRefCount()
|
||||
{
|
||||
new LLVolumeOctreeListener(this);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -673,7 +673,7 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
|
|||
U16 idx = indicesp[i];
|
||||
gGL.vertex3fv(pos[idx].getF32ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
gGL.end();
|
||||
gGL.flush();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,6 @@ set(viewer_SOURCE_FILES
|
|||
fsscriptlibrary.cpp
|
||||
fsscrolllistctrl.cpp
|
||||
fsslurlcommand.cpp
|
||||
groupchatlistener.cpp
|
||||
lggbeamcolormapfloater.cpp
|
||||
lggbeammapfloater.cpp
|
||||
lggbeammaps.cpp
|
||||
|
|
@ -186,6 +185,10 @@ set(viewer_SOURCE_FILES
|
|||
vjfloaterlocalmesh.cpp
|
||||
vjlocalmeshimportdae.cpp
|
||||
|
||||
gltfscenemanager.cpp
|
||||
gltf/asset.cpp
|
||||
gltf/primitive.cpp
|
||||
groupchatlistener.cpp
|
||||
llaccountingcostmanager.cpp
|
||||
llaisapi.cpp
|
||||
llagent.cpp
|
||||
|
|
@ -963,8 +966,6 @@ set(viewer_HEADER_FILES
|
|||
fsscrolllistctrl.h
|
||||
fsslurl.h
|
||||
fsslurlcommand.h
|
||||
groupchatlistener.h
|
||||
llaccountingcost.h
|
||||
lggbeamcolormapfloater.h
|
||||
lggbeammapfloater.h
|
||||
lggbeammaps.h
|
||||
|
|
@ -981,6 +982,11 @@ set(viewer_HEADER_FILES
|
|||
vjfloaterlocalmesh.h
|
||||
vjlocalmeshimportdae.h
|
||||
|
||||
gltfscenemanager.h
|
||||
groupchatlistener.h
|
||||
gltf/asset.h
|
||||
gltf/primitive.h
|
||||
llaccountingcost.h
|
||||
llaccountingcostmanager.h
|
||||
llaisapi.h
|
||||
llagent.h
|
||||
|
|
@ -2307,7 +2313,7 @@ if (WINDOWS)
|
|||
|
||||
if (PACKAGE)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.xz
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
ARGS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
|
||||
|
|
@ -2352,7 +2358,7 @@ if (WINDOWS)
|
|||
)
|
||||
# temporarily disable packaging of event_host until hg subrepos get
|
||||
# sorted out on the parabuild cluster...
|
||||
#${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2)
|
||||
#${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.xz)
|
||||
|
||||
endif (PACKAGE)
|
||||
elseif (DARWIN)
|
||||
|
|
@ -2506,7 +2512,7 @@ if (LINUX)
|
|||
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer10 media_plugin_cef linux-crash-logger)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${product}.tar.bz2
|
||||
OUTPUT ${product}.tar.xz
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
ARGS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
|
|
@ -2559,7 +2565,7 @@ if (LINUX)
|
|||
add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched)
|
||||
|
||||
if (PACKAGE)
|
||||
add_custom_target(llpackage ALL DEPENDS ${product}.tar.bz2)
|
||||
add_custom_target(llpackage ALL DEPENDS ${product}.tar.xz)
|
||||
# Make sure we don't run two instances of viewer_manifest.py at the same time.
|
||||
add_dependencies(llpackage copy_l_viewer_manifest)
|
||||
check_message_template(llpackage)
|
||||
|
|
@ -2708,7 +2714,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
|
|||
# OUTPUT_VARIABLE PARENT_DIRECTORY_CYGWIN
|
||||
# OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
# add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
|
||||
# # Use of 'tar ...j' here assumes VIEWER_SYMBOL_FILE endswith .tar.bz2;
|
||||
# # Use of 'tar ...j' here assumes VIEWER_SYMBOL_FILE endswith .tar.xz;
|
||||
# # testing a string suffix is painful enough in CMake language that
|
||||
# # we'll continue assuming it until forced to generalize.
|
||||
# COMMAND "tar"
|
||||
|
|
|
|||
|
|
@ -717,7 +717,7 @@ void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
|
|||
clipDist = clipDist * 0.95 + 0.05;
|
||||
clipDist = clamp(clipDist * falloffMult, 0, 1);
|
||||
w = clamp(w * falloffMult * clipDist, 0, 1);
|
||||
|
||||
w = mix(0, w, clamp(glossiness - 0.75, 0, 1) * 4); // We only generate a quarter of the mips for the hero probes. Linearly interpolate between normal probes and hero probes based upon glossiness.
|
||||
glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,11 @@ WLSkyDetail 1 96
|
|||
RenderFSAASamples 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 256
|
||||
RenderHeroProbeDistance 1 4
|
||||
RenderHeroProbeUpdateRate 1 4
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -138,6 +143,11 @@ WLSkyDetail 1 96
|
|||
RenderFSAASamples 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 256
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 3
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -169,6 +179,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 1
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 3
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -200,6 +215,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 2
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 2
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 8
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -231,6 +251,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 1024
|
||||
RenderHeroProbeDistance 1 8
|
||||
RenderHeroProbeUpdateRate 1 2
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 8
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (deferred + SSAO + all shadows)
|
||||
|
|
@ -262,6 +287,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 1024
|
||||
RenderHeroProbeDistance 1 16
|
||||
RenderHeroProbeUpdateRate 1 1
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 4
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -293,6 +323,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 1
|
||||
RenderHeroProbeResolution 1 2048
|
||||
RenderHeroProbeDistance 1 16
|
||||
RenderHeroProbeUpdateRate 1 1
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 4
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -301,6 +336,7 @@ list Unknown
|
|||
RenderShadowDetail 1 0
|
||||
RenderDeferredSSAO 1 0
|
||||
RenderUseAdvancedAtmospherics 1 0
|
||||
RenderMirrors 1 0
|
||||
|
||||
//
|
||||
// VRAM > 512MB
|
||||
|
|
@ -322,6 +358,7 @@ RenderTransparentWater 1 0
|
|||
RenderDeferredSSAO 0 0
|
||||
RenderShadowDetail 0 0
|
||||
RenderReflectionProbeDetail 0 -1
|
||||
RenderMirrors 0 0
|
||||
|
||||
list Intel
|
||||
RenderAnisotropic 1 0
|
||||
|
|
@ -336,6 +373,7 @@ list GL3
|
|||
RenderFSAASamples 0 0
|
||||
RenderReflectionsEnabled 0 0
|
||||
RenderReflectionProbeDetail 0 0
|
||||
RenderMirrors 0 0
|
||||
|
||||
list TexUnit16orLess
|
||||
RenderTerrainPBRDetail 1 -1
|
||||
|
|
|
|||
|
|
@ -107,6 +107,11 @@ WLSkyDetail 1 96
|
|||
RenderFSAASamples 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 256
|
||||
RenderHeroProbeDistance 1 4
|
||||
RenderHeroProbeUpdateRate 1 4
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -138,6 +143,11 @@ WLSkyDetail 1 96
|
|||
RenderFSAASamples 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 256
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 3
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -169,6 +179,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 1
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 3
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -200,6 +215,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 2
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 2
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 8
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -231,6 +251,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 1024
|
||||
RenderHeroProbeDistance 1 8
|
||||
RenderHeroProbeUpdateRate 1 2
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 8
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (deferred + SSAO + all shadows)
|
||||
|
|
@ -262,6 +287,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 1024
|
||||
RenderHeroProbeDistance 1 16
|
||||
RenderHeroProbeUpdateRate 1 1
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 4
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -293,6 +323,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 1
|
||||
RenderHeroProbeResolution 1 2048
|
||||
RenderHeroProbeDistance 1 16
|
||||
RenderHeroProbeUpdateRate 1 1
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 4
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -301,6 +336,7 @@ list Unknown
|
|||
RenderShadowDetail 1 0
|
||||
RenderDeferredSSAO 1 0
|
||||
RenderUseAdvancedAtmospherics 1 0
|
||||
RenderMirrors 1 0
|
||||
|
||||
//
|
||||
// VRAM > 512MB
|
||||
|
|
@ -322,6 +358,7 @@ RenderTransparentWater 1 0
|
|||
RenderDeferredSSAO 0 0
|
||||
RenderShadowDetail 0 0
|
||||
RenderReflectionProbeDetail 0 -1
|
||||
RenderMirrors 0 0
|
||||
|
||||
list Intel
|
||||
RenderAnisotropic 1 0
|
||||
|
|
@ -342,6 +379,7 @@ list GL3
|
|||
RenderFSAASamples 0 0
|
||||
RenderReflectionsEnabled 0 0
|
||||
RenderReflectionProbeDetail 0 0
|
||||
RenderMirrors 0 0
|
||||
RenderGLMultiThreadedTextures 0 0
|
||||
|
||||
list TexUnit16orLess
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 256
|
||||
RenderHeroProbeDistance 1 4
|
||||
RenderHeroProbeUpdateRate 1 4
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium Low Graphics Settings
|
||||
|
|
@ -136,6 +141,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 256
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 3
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium Graphics Settings (standard)
|
||||
|
|
@ -167,6 +177,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 3
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 16
|
||||
|
||||
//
|
||||
// Medium High Graphics Settings
|
||||
|
|
@ -198,6 +213,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 0
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 0
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 512
|
||||
RenderHeroProbeDistance 1 6
|
||||
RenderHeroProbeUpdateRate 1 2
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 8
|
||||
|
||||
//
|
||||
// High Graphics Settings (SSAO + sun shadows)
|
||||
|
|
@ -229,6 +249,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 1
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 1024
|
||||
RenderHeroProbeDistance 1 8
|
||||
RenderHeroProbeUpdateRate 1 2
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 8
|
||||
|
||||
//
|
||||
// High Ultra Graphics Settings (SSAO + all shadows)
|
||||
|
|
@ -260,6 +285,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 2
|
||||
RenderMirrors 1 0
|
||||
RenderHeroProbeResolution 1 1024
|
||||
RenderHeroProbeDistance 1 16
|
||||
RenderHeroProbeUpdateRate 1 1
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 4
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -291,6 +321,11 @@ RenderReflectionsEnabled 1 1
|
|||
RenderReflectionProbeDetail 1 1
|
||||
RenderScreenSpaceReflections 1 0
|
||||
RenderReflectionProbeLevel 1 3
|
||||
RenderMirrors 1 1
|
||||
RenderHeroProbeResolution 1 2048
|
||||
RenderHeroProbeDistance 1 16
|
||||
RenderHeroProbeUpdateRate 1 1
|
||||
RenderHeroProbeConservativeUpdateMultiplier 1 4
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -299,6 +334,7 @@ list Unknown
|
|||
RenderShadowDetail 1 0
|
||||
RenderDeferredSSAO 1 0
|
||||
RenderUseAdvancedAtmospherics 1 0
|
||||
RenderMirrors 1 0
|
||||
|
||||
|
||||
//
|
||||
|
|
@ -320,6 +356,7 @@ RenderTerrainDetail 1 0
|
|||
RenderDeferredSSAO 0 0
|
||||
RenderUseAdvancedAtmospherics 0 0
|
||||
RenderShadowDetail 0 0
|
||||
RenderMirrors 0 0
|
||||
|
||||
list TexUnit8orLess
|
||||
RenderDeferredSSAO 0 0
|
||||
|
|
@ -338,3 +375,4 @@ list GL3
|
|||
RenderFSAASamples 0 0
|
||||
RenderReflectionProbeDetail 0 0
|
||||
RenderReflectionsEnabled 0 0
|
||||
RenderMirrors 0 0
|
||||
|
|
|
|||
|
|
@ -792,7 +792,7 @@ BOOL FSPanelFace::postBuild()
|
|||
|
||||
// PBR Base Material swatch
|
||||
// mMaterialCtrlPBR->setDefaultImageAssetID(LLUUID::null); // we have no default material, and null is standard for LLUUID -Zi
|
||||
mMaterialCtrlPBR->setBlankImageAssetID(LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID);
|
||||
mMaterialCtrlPBR->setBlankImageAssetID(BLANK_MATERIAL_ASSET_ID);
|
||||
mMaterialCtrlPBR->setCommitCallback(boost::bind(&FSPanelFace::onCommitPbr, this));
|
||||
mMaterialCtrlPBR->setOnCancelCallback(boost::bind(&FSPanelFace::onCancelPbr, this));
|
||||
mMaterialCtrlPBR->setOnSelectCallback(boost::bind(&FSPanelFace::onSelectPbr, this));
|
||||
|
|
@ -2406,7 +2406,7 @@ void FSPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material,
|
|||
{
|
||||
mVOInventoryListener = nullptr;
|
||||
}
|
||||
if (!func.mIdenticalMaterial || func.mMaterialId.isNull() || func.mMaterialId == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID)
|
||||
if (!func.mIdenticalMaterial || func.mMaterialId.isNull() || func.mMaterialId == BLANK_MATERIAL_ASSET_ID)
|
||||
{
|
||||
mAgentInventoryListener = nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,211 @@
|
|||
/**
|
||||
* @file asset.cpp
|
||||
* @brief LL GLTF Implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "../llviewerprecompiledheaders.h"
|
||||
|
||||
#include "asset.h"
|
||||
#include "llvolumeoctree.h"
|
||||
|
||||
using namespace LL::GLTF;
|
||||
|
||||
void Scene::updateTransforms(Asset& asset)
|
||||
{
|
||||
LLMatrix4a identity;
|
||||
identity.setIdentity();
|
||||
for (auto& nodeIndex : mNodes)
|
||||
{
|
||||
Node& node = asset.mNodes[nodeIndex];
|
||||
node.updateTransforms(asset, identity);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview)
|
||||
{
|
||||
for (auto& nodeIndex : mNodes)
|
||||
{
|
||||
Node& node = asset.mNodes[nodeIndex];
|
||||
node.updateRenderTransforms(asset, modelview);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview)
|
||||
{
|
||||
matMul(mMatrix, modelview, mRenderMatrix);
|
||||
|
||||
for (auto& childIndex : mChildren)
|
||||
{
|
||||
Node& child = asset.mNodes[childIndex];
|
||||
child.updateRenderTransforms(asset, mRenderMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
LLMatrix4a inverse(const LLMatrix4a& mat);
|
||||
|
||||
void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix)
|
||||
{
|
||||
matMul(mMatrix, parentMatrix, mAssetMatrix);
|
||||
mAssetMatrixInv = inverse(mAssetMatrix);
|
||||
|
||||
for (auto& childIndex : mChildren)
|
||||
{
|
||||
Node& child = asset.mNodes[childIndex];
|
||||
child.updateTransforms(asset, mAssetMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::updateTransforms()
|
||||
{
|
||||
for (auto& scene : mScenes)
|
||||
{
|
||||
scene.updateTransforms(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::updateRenderTransforms(const LLMatrix4a& modelview)
|
||||
{
|
||||
#if 0
|
||||
// traverse hierarchy and update render transforms from scratch
|
||||
for (auto& scene : mScenes)
|
||||
{
|
||||
scene.updateRenderTransforms(*this, modelview);
|
||||
}
|
||||
#else
|
||||
// use mAssetMatrix to update render transforms from node list
|
||||
for (auto& node : mNodes)
|
||||
{
|
||||
if (node.mMesh != INVALID_INDEX)
|
||||
{
|
||||
matMul(node.mAssetMatrix, modelview, node.mRenderMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
LLVector4a* intersection, // return the intersection point
|
||||
LLVector2* tex_coord, // return the texture coordinates of the intersection point
|
||||
LLVector4a* normal, // return the surface normal at the intersection point
|
||||
LLVector4a* tangent, // return the surface tangent at the intersection point
|
||||
S32* primitive_hitp
|
||||
)
|
||||
{
|
||||
S32 node_hit = -1;
|
||||
S32 primitive_hit = -1;
|
||||
|
||||
LLVector4a local_start;
|
||||
LLVector4a asset_end = end;
|
||||
LLVector4a local_end;
|
||||
LLVector4a p;
|
||||
|
||||
|
||||
for (auto& node : mNodes)
|
||||
{
|
||||
if (node.mMesh != INVALID_INDEX)
|
||||
{
|
||||
|
||||
bool newHit = false;
|
||||
|
||||
// transform start and end to this node's local space
|
||||
node.mAssetMatrixInv.affineTransform(start, local_start);
|
||||
node.mAssetMatrixInv.affineTransform(asset_end, local_end);
|
||||
|
||||
Mesh& mesh = mMeshes[node.mMesh];
|
||||
for (auto& primitive : mesh.mPrimitives)
|
||||
{
|
||||
const LLVolumeTriangle* tri = primitive.lineSegmentIntersect(local_start, local_end, &p, tex_coord, normal, tangent);
|
||||
if (tri)
|
||||
{
|
||||
newHit = true;
|
||||
local_end = p;
|
||||
|
||||
// pointer math to get the node index
|
||||
node_hit = &node - &mNodes[0];
|
||||
llassert(&mNodes[node_hit] == &node);
|
||||
|
||||
//pointer math to get the primitive index
|
||||
primitive_hit = &primitive - &mesh.mPrimitives[0];
|
||||
llassert(&mesh.mPrimitives[primitive_hit] == &primitive);
|
||||
}
|
||||
}
|
||||
|
||||
if (newHit)
|
||||
{
|
||||
// shorten line segment on hit
|
||||
node.mAssetMatrix.affineTransform(p, asset_end);
|
||||
|
||||
// transform results back to asset space
|
||||
if (intersection)
|
||||
{
|
||||
*intersection = asset_end;
|
||||
}
|
||||
|
||||
if (normal || tangent)
|
||||
{
|
||||
LLMatrix4 normalMatrix(node.mAssetMatrixInv.getF32ptr());
|
||||
|
||||
normalMatrix.transpose();
|
||||
|
||||
LLMatrix4a norm_mat;
|
||||
norm_mat.loadu((F32*)normalMatrix.mMatrix);
|
||||
|
||||
if (normal)
|
||||
{
|
||||
LLVector4a n = *normal;
|
||||
F32 w = n.getF32ptr()[3];
|
||||
n.getF32ptr()[3] = 0.0f;
|
||||
|
||||
norm_mat.affineTransform(n, *normal);
|
||||
normal->getF32ptr()[3] = w;
|
||||
}
|
||||
|
||||
if (tangent)
|
||||
{
|
||||
LLVector4a t = *tangent;
|
||||
F32 w = t.getF32ptr()[3];
|
||||
t.getF32ptr()[3] = 0.0f;
|
||||
|
||||
norm_mat.affineTransform(t, *tangent);
|
||||
tangent->getF32ptr()[3] = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node_hit != -1)
|
||||
{
|
||||
if (primitive_hitp)
|
||||
{
|
||||
*primitive_hitp = primitive_hit;
|
||||
}
|
||||
}
|
||||
|
||||
return node_hit;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,445 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file asset.h
|
||||
* @brief LL GLTF Implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "llvertexbuffer.h"
|
||||
#include "llvolumeoctree.h"
|
||||
#include "../lltinygltfhelper.h"
|
||||
#include "primitive.h"
|
||||
|
||||
// LL GLTF Implementation
|
||||
namespace LL
|
||||
{
|
||||
namespace GLTF
|
||||
{
|
||||
constexpr S32 INVALID_INDEX = -1;
|
||||
|
||||
class Asset;
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
std::vector<U8> mData;
|
||||
std::string mName;
|
||||
std::string mUri;
|
||||
|
||||
const Buffer& operator=(const tinygltf::Buffer& src)
|
||||
{
|
||||
mData = src.data;
|
||||
mName = src.name;
|
||||
mUri = src.uri;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class BufferView
|
||||
{
|
||||
public:
|
||||
S32 mBuffer = INVALID_INDEX;
|
||||
S32 mByteLength;
|
||||
S32 mByteOffset;
|
||||
S32 mByteStride;
|
||||
S32 mTarget;
|
||||
S32 mComponentType;
|
||||
|
||||
std::string mName;
|
||||
|
||||
const BufferView& operator=(const tinygltf::BufferView& src)
|
||||
{
|
||||
mBuffer = src.buffer;
|
||||
mByteLength = src.byteLength;
|
||||
mByteOffset = src.byteOffset;
|
||||
mByteStride = src.byteStride;
|
||||
mTarget = src.target;
|
||||
mName = src.name;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class Accessor
|
||||
{
|
||||
public:
|
||||
S32 mBufferView = INVALID_INDEX;
|
||||
S32 mByteOffset;
|
||||
S32 mComponentType;
|
||||
S32 mCount;
|
||||
std::vector<double> mMax;
|
||||
std::vector<double> mMin;
|
||||
S32 mType;
|
||||
bool mNormalized;
|
||||
std::string mName;
|
||||
|
||||
const Accessor& operator=(const tinygltf::Accessor& src)
|
||||
{
|
||||
mBufferView = src.bufferView;
|
||||
mByteOffset = src.byteOffset;
|
||||
mComponentType = src.componentType;
|
||||
mCount = src.count;
|
||||
mType = src.type;
|
||||
mNormalized = src.normalized;
|
||||
mName = src.name;
|
||||
mMax = src.maxValues;
|
||||
mMin = src.maxValues;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
// use LLFetchedGLTFMaterial for now, but eventually we'll want to use
|
||||
// a more flexible GLTF material implementation instead of the fixed packing
|
||||
// version we use for sharable GLTF material assets
|
||||
LLPointer<LLFetchedGLTFMaterial> mMaterial;
|
||||
std::string mName;
|
||||
|
||||
const Material& operator=(const tinygltf::Material& src)
|
||||
{
|
||||
mName = src.name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void allocateGLResources(Asset& asset)
|
||||
{
|
||||
// allocate material
|
||||
mMaterial = new LLFetchedGLTFMaterial();
|
||||
}
|
||||
};
|
||||
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
std::vector<Primitive> mPrimitives;
|
||||
std::vector<double> mWeights;
|
||||
std::string mName;
|
||||
|
||||
const Mesh& operator=(const tinygltf::Mesh& src)
|
||||
{
|
||||
mPrimitives.resize(src.primitives.size());
|
||||
for (U32 i = 0; i < src.primitives.size(); ++i)
|
||||
{
|
||||
mPrimitives[i] = src.primitives[i];
|
||||
}
|
||||
|
||||
mWeights = src.weights;
|
||||
mName = src.name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void allocateGLResources(Asset& asset)
|
||||
{
|
||||
for (auto& primitive : mPrimitives)
|
||||
{
|
||||
primitive.allocateGLResources(asset);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
LLMatrix4a mMatrix; //local transform
|
||||
LLMatrix4a mRenderMatrix; //transform for rendering
|
||||
LLMatrix4a mAssetMatrix; //transform from local to asset space
|
||||
LLMatrix4a mAssetMatrixInv; //transform from asset to local space
|
||||
|
||||
std::vector<S32> mChildren;
|
||||
S32 mMesh = INVALID_INDEX;
|
||||
std::string mName;
|
||||
|
||||
const Node& operator=(const tinygltf::Node& src)
|
||||
{
|
||||
F32* dstMatrix = mMatrix.getF32ptr();
|
||||
|
||||
if (src.matrix.size() != 16)
|
||||
{
|
||||
mMatrix.setIdentity();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (U32 i = 0; i < 16; ++i)
|
||||
{
|
||||
dstMatrix[i] = (F32)src.matrix[i];
|
||||
}
|
||||
}
|
||||
|
||||
mChildren = src.children;
|
||||
mMesh = src.mesh;
|
||||
mName = src.name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set mRenderMatrix to a transform that can be used for the current render pass
|
||||
// modelview -- parent's render matrix
|
||||
void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview);
|
||||
|
||||
// update mAssetMatrix and mAssetMatrixInv
|
||||
void updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix);
|
||||
|
||||
};
|
||||
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
std::vector<S32> mNodes;
|
||||
std::string mName;
|
||||
|
||||
const Scene& operator=(const tinygltf::Scene& src)
|
||||
{
|
||||
mNodes = src.nodes;
|
||||
mName = src.name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void updateTransforms(Asset& asset);
|
||||
void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview);
|
||||
|
||||
};
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
S32 mSampler = INVALID_INDEX;
|
||||
S32 mSource = INVALID_INDEX;
|
||||
std::string mName;
|
||||
|
||||
const Texture& operator=(const tinygltf::Texture& src)
|
||||
{
|
||||
mSampler = src.sampler;
|
||||
mSource = src.source;
|
||||
mName = src.name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class Sampler
|
||||
{
|
||||
public:
|
||||
S32 mMagFilter;
|
||||
S32 mMinFilter;
|
||||
S32 mWrapS;
|
||||
S32 mWrapT;
|
||||
std::string mName;
|
||||
|
||||
const Sampler& operator=(const tinygltf::Sampler& src)
|
||||
{
|
||||
mMagFilter = src.magFilter;
|
||||
mMinFilter = src.minFilter;
|
||||
mWrapS = src.wrapS;
|
||||
mWrapT = src.wrapT;
|
||||
mName = src.name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class Image
|
||||
{
|
||||
public:
|
||||
std::string mName;
|
||||
std::string mUri;
|
||||
std::string mMimeType;
|
||||
std::vector<U8> mData;
|
||||
S32 mWidth;
|
||||
S32 mHeight;
|
||||
S32 mComponent;
|
||||
S32 mBits;
|
||||
LLPointer<LLViewerFetchedTexture> mTexture;
|
||||
|
||||
const Image& operator=(const tinygltf::Image& src)
|
||||
{
|
||||
mName = src.name;
|
||||
mUri = src.uri;
|
||||
mMimeType = src.mimeType;
|
||||
mData = src.image;
|
||||
mWidth = src.width;
|
||||
mHeight = src.height;
|
||||
mComponent = src.component;
|
||||
mBits = src.bits;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void allocateGLResources()
|
||||
{
|
||||
// allocate texture
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// C++ representation of a GLTF Asset
|
||||
class Asset : public LLRefCount
|
||||
{
|
||||
public:
|
||||
std::vector<Scene> mScenes;
|
||||
std::vector<Node> mNodes;
|
||||
std::vector<Mesh> mMeshes;
|
||||
std::vector<Material> mMaterials;
|
||||
std::vector<Buffer> mBuffers;
|
||||
std::vector<BufferView> mBufferViews;
|
||||
std::vector<Texture> mTextures;
|
||||
std::vector<Sampler> mSamplers;
|
||||
std::vector<Image> mImages;
|
||||
std::vector<Accessor> mAccessors;
|
||||
|
||||
void allocateGLResources(const std::string& filename, const tinygltf::Model& model)
|
||||
{
|
||||
for (auto& mesh : mMeshes)
|
||||
{
|
||||
mesh.allocateGLResources(*this);
|
||||
}
|
||||
|
||||
for (auto& image : mImages)
|
||||
{
|
||||
image.allocateGLResources();
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < mMaterials.size(); ++i)
|
||||
{
|
||||
mMaterials[i].allocateGLResources(*this);
|
||||
LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true);
|
||||
}
|
||||
}
|
||||
|
||||
// update asset-to-node and node-to-asset transforms
|
||||
void updateTransforms();
|
||||
|
||||
// update node render transforms
|
||||
void updateRenderTransforms(const LLMatrix4a& modelview);
|
||||
|
||||
void renderOpaque()
|
||||
{
|
||||
for (auto& node : mNodes)
|
||||
{
|
||||
if (node.mMesh != INVALID_INDEX)
|
||||
{
|
||||
Mesh& mesh = mMeshes[node.mMesh];
|
||||
for (auto& primitive : mesh.mPrimitives)
|
||||
{
|
||||
gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix);
|
||||
if (primitive.mMaterial != INVALID_INDEX)
|
||||
{
|
||||
Material& material = mMaterials[primitive.mMaterial];
|
||||
material.mMaterial->bind();
|
||||
}
|
||||
primitive.mVertexBuffer->setBuffer();
|
||||
if (primitive.mVertexBuffer->getNumIndices() > 0)
|
||||
{
|
||||
primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the index of the node that the line segment intersects with, or -1 if no hit
|
||||
// input and output values must be in this asset's local coordinate frame
|
||||
S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
LLVector4a* intersection = nullptr, // return the intersection point
|
||||
LLVector2* tex_coord = nullptr, // return the texture coordinates of the intersection point
|
||||
LLVector4a* normal = nullptr, // return the surface normal at the intersection point
|
||||
LLVector4a* tangent = nullptr, // return the surface tangent at the intersection point
|
||||
S32* primitive_hitp = nullptr // return the index of the primitive that was hit
|
||||
);
|
||||
|
||||
const Asset& operator=(const tinygltf::Model& src)
|
||||
{
|
||||
mScenes.resize(src.scenes.size());
|
||||
for (U32 i = 0; i < src.scenes.size(); ++i)
|
||||
{
|
||||
mScenes[i] = src.scenes[i];
|
||||
}
|
||||
|
||||
mNodes.resize(src.nodes.size());
|
||||
for (U32 i = 0; i < src.nodes.size(); ++i)
|
||||
{
|
||||
mNodes[i] = src.nodes[i];
|
||||
}
|
||||
|
||||
mMeshes.resize(src.meshes.size());
|
||||
for (U32 i = 0; i < src.meshes.size(); ++i)
|
||||
{
|
||||
mMeshes[i] = src.meshes[i];
|
||||
}
|
||||
|
||||
mMaterials.resize(src.materials.size());
|
||||
for (U32 i = 0; i < src.materials.size(); ++i)
|
||||
{
|
||||
mMaterials[i] = src.materials[i];
|
||||
}
|
||||
|
||||
mBuffers.resize(src.buffers.size());
|
||||
for (U32 i = 0; i < src.buffers.size(); ++i)
|
||||
{
|
||||
mBuffers[i] = src.buffers[i];
|
||||
}
|
||||
|
||||
mBufferViews.resize(src.bufferViews.size());
|
||||
for (U32 i = 0; i < src.bufferViews.size(); ++i)
|
||||
{
|
||||
mBufferViews[i] = src.bufferViews[i];
|
||||
}
|
||||
|
||||
mTextures.resize(src.textures.size());
|
||||
for (U32 i = 0; i < src.textures.size(); ++i)
|
||||
{
|
||||
mTextures[i] = src.textures[i];
|
||||
}
|
||||
|
||||
mSamplers.resize(src.samplers.size());
|
||||
for (U32 i = 0; i < src.samplers.size(); ++i)
|
||||
{
|
||||
mSamplers[i] = src.samplers[i];
|
||||
}
|
||||
|
||||
mImages.resize(src.images.size());
|
||||
for (U32 i = 0; i < src.images.size(); ++i)
|
||||
{
|
||||
mImages[i] = src.images[i];
|
||||
}
|
||||
|
||||
mAccessors.resize(src.accessors.size());
|
||||
for (U32 i = 0; i < src.accessors.size(); ++i)
|
||||
{
|
||||
mAccessors[i] = src.accessors[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,484 @@
|
|||
/**
|
||||
* @file primitive.cpp
|
||||
* @brief LL GLTF Implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "../llviewerprecompiledheaders.h"
|
||||
|
||||
#include "asset.h"
|
||||
#include "../lltinygltfhelper.h"
|
||||
|
||||
using namespace LL::GLTF;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define LL_FUNCSIG __FUNCSIG__
|
||||
#else
|
||||
#define LL_FUNCSIG __PRETTY_FUNCTION__
|
||||
#endif
|
||||
|
||||
// copy one vec3 from src to dst
|
||||
template<class S, class T>
|
||||
void copyVec2(S* src, T& dst)
|
||||
{
|
||||
LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL;
|
||||
}
|
||||
|
||||
// copy one vec3 from src to dst
|
||||
template<class S, class T>
|
||||
void copyVec3(S* src, T& dst)
|
||||
{
|
||||
LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL;
|
||||
}
|
||||
|
||||
// copy one vec4 from src to dst
|
||||
template<class S, class T>
|
||||
void copyVec4(S* src, T& dst)
|
||||
{
|
||||
LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL;
|
||||
}
|
||||
|
||||
template<>
|
||||
void copyVec2<F32, LLVector2>(F32* src, LLVector2& dst)
|
||||
{
|
||||
dst.set(src[0], src[1]);
|
||||
}
|
||||
|
||||
template<>
|
||||
void copyVec3<F32, LLVector4a>(F32* src, LLVector4a& dst)
|
||||
{
|
||||
dst.load3(src);
|
||||
}
|
||||
|
||||
template<>
|
||||
void copyVec3<U16, LLColor4U>(U16* src, LLColor4U& dst)
|
||||
{
|
||||
dst.set(src[0], src[1], src[2], 255);
|
||||
}
|
||||
|
||||
template<>
|
||||
void copyVec4<F32, LLVector4a>(F32* src, LLVector4a& dst)
|
||||
{
|
||||
dst.loadua(src);
|
||||
}
|
||||
|
||||
// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy
|
||||
template<class S, class T>
|
||||
void copyVec2(S* src, LLStrider<T> dst, S32 stride, S32 count)
|
||||
{
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
copyVec2(src, *dst);
|
||||
dst++;
|
||||
src = (S*)((U8*)src + stride);
|
||||
}
|
||||
}
|
||||
|
||||
// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy
|
||||
template<class S, class T>
|
||||
void copyVec3(S* src, LLStrider<T> dst, S32 stride, S32 count)
|
||||
{
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
copyVec3(src, *dst);
|
||||
dst++;
|
||||
src = (S*)((U8*)src + stride);
|
||||
}
|
||||
}
|
||||
|
||||
// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy
|
||||
template<class S, class T>
|
||||
void copyVec4(S* src, LLStrider<T> dst, S32 stride, S32 count)
|
||||
{
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
copyVec3(src, *dst);
|
||||
dst++;
|
||||
src = (S*)((U8*)src + stride);
|
||||
}
|
||||
}
|
||||
|
||||
template<class S, class T>
|
||||
void copyAttributeArray(Asset& asset, const Accessor& accessor, const S* src, LLStrider<T>& dst, S32 byteStride)
|
||||
{
|
||||
if (accessor.mType == TINYGLTF_TYPE_VEC2)
|
||||
{
|
||||
S32 stride = byteStride == 0 ? sizeof(S) * 2 : byteStride;
|
||||
copyVec2((S*)src, dst, stride, accessor.mCount);
|
||||
}
|
||||
else if (accessor.mType == TINYGLTF_TYPE_VEC3)
|
||||
{
|
||||
S32 stride = byteStride == 0 ? sizeof(S) * 3 : byteStride;
|
||||
copyVec3((S*)src, dst, stride, accessor.mCount);
|
||||
}
|
||||
else if (accessor.mType == TINYGLTF_TYPE_VEC4)
|
||||
{
|
||||
S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride;
|
||||
copyVec4((S*)src, dst, stride, accessor.mCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider<T>& dst)
|
||||
{
|
||||
const Accessor& accessor = asset.mAccessors[accessorIdx];
|
||||
const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView];
|
||||
const Buffer& buffer = asset.mBuffers[bufferView.mBuffer];
|
||||
const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset;
|
||||
|
||||
if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_FLOAT)
|
||||
{
|
||||
copyAttributeArray(asset, accessor, (const F32*)src, dst, bufferView.mByteStride);
|
||||
}
|
||||
else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
|
||||
{
|
||||
copyAttributeArray(asset, accessor, (const U16*)src, dst, bufferView.mByteStride);
|
||||
}
|
||||
else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
|
||||
{
|
||||
copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride);
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
LL_ERRS() << "Unsupported component type" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void Primitive::allocateGLResources(Asset& asset)
|
||||
{
|
||||
// allocate vertex buffer
|
||||
// We diverge from the intent of the GLTF format here to work with our existing render pipeline
|
||||
// GLTF wants us to copy the buffer views into GPU storage as is and build render commands that source that data.
|
||||
// For our engine, though, it's better to rearrange the buffers at load time into a layout that's more consistent.
|
||||
// The GLTF native approach undoubtedly works well if you can count on VAOs, but VAOs perform much worse with our scenes.
|
||||
|
||||
// get the number of vertices
|
||||
U32 numVertices = 0;
|
||||
for (auto& it : mAttributes)
|
||||
{
|
||||
const Accessor& accessor = asset.mAccessors[it.second];
|
||||
numVertices = accessor.mCount;
|
||||
break;
|
||||
}
|
||||
|
||||
// get the number of indices
|
||||
U32 numIndices = 0;
|
||||
if (mIndices != INVALID_INDEX)
|
||||
{
|
||||
const Accessor& accessor = asset.mAccessors[mIndices];
|
||||
numIndices = accessor.mCount;
|
||||
}
|
||||
|
||||
// create vertex buffer
|
||||
mVertexBuffer = new LLVertexBuffer(ATTRIBUTE_MASK);
|
||||
mVertexBuffer->allocateBuffer(numVertices, numIndices);
|
||||
|
||||
bool needs_color = true;
|
||||
bool needs_texcoord = true;
|
||||
bool needs_normal = true;
|
||||
bool needs_tangent = true;
|
||||
|
||||
// load vertex data
|
||||
for (auto& it : mAttributes)
|
||||
{
|
||||
const std::string& attribName = it.first;
|
||||
|
||||
// load vertex data
|
||||
if (attribName == "POSITION")
|
||||
{
|
||||
// load position data
|
||||
LLStrider<LLVector4a> dst;
|
||||
mVertexBuffer->getVertexStrider(dst);
|
||||
|
||||
copyAttribute(asset, it.second, dst);
|
||||
}
|
||||
else if (attribName == "NORMAL")
|
||||
{
|
||||
needs_normal = false;
|
||||
// load normal data
|
||||
LLStrider<LLVector4a> dst;
|
||||
mVertexBuffer->getNormalStrider(dst);
|
||||
|
||||
copyAttribute(asset, it.second, dst);
|
||||
}
|
||||
else if (attribName == "TANGENT")
|
||||
{
|
||||
needs_tangent = false;
|
||||
// load tangent data
|
||||
|
||||
LLStrider<LLVector4a> dst;
|
||||
mVertexBuffer->getTangentStrider(dst);
|
||||
|
||||
copyAttribute(asset, it.second, dst);
|
||||
}
|
||||
else if (attribName == "COLOR_0")
|
||||
{
|
||||
needs_color = false;
|
||||
// load color data
|
||||
|
||||
LLStrider<LLColor4U> dst;
|
||||
mVertexBuffer->getColorStrider(dst);
|
||||
|
||||
copyAttribute(asset, it.second, dst);
|
||||
}
|
||||
else if (attribName == "TEXCOORD_0")
|
||||
{
|
||||
needs_texcoord = false;
|
||||
// load texcoord data
|
||||
LLStrider<LLVector2> dst;
|
||||
mVertexBuffer->getTexCoord0Strider(dst);
|
||||
|
||||
LLStrider<LLVector2> tc = dst;
|
||||
copyAttribute(asset, it.second, dst);
|
||||
|
||||
// convert to OpenGL coordinate space
|
||||
for (U32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
tc->mV[1] = 1.0f - tc->mV[1];;
|
||||
tc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy index buffer
|
||||
if (mIndices != INVALID_INDEX)
|
||||
{
|
||||
const Accessor& accessor = asset.mAccessors[mIndices];
|
||||
const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView];
|
||||
const Buffer& buffer = asset.mBuffers[bufferView.mBuffer];
|
||||
|
||||
const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset;
|
||||
|
||||
LLStrider<U16> dst;
|
||||
mVertexBuffer->getIndexStrider(dst);
|
||||
mIndexArray.resize(numIndices);
|
||||
|
||||
if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
|
||||
{
|
||||
for (U32 i = 0; i < numIndices; ++i)
|
||||
{
|
||||
*(dst++) = (U16) * (U32*)src;
|
||||
src += sizeof(U32);
|
||||
}
|
||||
}
|
||||
else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
|
||||
{
|
||||
for (U32 i = 0; i < numIndices; ++i)
|
||||
{
|
||||
*(dst++) = *(U16*)src;
|
||||
src += sizeof(U16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL;
|
||||
}
|
||||
|
||||
U16* idx = (U16*)mVertexBuffer->getMappedIndices();
|
||||
for (U32 i = 0; i < numIndices; ++i)
|
||||
{
|
||||
mIndexArray[i] = idx[i];
|
||||
}
|
||||
}
|
||||
|
||||
// fill in default values for missing attributes
|
||||
if (needs_color)
|
||||
{ // set default color
|
||||
LLStrider<LLColor4U> dst;
|
||||
mVertexBuffer->getColorStrider(dst);
|
||||
for (U32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
*(dst++) = LLColor4U(255, 255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_texcoord)
|
||||
{ // set default texcoord
|
||||
LLStrider<LLVector2> dst;
|
||||
mVertexBuffer->getTexCoord0Strider(dst);
|
||||
for (U32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
*(dst++) = LLVector2(0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_normal)
|
||||
{ // set default normal
|
||||
LLStrider<LLVector4a> dst;
|
||||
mVertexBuffer->getNormalStrider(dst);
|
||||
for (U32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
*(dst++) = LLVector4a(0.0f, 0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_tangent)
|
||||
{ // TODO: generate tangents if needed
|
||||
LLStrider<LLVector4a> dst;
|
||||
mVertexBuffer->getTangentStrider(dst);
|
||||
for (U32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
*(dst++) = LLVector4a(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
mPositions.resize(numVertices);
|
||||
mTexCoords.resize(numVertices);
|
||||
mNormals.resize(numVertices);
|
||||
mTangents.resize(numVertices);
|
||||
|
||||
LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
|
||||
LLVector2* tc = (LLVector2*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TEXCOORD0));
|
||||
LLVector4a* norm = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_NORMAL));
|
||||
LLVector4a* tangent = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TANGENT));
|
||||
for (U32 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
mPositions[i] = pos[i];
|
||||
mTexCoords[i] = tc[i];
|
||||
mNormals[i] = norm[i];
|
||||
mTangents[i] = tangent[i];
|
||||
}
|
||||
createOctree();
|
||||
|
||||
mVertexBuffer->unmapBuffer();
|
||||
}
|
||||
|
||||
void Primitive::createOctree()
|
||||
{
|
||||
// create octree
|
||||
mOctree = new LLVolumeOctree();
|
||||
|
||||
if (mMode == TINYGLTF_MODE_TRIANGLES)
|
||||
{
|
||||
F32 scaler = 0.25f;
|
||||
|
||||
const U32 num_triangles = mVertexBuffer->getNumIndices() / 3;
|
||||
// Initialize all the triangles we need
|
||||
mOctreeTriangles.resize(num_triangles);
|
||||
|
||||
LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
|
||||
U16* indices = (U16*)mVertexBuffer->getMappedIndices();
|
||||
|
||||
for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index)
|
||||
{ //for each triangle
|
||||
const U32 index = triangle_index * 3;
|
||||
LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index];
|
||||
const LLVector4a& v0 = pos[indices[index]];
|
||||
const LLVector4a& v1 = pos[indices[index + 1]];
|
||||
const LLVector4a& v2 = pos[indices[index + 2]];
|
||||
|
||||
//store pointers to vertex data
|
||||
tri->mV[0] = &v0;
|
||||
tri->mV[1] = &v1;
|
||||
tri->mV[2] = &v2;
|
||||
|
||||
//store indices
|
||||
tri->mIndex[0] = indices[index];
|
||||
tri->mIndex[1] = indices[index + 1];
|
||||
tri->mIndex[2] = indices[index + 2];
|
||||
|
||||
//get minimum point
|
||||
LLVector4a min = v0;
|
||||
min.setMin(min, v1);
|
||||
min.setMin(min, v2);
|
||||
|
||||
//get maximum point
|
||||
LLVector4a max = v0;
|
||||
max.setMax(max, v1);
|
||||
max.setMax(max, v2);
|
||||
|
||||
//compute center
|
||||
LLVector4a center;
|
||||
center.setAdd(min, max);
|
||||
center.mul(0.5f);
|
||||
|
||||
tri->mPositionGroup = center;
|
||||
|
||||
//compute "radius"
|
||||
LLVector4a size;
|
||||
size.setSub(max, min);
|
||||
|
||||
tri->mRadius = size.getLength3().getF32() * scaler;
|
||||
|
||||
//insert
|
||||
mOctree->insert(tri);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS() << "Unsupported Primitive mode" << LL_ENDL;
|
||||
}
|
||||
|
||||
//remove unneeded octree layers
|
||||
while (!mOctree->balance()) {}
|
||||
|
||||
//calculate AABB for each node
|
||||
LLVolumeOctreeRebound rebound;
|
||||
rebound.traverse(mOctree);
|
||||
}
|
||||
|
||||
const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out)
|
||||
{
|
||||
if (mOctree.isNull())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LLVector4a dir;
|
||||
dir.setSub(end, start);
|
||||
|
||||
F32 closest_t = 2.f; // must be larger than 1
|
||||
|
||||
//create a proxy LLVolumeFace for the raycast
|
||||
LLVolumeFace face;
|
||||
face.mPositions = mPositions.data();
|
||||
face.mTexCoords = mTexCoords.data();
|
||||
face.mNormals = mNormals.data();
|
||||
face.mTangents = mTangents.data();
|
||||
face.mIndices = mIndexArray.data();
|
||||
|
||||
face.mNumIndices = mIndexArray.size();
|
||||
face.mNumVertices = mPositions.size();
|
||||
|
||||
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out);
|
||||
intersect.traverse(mOctree);
|
||||
|
||||
// null out proxy data so it doesn't get freed
|
||||
face.mPositions = face.mNormals = face.mTangents = nullptr;
|
||||
face.mIndices = nullptr;
|
||||
face.mTexCoords = nullptr;
|
||||
|
||||
return intersect.mHitTriangle;
|
||||
}
|
||||
|
||||
Primitive::~Primitive()
|
||||
{
|
||||
mOctree = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file primitive.h
|
||||
* @brief LL GLTF Implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "llvertexbuffer.h"
|
||||
#include "llvolumeoctree.h"
|
||||
|
||||
// LL GLTF Implementation
|
||||
namespace LL
|
||||
{
|
||||
namespace GLTF
|
||||
{
|
||||
class Asset;
|
||||
|
||||
constexpr U32 ATTRIBUTE_MASK =
|
||||
LLVertexBuffer::MAP_VERTEX |
|
||||
LLVertexBuffer::MAP_NORMAL |
|
||||
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||
LLVertexBuffer::MAP_TANGENT |
|
||||
LLVertexBuffer::MAP_COLOR;
|
||||
|
||||
class Primitive
|
||||
{
|
||||
public:
|
||||
~Primitive();
|
||||
|
||||
// GPU copy of mesh data
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
|
||||
// CPU copy of mesh data
|
||||
std::vector<LLVector2> mTexCoords;
|
||||
std::vector<LLVector4a> mNormals;
|
||||
std::vector<LLVector4a> mTangents;
|
||||
std::vector<LLVector4a> mPositions;
|
||||
std::vector<U16> mIndexArray;
|
||||
|
||||
// raycast acceleration structure
|
||||
LLPointer<LLVolumeOctree> mOctree;
|
||||
std::vector<LLVolumeTriangle> mOctreeTriangles;
|
||||
|
||||
S32 mMaterial = -1;
|
||||
U32 mMode = TINYGLTF_MODE_TRIANGLES; // default to triangles
|
||||
U32 mGLMode = LLRender::TRIANGLES;
|
||||
S32 mIndices = -1;
|
||||
std::unordered_map<std::string, int> mAttributes;
|
||||
|
||||
// copy the attribute in the given BufferView to the given destination
|
||||
// assumes destination has enough storage for the attribute
|
||||
template<class T>
|
||||
void copyAttribute(Asset& asset, S32 bufferViewIdx, LLStrider<T>& dst);
|
||||
|
||||
// create octree based on vertex buffer
|
||||
// must be called before buffer is unmapped and after buffer is populated with good data
|
||||
void createOctree();
|
||||
|
||||
//get the LLVolumeTriangle that intersects with the given line segment at the point
|
||||
//closest to start. Moves end to the point of intersection. Returns nullptr if no intersection.
|
||||
//Line segment must be in the same coordinate frame as this Primitive
|
||||
const LLVolumeTriangle* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
LLVector4a* intersection = NULL, // return the intersection point
|
||||
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
|
||||
LLVector4a* normal = NULL, // return the surface normal at the intersection point
|
||||
LLVector4a* tangent = NULL // return the surface tangent at the intersection point
|
||||
);
|
||||
|
||||
const Primitive& operator=(const tinygltf::Primitive& src)
|
||||
{
|
||||
// load material
|
||||
mMaterial = src.material;
|
||||
|
||||
// load mode
|
||||
mMode = src.mode;
|
||||
|
||||
// load indices
|
||||
mIndices = src.indices;
|
||||
|
||||
// load attributes
|
||||
for (auto& it : src.attributes)
|
||||
{
|
||||
mAttributes[it.first] = it.second;
|
||||
}
|
||||
|
||||
switch (mMode)
|
||||
{
|
||||
case TINYGLTF_MODE_POINTS:
|
||||
mGLMode = LLRender::POINTS;
|
||||
break;
|
||||
case TINYGLTF_MODE_LINE:
|
||||
mGLMode = LLRender::LINES;
|
||||
break;
|
||||
case TINYGLTF_MODE_LINE_LOOP:
|
||||
mGLMode = LLRender::LINE_LOOP;
|
||||
break;
|
||||
case TINYGLTF_MODE_LINE_STRIP:
|
||||
mGLMode = LLRender::LINE_STRIP;
|
||||
break;
|
||||
case TINYGLTF_MODE_TRIANGLES:
|
||||
mGLMode = LLRender::TRIANGLES;
|
||||
break;
|
||||
case TINYGLTF_MODE_TRIANGLE_STRIP:
|
||||
mGLMode = LLRender::TRIANGLE_STRIP;
|
||||
break;
|
||||
case TINYGLTF_MODE_TRIANGLE_FAN:
|
||||
mGLMode = LLRender::TRIANGLE_FAN;
|
||||
break;
|
||||
default:
|
||||
mGLMode = GL_TRIANGLES;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void allocateGLResources(Asset& asset);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,470 @@
|
|||
/**
|
||||
* @file gltfscenemanager.cpp
|
||||
* @brief Builds menus out of items.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "gltfscenemanager.h"
|
||||
#include "llviewermenufile.h"
|
||||
#include "llappviewer.h"
|
||||
#include "lltinygltfhelper.h"
|
||||
#include "llvertexbuffer.h"
|
||||
#include "llselectmgr.h"
|
||||
#include "llagent.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llvolumeoctree.h"
|
||||
#include "gltf/asset.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewershadermgr.h"
|
||||
|
||||
|
||||
using namespace LL;
|
||||
|
||||
// temporary location of LL GLTF Implementation
|
||||
using namespace LL::GLTF;
|
||||
|
||||
void GLTFSceneManager::load()
|
||||
{
|
||||
LLViewerObject* obj = LLSelectMgr::instance().getSelection()->getFirstRootObject();
|
||||
|
||||
if (obj)
|
||||
{
|
||||
// Load a scene from disk
|
||||
LLFilePickerReplyThread::startPicker(
|
||||
[](const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)
|
||||
{
|
||||
if (LLAppViewer::instance()->quitRequested())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (filenames.size() > 0)
|
||||
{
|
||||
GLTFSceneManager::instance().load(filenames[0]);
|
||||
}
|
||||
},
|
||||
LLFilePicker::FFLOAD_GLTF,
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("GLTFPreviewSelection");
|
||||
}
|
||||
}
|
||||
|
||||
void GLTFSceneManager::load(const std::string& filename)
|
||||
{
|
||||
tinygltf::Model model;
|
||||
LLTinyGLTFHelper::loadModel(filename, model);
|
||||
|
||||
LLPointer<Asset> asset = new Asset();
|
||||
*asset = model;
|
||||
|
||||
asset->allocateGLResources(filename, model);
|
||||
asset->updateTransforms();
|
||||
|
||||
// hang the asset off the currently selected object, or off of the avatar if no object is selected
|
||||
LLViewerObject* obj = LLSelectMgr::instance().getSelection()->getFirstRootObject();
|
||||
|
||||
if (obj)
|
||||
{ // assign to self avatar
|
||||
obj->mGLTFAsset = asset;
|
||||
mObjects.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
GLTFSceneManager::~GLTFSceneManager()
|
||||
{
|
||||
mObjects.clear();
|
||||
}
|
||||
|
||||
LLMatrix4a getAssetToAgentTransform(LLViewerObject* obj)
|
||||
{
|
||||
LLMatrix4 root;
|
||||
root.initScale(obj->getScale());
|
||||
root.rotate(obj->getRenderRotation());
|
||||
root.translate(obj->getPositionAgent());
|
||||
|
||||
LLMatrix4a mat;
|
||||
mat.loadu((F32*) root.mMatrix);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
LLMatrix4a getAgentToAssetTransform(LLViewerObject* obj)
|
||||
{
|
||||
LLMatrix4 root;
|
||||
LLVector3 scale = obj->getScale();
|
||||
scale.mV[0] = 1.f / scale.mV[0];
|
||||
scale.mV[1] = 1.f / scale.mV[1];
|
||||
scale.mV[2] = 1.f / scale.mV[2];
|
||||
|
||||
root.translate(-obj->getPositionAgent());
|
||||
root.rotate(~obj->getRenderRotation());
|
||||
|
||||
LLMatrix4 scale_mat;
|
||||
scale_mat.initScale(scale);
|
||||
|
||||
root *= scale_mat;
|
||||
|
||||
|
||||
LLMatrix4a mat;
|
||||
mat.loadu((F32*) root.mMatrix);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
void GLTFSceneManager::renderOpaque()
|
||||
{
|
||||
// for debugging, just render the whole scene as opaque
|
||||
// by traversing the whole scenegraph
|
||||
// Assumes camera transform is already set and
|
||||
// appropriate shader is already bound
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
|
||||
for (U32 i = 0; i < mObjects.size(); ++i)
|
||||
{
|
||||
if (mObjects[i]->isDead() || mObjects[i]->mGLTFAsset == nullptr)
|
||||
{
|
||||
mObjects.erase(mObjects.begin() + i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
Asset* asset = mObjects[i]->mGLTFAsset;
|
||||
|
||||
gGL.pushMatrix();
|
||||
|
||||
LLMatrix4a mat = getAssetToAgentTransform(mObjects[i]);
|
||||
|
||||
LLMatrix4a modelview;
|
||||
modelview.loadu(gGLModelView);
|
||||
|
||||
matMul(mat, modelview, modelview);
|
||||
|
||||
asset->updateRenderTransforms(modelview);
|
||||
asset->renderOpaque();
|
||||
|
||||
gGL.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
LLMatrix4a inverse(const LLMatrix4a& mat)
|
||||
{
|
||||
glh::matrix4f m((F32*)mat.mMatrix);
|
||||
m = m.inverse();
|
||||
LLMatrix4a ret;
|
||||
ret.loadu(m.m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GLTFSceneManager::lineSegmentIntersect(LLVOVolume* obj, Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32* node_hit, S32* primitive_hit,
|
||||
LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
|
||||
|
||||
{
|
||||
// line segment intersection test
|
||||
// start and end should be in agent space
|
||||
// volume space and asset space should be the same coordinate frame
|
||||
// results should be transformed back to agent space
|
||||
|
||||
bool ret = false;
|
||||
|
||||
LLVector4a local_start;
|
||||
LLVector4a local_end;
|
||||
|
||||
LLMatrix4a asset_to_agent = getAssetToAgentTransform(obj);
|
||||
LLMatrix4a agent_to_asset = inverse(asset_to_agent);
|
||||
|
||||
agent_to_asset.affineTransform(start, local_start);
|
||||
agent_to_asset.affineTransform(end, local_end);
|
||||
|
||||
LLVector4a p;
|
||||
LLVector4a n;
|
||||
LLVector2 tc;
|
||||
LLVector4a tn;
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
p = *intersection;
|
||||
}
|
||||
|
||||
if (tex_coord != NULL)
|
||||
{
|
||||
tc = *tex_coord;
|
||||
}
|
||||
|
||||
if (normal != NULL)
|
||||
{
|
||||
n = *normal;
|
||||
}
|
||||
|
||||
if (tangent != NULL)
|
||||
{
|
||||
tn = *tangent;
|
||||
}
|
||||
|
||||
S32 hit_node_index = asset->lineSegmentIntersect(local_start, local_end, &p, &tc, &n, &tn, primitive_hit);
|
||||
|
||||
if (hit_node_index >= 0)
|
||||
{
|
||||
local_end = p;
|
||||
if (node_hit != NULL)
|
||||
{
|
||||
*node_hit = hit_node_index;
|
||||
}
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
asset_to_agent.affineTransform(p, *intersection);
|
||||
}
|
||||
|
||||
if (normal != NULL)
|
||||
{
|
||||
LLVector3 v_n(n.getF32ptr());
|
||||
normal->load3(obj->volumeDirectionToAgent(v_n).mV);
|
||||
(*normal).normalize3fast();
|
||||
}
|
||||
|
||||
if (tangent != NULL)
|
||||
{
|
||||
LLVector3 v_tn(tn.getF32ptr());
|
||||
|
||||
LLVector4a trans_tangent;
|
||||
trans_tangent.load3(obj->volumeDirectionToAgent(v_tn).mV);
|
||||
|
||||
LLVector4Logical mask;
|
||||
mask.clear();
|
||||
mask.setElement<3>();
|
||||
|
||||
tangent->setSelectWithMask(mask, tn, trans_tangent);
|
||||
(*tangent).normalize3fast();
|
||||
}
|
||||
|
||||
if (tex_coord != NULL)
|
||||
{
|
||||
*tex_coord = tc;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LLDrawable* GLTFSceneManager::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
BOOL pick_transparent,
|
||||
BOOL pick_rigged,
|
||||
BOOL pick_unselectable,
|
||||
BOOL pick_reflection_probe,
|
||||
S32* node_hit, // return the index of the node that was hit
|
||||
S32* primitive_hit, // return the index of the primitive that was hit
|
||||
LLVector4a* intersection, // return the intersection point
|
||||
LLVector2* tex_coord, // return the texture coordinates of the intersection point
|
||||
LLVector4a* normal, // return the surface normal at the intersection point
|
||||
LLVector4a* tangent) // return the surface tangent at the intersection point
|
||||
{
|
||||
LLDrawable* drawable = nullptr;
|
||||
|
||||
LLVector4a local_end = end;
|
||||
LLVector4a position;
|
||||
|
||||
for (U32 i = 0; i < mObjects.size(); ++i)
|
||||
{
|
||||
if (mObjects[i]->isDead() || mObjects[i]->mGLTFAsset == nullptr || !mObjects[i]->getVolume())
|
||||
{
|
||||
mObjects.erase(mObjects.begin() + i);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// temporary debug -- always double check objects that have GLTF scenes hanging off of them even if the ray doesn't intersect the object bounds
|
||||
if (lineSegmentIntersect((LLVOVolume*) mObjects[i].get(), mObjects[i]->mGLTFAsset, start, local_end, -1, pick_transparent, pick_rigged, pick_unselectable, node_hit, primitive_hit, &position, tex_coord, normal, tangent))
|
||||
{
|
||||
local_end = position;
|
||||
if (intersection)
|
||||
{
|
||||
*intersection = position;
|
||||
}
|
||||
drawable = mObjects[i]->mDrawable;
|
||||
}
|
||||
}
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size);
|
||||
|
||||
extern LLVector4a gDebugRaycastStart;
|
||||
extern LLVector4a gDebugRaycastEnd;
|
||||
|
||||
void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const LLVolumeOctree* octree);
|
||||
|
||||
void renderAssetDebug(LLViewerObject* obj, Asset* asset)
|
||||
{
|
||||
// render debug
|
||||
// assumes appropriate shader is already bound
|
||||
// assumes modelview matrix is already set
|
||||
|
||||
gGL.pushMatrix();
|
||||
|
||||
// get raycast in asset space
|
||||
LLMatrix4a agent_to_asset = getAgentToAssetTransform(obj);
|
||||
|
||||
LLVector4a start;
|
||||
LLVector4a end;
|
||||
|
||||
agent_to_asset.affineTransform(gDebugRaycastStart, start);
|
||||
agent_to_asset.affineTransform(gDebugRaycastEnd, end);
|
||||
|
||||
|
||||
for (auto& node : asset->mNodes)
|
||||
{
|
||||
Mesh& mesh = asset->mMeshes[node.mMesh];
|
||||
|
||||
if (node.mMesh != INVALID_INDEX)
|
||||
{
|
||||
gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix);
|
||||
|
||||
// draw bounding box of mesh primitives
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
|
||||
{
|
||||
gGL.color3f(0.f, 1.f, 1.f);
|
||||
|
||||
for (auto& primitive : mesh.mPrimitives)
|
||||
{
|
||||
auto* listener = (LLVolumeOctreeListener*) primitive.mOctree->getListener(0);
|
||||
|
||||
LLVector4a center = listener->mBounds[0];
|
||||
LLVector4a size = listener->mBounds[1];
|
||||
|
||||
drawBoxOutline(center, size);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
|
||||
{
|
||||
gGL.flush();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// convert raycast to node local space
|
||||
LLVector4a local_start;
|
||||
LLVector4a local_end;
|
||||
|
||||
node.mAssetMatrixInv.affineTransform(start, local_start);
|
||||
node.mAssetMatrixInv.affineTransform(end, local_end);
|
||||
|
||||
for (auto& primitive : mesh.mPrimitives)
|
||||
{
|
||||
if (primitive.mOctree.notNull())
|
||||
{
|
||||
renderOctreeRaycast(local_start, local_end, primitive.mOctree);
|
||||
}
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
||||
void GLTFSceneManager::renderDebug()
|
||||
{
|
||||
if (!gPipeline.hasRenderDebugMask(
|
||||
LLPipeline::RENDER_DEBUG_BBOXES |
|
||||
LLPipeline::RENDER_DEBUG_RAYCAST))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gDebugProgram.bind();
|
||||
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gPipeline.disableLights();
|
||||
|
||||
for (auto& obj : mObjects)
|
||||
{
|
||||
if (obj->isDead() || obj->mGLTFAsset == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Asset* asset = obj->mGLTFAsset;
|
||||
|
||||
|
||||
LLMatrix4a mat = getAssetToAgentTransform(obj);
|
||||
|
||||
LLMatrix4a modelview;
|
||||
modelview.loadu(gGLModelView);
|
||||
|
||||
matMul(mat, modelview, modelview);
|
||||
|
||||
asset->updateRenderTransforms(modelview);
|
||||
renderAssetDebug(obj, asset);
|
||||
}
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
|
||||
{
|
||||
S32 node_hit = -1;
|
||||
S32 primitive_hit = -1;
|
||||
LLVector4a intersection;
|
||||
|
||||
LLDrawable* drawable = lineSegmentIntersect(gDebugRaycastStart, gDebugRaycastEnd, TRUE, TRUE, TRUE, TRUE, &node_hit, &primitive_hit, &intersection, nullptr, nullptr, nullptr);
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
gGL.pushMatrix();
|
||||
Asset* asset = drawable->getVObj()->mGLTFAsset;
|
||||
Node* node = &asset->mNodes[node_hit];
|
||||
Primitive* primitive = &asset->mMeshes[node->mMesh].mPrimitives[primitive_hit];
|
||||
|
||||
gGL.flush();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
gGL.color3f(1, 0, 1);
|
||||
drawBoxOutline(intersection, LLVector4a(0.1f, 0.1f, 0.1f, 0.f));
|
||||
|
||||
gGL.loadMatrix((F32*) node->mRenderMatrix.mMatrix);
|
||||
|
||||
|
||||
|
||||
auto* listener = (LLVolumeOctreeListener*) primitive->mOctree->getListener(0);
|
||||
drawBoxOutline(listener->mBounds[0], listener->mBounds[1]);
|
||||
|
||||
gGL.flush();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
gGL.popMatrix();
|
||||
}
|
||||
}
|
||||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file gltfscenemanager.h
|
||||
* @brief Builds menus out of items.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2024, 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 "llsingleton.h"
|
||||
#include "llviewerobject.h"
|
||||
|
||||
namespace LL
|
||||
{
|
||||
class GLTFSceneManager : public LLSimpleton<GLTFSceneManager>
|
||||
{
|
||||
public:
|
||||
~GLTFSceneManager();
|
||||
// load GLTF file from disk
|
||||
void load(); // open filepicker to choose asset
|
||||
void load(const std::string& filename); // load asset from filename
|
||||
void renderOpaque();
|
||||
|
||||
LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
|
||||
BOOL pick_transparent,
|
||||
BOOL pick_rigged,
|
||||
BOOL pick_unselectable,
|
||||
BOOL pick_reflection_probe,
|
||||
S32* node_hit, // return the index of the node that was hit
|
||||
S32* primitive_hit, // return the index of the primitive that was hit
|
||||
LLVector4a* intersection, // return the intersection point
|
||||
LLVector2* tex_coord, // return the texture coordinates of the intersection point
|
||||
LLVector4a* normal, // return the surface normal at the intersection point
|
||||
LLVector4a* tangent); // return the surface tangent at the intersection point
|
||||
|
||||
bool lineSegmentIntersect(LLVOVolume* obj, GLTF::Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32* face_hitp, S32* primitive_hitp,
|
||||
LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent);
|
||||
|
||||
void renderDebug();
|
||||
|
||||
std::vector<LLPointer<LLViewerObject>> mObjects;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llagentbenefits.h"
|
||||
#include "llviewertexture.h"
|
||||
|
||||
// <FS:Ansariel> OpenSim legacy economy
|
||||
#include "llagent.h"
|
||||
|
|
@ -45,7 +46,6 @@ LLAgentBenefits::LLAgentBenefits():
|
|||
m_picks_limit(-1),
|
||||
m_sound_upload_cost(-1),
|
||||
m_texture_upload_cost(-1),
|
||||
m_2k_texture_upload_cost(-1),
|
||||
m_create_group_cost(-1)
|
||||
{
|
||||
}
|
||||
|
|
@ -106,7 +106,26 @@ bool LLAgentBenefits::init(const LLSD& benefits_sd)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
get_required_S32(benefits_sd, "large_texture_upload_cost", m_2k_texture_upload_cost);
|
||||
|
||||
if (benefits_sd.has("large_texture_upload_cost"))
|
||||
{
|
||||
LLSD large_texture_cost = benefits_sd.get("large_texture_upload_cost");
|
||||
if (large_texture_cost.isArray())
|
||||
{
|
||||
LLSD::array_const_iterator end = large_texture_cost.endArray();
|
||||
LLSD::array_const_iterator it = large_texture_cost.beginArray();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
m_2k_texture_upload_cost.push_back(it->asInteger());
|
||||
}
|
||||
std::sort(m_2k_texture_upload_cost.begin(), m_2k_texture_upload_cost.end());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_2k_texture_upload_cost.empty())
|
||||
{
|
||||
m_2k_texture_upload_cost.push_back(m_texture_upload_cost);
|
||||
}
|
||||
|
||||
// FIXME PREMIUM - either use this field or get rid of it
|
||||
m_initalized = true;
|
||||
|
|
@ -221,9 +240,60 @@ S32 LLAgentBenefits::getTextureUploadCost() const
|
|||
// </FS:Ansariel>
|
||||
}
|
||||
|
||||
S32 LLAgentBenefits::get2KTextureUploadCost() const
|
||||
S32 LLAgentBenefits::getTextureUploadCost(const LLViewerTexture* tex) const
|
||||
{
|
||||
return m_2k_texture_upload_cost;
|
||||
if (tex)
|
||||
{
|
||||
S32 area = tex->getFullHeight() * tex->getFullWidth();
|
||||
if (area >= MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
return get2KTextureUploadCost(area);
|
||||
}
|
||||
else
|
||||
{
|
||||
return getTextureUploadCost();
|
||||
}
|
||||
}
|
||||
return getTextureUploadCost();
|
||||
}
|
||||
|
||||
S32 LLAgentBenefits::getTextureUploadCost(const LLImageBase* tex) const
|
||||
{
|
||||
if (tex)
|
||||
{
|
||||
S32 area = tex->getHeight() * tex->getWidth();
|
||||
if (area >= MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
return get2KTextureUploadCost(area);
|
||||
}
|
||||
else
|
||||
{
|
||||
return getTextureUploadCost();
|
||||
}
|
||||
}
|
||||
return getTextureUploadCost();
|
||||
}
|
||||
|
||||
S32 LLAgentBenefits::get2KTextureUploadCost(S32 area) const
|
||||
{
|
||||
if (m_2k_texture_upload_cost.empty())
|
||||
{
|
||||
return m_texture_upload_cost;
|
||||
}
|
||||
const S32 TEXTURE_SEGMENTS = 1024;
|
||||
if (m_2k_texture_upload_cost.size() == TEXTURE_SEGMENTS)
|
||||
{
|
||||
S32 index = (S32)llceil(sqrt((F32)area));
|
||||
// 1..1024 pixels uses m_texture_upload_cost
|
||||
// 1025..2048 uses m_2k_texture_upload_cost
|
||||
// Translate 1025..2048 to 0..1023 of the
|
||||
// cost array
|
||||
const S32 PIXELS_TO_2K_ARRAY_TRANLATE = 1025;
|
||||
index -= PIXELS_TO_2K_ARRAY_TRANLATE;
|
||||
index = llclamp(index, 0, TEXTURE_SEGMENTS - 1);
|
||||
return m_2k_texture_upload_cost[index];
|
||||
}
|
||||
return m_2k_texture_upload_cost[0];
|
||||
}
|
||||
|
||||
bool LLAgentBenefits::findUploadCost(LLAssetType::EType& asset_type, S32& cost) const
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
#include "llsd.h"
|
||||
#include "llassettype.h"
|
||||
|
||||
class LLViewerTexture;
|
||||
class LLImageBase;
|
||||
|
||||
class LLAgentBenefits
|
||||
{
|
||||
public:
|
||||
|
|
@ -49,7 +52,9 @@ public:
|
|||
S32 getPicksLimit() const;
|
||||
S32 getSoundUploadCost() const;
|
||||
S32 getTextureUploadCost() const;
|
||||
S32 get2KTextureUploadCost() const;
|
||||
S32 getTextureUploadCost(const LLViewerTexture* tex) const;
|
||||
S32 getTextureUploadCost(const LLImageBase* tex) const;
|
||||
S32 get2KTextureUploadCost(S32 area) const;
|
||||
|
||||
bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const;
|
||||
|
||||
|
|
@ -62,7 +67,7 @@ private:
|
|||
S32 m_picks_limit;
|
||||
S32 m_sound_upload_cost;
|
||||
S32 m_texture_upload_cost;
|
||||
S32 m_2k_texture_upload_cost;
|
||||
std::vector<S32> m_2k_texture_upload_cost;
|
||||
|
||||
bool m_initalized;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -256,6 +256,8 @@
|
|||
#include "llavatariconctrl.h"
|
||||
#include "llgroupiconctrl.h"
|
||||
#include "llviewerassetstats.h"
|
||||
#include "gltfscenemanager.h"
|
||||
|
||||
#include "workqueue.h"
|
||||
using namespace LL;
|
||||
|
||||
|
|
@ -1484,6 +1486,8 @@ bool LLAppViewer::init()
|
|||
LLWorld::createInstance();
|
||||
LLSelectMgr::createInstance();
|
||||
LLViewerCamera::createInstance();
|
||||
LL::GLTFSceneManager::createInstance();
|
||||
|
||||
|
||||
#if LL_WINDOWS
|
||||
if (!mSecondInstance)
|
||||
|
|
@ -2515,7 +2519,7 @@ bool LLAppViewer::cleanup()
|
|||
ll_close_fail_log();
|
||||
|
||||
LLError::LLCallStacks::cleanup();
|
||||
|
||||
LL::GLTFSceneManager::deleteSingleton();
|
||||
LLEnvironment::deleteSingleton();
|
||||
LLSelectMgr::deleteSingleton();
|
||||
LLViewerEventRecorder::deleteSingleton();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "lldrawpoolpbropaque.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "pipeline.h"
|
||||
#include "gltfscenemanager.h"
|
||||
|
||||
LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR(U32 type) :
|
||||
LLRenderPass(type)
|
||||
|
|
@ -54,8 +55,11 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass)
|
|||
llassert(!LLPipeline::sRenderingHUDs);
|
||||
|
||||
gDeferredPBROpaqueProgram.bind();
|
||||
|
||||
LL::GLTFSceneManager::instance().renderOpaque();
|
||||
pushGLTFBatches(mRenderType);
|
||||
|
||||
|
||||
gDeferredPBROpaqueProgram.bind(true);
|
||||
pushRiggedGLTFBatches(mRenderType + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,18 +293,7 @@ void LLFloaterImagePreview::onBtnUpload()
|
|||
//-----------------------------------------------------------------------------
|
||||
S32 LLFloaterImagePreview::getExpectedUploadCost() const
|
||||
{
|
||||
if (mRawImagep.notNull())
|
||||
{
|
||||
if (mRawImagep->getWidth() * mRawImagep->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
return LLAgentBenefitsMgr::current().get2KTextureUploadCost();
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLAgentBenefitsMgr::current().getTextureUploadCost();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return LLAgentBenefitsMgr::current().getTextureUploadCost(mRawImagep);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -591,7 +580,7 @@ bool LLFloaterImagePreview::loadImage(const std::string& src_filename)
|
|||
return false;
|
||||
}
|
||||
|
||||
raw_image->biasedScaleToPowerOfTwo(1024);
|
||||
raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
|
||||
mRawImagep = raw_image;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -243,13 +243,13 @@ void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::s
|
|||
}
|
||||
}
|
||||
}
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
|
||||
// Workaround for server sending empty overrides.
|
||||
if(cache.mSides.size() > 0)
|
||||
{
|
||||
region->cacheFullUpdateGLTFOverride(cache);
|
||||
LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL;
|
||||
}
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,14 @@ LLHeroProbeManager::LLHeroProbeManager()
|
|||
{
|
||||
}
|
||||
|
||||
LLHeroProbeManager::~LLHeroProbeManager()
|
||||
{
|
||||
cleanup();
|
||||
|
||||
mHeroVOList.clear();
|
||||
mNearestHero = nullptr;
|
||||
}
|
||||
|
||||
// helper class to seed octree with probes
|
||||
void LLHeroProbeManager::update()
|
||||
{
|
||||
|
|
@ -84,8 +92,7 @@ void LLHeroProbeManager::update()
|
|||
if (!mRenderTarget.isComplete())
|
||||
{
|
||||
U32 color_fmt = GL_RGBA16F;
|
||||
U32 targetRes = mProbeResolution; // super sample
|
||||
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
|
||||
mRenderTarget.allocate(mProbeResolution, mProbeResolution, color_fmt, true);
|
||||
}
|
||||
|
||||
if (mMipChain.empty())
|
||||
|
|
@ -472,12 +479,19 @@ void LLHeroProbeManager::renderDebug()
|
|||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
|
||||
void LLHeroProbeManager::initReflectionMaps()
|
||||
{
|
||||
U32 count = LL_MAX_HERO_PROBE_COUNT;
|
||||
|
||||
if (mTexture.isNull() || mReflectionProbeCount != count || mReset)
|
||||
if ((mTexture.isNull() || mReflectionProbeCount != count || mReset) && LLPipeline::RenderMirrors)
|
||||
{
|
||||
|
||||
if (mReset)
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
mReset = false;
|
||||
mReflectionProbeCount = count;
|
||||
mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution");
|
||||
|
|
@ -546,9 +560,8 @@ void LLHeroProbeManager::cleanup()
|
|||
|
||||
mDefaultProbe = nullptr;
|
||||
mUpdatingProbe = nullptr;
|
||||
|
||||
mHeroVOList.clear();
|
||||
mNearestHero = nullptr;
|
||||
/*
|
||||
*/
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::doOcclusion()
|
||||
|
|
@ -565,6 +578,11 @@ void LLHeroProbeManager::doOcclusion()
|
|||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::reset()
|
||||
{
|
||||
mReset = true;
|
||||
}
|
||||
|
||||
bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep)
|
||||
{
|
||||
llassert(drawablep != nullptr);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public:
|
|||
|
||||
// allocate an environment map of the given resolution
|
||||
LLHeroProbeManager();
|
||||
~LLHeroProbeManager();
|
||||
|
||||
// release any GL state
|
||||
void cleanup();
|
||||
|
|
@ -77,6 +78,8 @@ public:
|
|||
// perform occlusion culling on all active reflection probes
|
||||
void doOcclusion();
|
||||
|
||||
void reset();
|
||||
|
||||
bool registerViewerObject(LLVOVolume *drawablep);
|
||||
void unregisterViewerObject(LLVOVolume* drawablep);
|
||||
|
||||
|
|
|
|||
|
|
@ -492,20 +492,10 @@ BOOL LLMaterialEditor::postBuild()
|
|||
}
|
||||
else
|
||||
{
|
||||
S32 upload_cost_base = LLAgentBenefitsMgr::current().getTextureUploadCost();
|
||||
S32 upload_cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost();
|
||||
|
||||
bool large_texture = mBaseColorFetched && (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA);
|
||||
getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base));
|
||||
|
||||
large_texture = mMetallicRoughnessFetched && (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA);
|
||||
getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base));
|
||||
|
||||
large_texture = mEmissiveFetched && (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA);
|
||||
getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base));
|
||||
|
||||
large_texture = mNormalFetched && (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA);
|
||||
getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base));
|
||||
getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched)));
|
||||
getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched)));
|
||||
getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched)));
|
||||
getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched)));
|
||||
}
|
||||
|
||||
boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void* userData)
|
||||
|
|
@ -854,60 +844,24 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
|
|||
setCanSave(false);
|
||||
}
|
||||
|
||||
S32 upload_texture_count = 0;
|
||||
S32 upload_2k_texture_count = 0;
|
||||
mExpectedUploadCost = 0;
|
||||
if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId() && mBaseColorFetched)
|
||||
{
|
||||
if (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
upload_2k_texture_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
upload_texture_count++;
|
||||
}
|
||||
mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched);
|
||||
}
|
||||
if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicRoughnessFetched)
|
||||
{
|
||||
if (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
upload_2k_texture_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
upload_texture_count++;
|
||||
}
|
||||
mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched);
|
||||
}
|
||||
if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId() && mEmissiveFetched)
|
||||
{
|
||||
if (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
upload_2k_texture_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
upload_texture_count++;
|
||||
}
|
||||
mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched);
|
||||
}
|
||||
if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId() && mNormalFetched)
|
||||
{
|
||||
if (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
upload_2k_texture_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
upload_texture_count++;
|
||||
}
|
||||
mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched);
|
||||
}
|
||||
|
||||
mExpectedUploadCost = upload_texture_count * LLAgentBenefitsMgr::current().getTextureUploadCost();
|
||||
S32 cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost();
|
||||
if (cost_2k < 0)
|
||||
{
|
||||
cost_2k = 0;
|
||||
}
|
||||
mExpectedUploadCost += upload_2k_texture_count * cost_2k;
|
||||
getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
|
||||
}
|
||||
|
||||
|
|
@ -3553,12 +3507,7 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con
|
|||
std::string buffer;
|
||||
buffer.assign((const char*) img->getData(), img->getDataSize());
|
||||
|
||||
U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
|
||||
if (img->getWidth() * img->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost();
|
||||
}
|
||||
|
||||
U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(img);
|
||||
LLSD key = getKey();
|
||||
std::function<bool(LLUUID itemId, LLSD response, std::string reason)> failed_upload([key](LLUUID assetId, LLSD response, std::string reason)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2969,10 +2969,8 @@ void renderLights(LLDrawable* drawablep)
|
|||
class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t)
|
||||
: LLOctreeTriangleRayIntersect(start, dir, NULL, closest_t, NULL, NULL, NULL, NULL)
|
||||
: LLOctreeTriangleRayIntersect(start, dir, nullptr, closest_t, NULL, NULL, NULL, NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -2996,7 +2994,7 @@ public:
|
|||
size.set(vl->mBounds[1].getF32ptr());
|
||||
}
|
||||
|
||||
drawBoxOutline(center, size);
|
||||
drawBoxOutline(center, size);
|
||||
|
||||
for (U32 i = 0; i < 2; i++)
|
||||
{
|
||||
|
|
@ -3040,6 +3038,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const LLVolumeOctree* octree)
|
||||
{
|
||||
F32 t = 1.f;
|
||||
LLRenderOctreeRaycast render(start, end, &t);
|
||||
render.traverse(octree);
|
||||
}
|
||||
|
||||
void renderRaycast(LLDrawable* drawablep)
|
||||
{
|
||||
if (drawablep->getNumFaces())
|
||||
|
|
@ -3097,33 +3102,22 @@ void renderRaycast(LLDrawable* drawablep)
|
|||
dir.setSub(end, start);
|
||||
|
||||
gGL.flush();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
{
|
||||
//render face positions
|
||||
// <FS:Ansariel> Use a vbo for the static LLVertexBuffer::drawArray/Element functions; by Drake Arconis/Shyotl Kuhr
|
||||
//LLVertexBuffer::unbind();
|
||||
//gGL.diffuseColor4f(0, 1, 1, 0.5f);
|
||||
//glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions);
|
||||
//gGL.syncMatrices();
|
||||
//glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
|
||||
gGL.diffuseColor4f(0.f, 1.f, 1.f, 0.5f);
|
||||
LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices);
|
||||
// </FS:Ansariel>
|
||||
//gGL.diffuseColor4f(0,1,1,0.5f);
|
||||
//LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, nullptr, face.mNumIndices, face.mIndices);
|
||||
}
|
||||
|
||||
if (!volume->isUnique())
|
||||
{
|
||||
F32 t = 1.f;
|
||||
|
||||
if (!face.getOctree())
|
||||
{
|
||||
((LLVolumeFace*) &face)->createOctree();
|
||||
}
|
||||
|
||||
LLRenderOctreeRaycast render(start, dir, &t);
|
||||
|
||||
render.traverse(face.getOctree());
|
||||
renderOctreeRaycast(start, end, face.getOctree());
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ const tinygltf::Image * LLTinyGLTFHelper::getImageFromTextureIndex(const tinyglt
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, std::string & name)
|
||||
LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, std::string & name, bool flip)
|
||||
{
|
||||
const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index);
|
||||
LLImageRaw* rawImage = nullptr;
|
||||
|
|
@ -159,14 +159,17 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny
|
|||
{
|
||||
name = image->name;
|
||||
rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component);
|
||||
rawImage->verticalFlip();
|
||||
if (flip)
|
||||
{
|
||||
rawImage->verticalFlip();
|
||||
}
|
||||
rawImage->optimizeAwayAlpha();
|
||||
}
|
||||
|
||||
return rawImage;
|
||||
}
|
||||
|
||||
LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index)
|
||||
LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, bool flip)
|
||||
{
|
||||
const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index);
|
||||
LLImageRaw* rawImage = nullptr;
|
||||
|
|
@ -177,7 +180,10 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny
|
|||
image->component <= 4)
|
||||
{
|
||||
rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component);
|
||||
rawImage->verticalFlip();
|
||||
if (flip)
|
||||
{
|
||||
rawImage->verticalFlip();
|
||||
}
|
||||
rawImage->optimizeAwayAlpha();
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +243,8 @@ bool LLTinyGLTFHelper::getMaterialFromModel(
|
|||
const tinygltf::Model& model_in,
|
||||
S32 mat_index,
|
||||
LLFetchedGLTFMaterial* material,
|
||||
std::string& material_name)
|
||||
std::string& material_name,
|
||||
bool flip)
|
||||
{
|
||||
llassert(material);
|
||||
|
||||
|
|
@ -256,18 +263,18 @@ bool LLTinyGLTFHelper::getMaterialFromModel(
|
|||
material_name = material_in.name;
|
||||
|
||||
// get base color texture
|
||||
LLPointer<LLImageRaw> base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index);
|
||||
LLPointer<LLImageRaw> base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index, flip);
|
||||
// get normal map
|
||||
LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index);
|
||||
LLPointer<LLImageRaw> normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index, flip);
|
||||
// get metallic-roughness texture
|
||||
LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index);
|
||||
LLPointer<LLImageRaw> mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index, flip);
|
||||
// get emissive texture
|
||||
LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index);
|
||||
LLPointer<LLImageRaw> emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index, flip);
|
||||
// get occlusion map if needed
|
||||
LLPointer<LLImageRaw> occlusion_img;
|
||||
if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index)
|
||||
{
|
||||
occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index);
|
||||
occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index, flip);
|
||||
}
|
||||
|
||||
LLPointer<LLViewerFetchedTexture> base_color_tex;
|
||||
|
|
|
|||
|
|
@ -38,10 +38,8 @@ namespace LLTinyGLTFHelper
|
|||
{
|
||||
LLColor4 getColor(const std::vector<double>& in);
|
||||
const tinygltf::Image* getImageFromTextureIndex(const tinygltf::Model& model, S32 texture_index);
|
||||
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name);
|
||||
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index);
|
||||
|
||||
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index);
|
||||
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name, bool flip = true);
|
||||
LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, bool flip = true);
|
||||
|
||||
bool loadModel(const std::string& filename, tinygltf::Model& model_out);
|
||||
|
||||
|
|
@ -50,7 +48,8 @@ namespace LLTinyGLTFHelper
|
|||
const tinygltf::Model& model,
|
||||
S32 mat_index,
|
||||
LLFetchedGLTFMaterial* material,
|
||||
std::string& material_name);
|
||||
std::string& material_name,
|
||||
bool flip = true);
|
||||
|
||||
void initFetchedTextures(tinygltf::Material& material,
|
||||
LLPointer<LLImageRaw>& base_color_img,
|
||||
|
|
|
|||
|
|
@ -162,9 +162,9 @@ LLSD LLResourceUploadInfo::generatePostBody()
|
|||
body["next_owner_mask"] = LLSD::Integer(mNextOwnerPerms);
|
||||
body["group_mask"] = LLSD::Integer(mGroupPerms);
|
||||
body["everyone_mask"] = LLSD::Integer(mEveryonePerms);
|
||||
body["expected_upload_cost"] = mExpectedUploadCost;
|
||||
|
||||
return body;
|
||||
|
||||
}
|
||||
|
||||
void LLResourceUploadInfo::logPreparedUpload()
|
||||
|
|
|
|||
|
|
@ -543,6 +543,19 @@ static bool handleReflectionProbeDetailChanged(const LLSD& newvalue)
|
|||
gPipeline.createGLBuffers();
|
||||
LLViewerShaderMgr::instance()->setShaders();
|
||||
gPipeline.mReflectionMapManager.reset();
|
||||
gPipeline.mHeroProbeManager.reset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handleHeroProbeResolutionChanged(const LLSD &newvalue)
|
||||
{
|
||||
if (gPipeline.isInit())
|
||||
{
|
||||
LLPipeline::refreshCachedSettings();
|
||||
gPipeline.mHeroProbeManager.reset();
|
||||
gPipeline.releaseGLBuffers();
|
||||
gPipeline.createGLBuffers();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1218,6 +1231,7 @@ void settings_setup_listeners()
|
|||
setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged);
|
||||
// setting_setup_signal_listener(gSavedSettings, "RenderReflectionsEnabled", handleReflectionsEnabled); // <FS:Beq/> FIRE-33659 better way to enable/disable reflections
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderScreenSpaceReflections", handleReflectionProbeDetailChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderHeroProbeResolution", handleHeroProbeResolutionChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged);
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@
|
|||
#include <boost/algorithm/string.hpp>
|
||||
#include "llcleanup.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "gltfscenemanager.h"
|
||||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
||||
#include "fsavatarrenderpersistence.h"
|
||||
#include "rlvactions.h"
|
||||
|
|
@ -9919,6 +9920,17 @@ class LLAdvancedClickHDRIPreview: public view_listener_t
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class LLAdvancedClickGLTFScenePreview : public view_listener_t
|
||||
{
|
||||
bool handleEvent(const LLSD& userdata)
|
||||
{
|
||||
// open personal lighting floater when previewing an HDRI (keeps HDRI from implicitly unloading when opening build tools)
|
||||
LL::GLTFSceneManager::instance().load();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// these are used in the gl menus to set control values that require shader recompilation
|
||||
class LLToggleShaderControl : public view_listener_t
|
||||
{
|
||||
|
|
@ -12367,6 +12379,7 @@ void initialize_menus()
|
|||
view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile");
|
||||
view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark");
|
||||
view_listener_t::addMenu(new LLAdvancedClickHDRIPreview(), "Advanced.ClickHDRIPreview");
|
||||
view_listener_t::addMenu(new LLAdvancedClickGLTFScenePreview(), "Advanced.ClickGLTFScenePreview");
|
||||
view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache");
|
||||
view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain");
|
||||
//[FIX FIRE-1927 - enable DoubleClickTeleport shortcut : SJ]
|
||||
|
|
|
|||
|
|
@ -571,19 +571,8 @@ void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification
|
|||
LLPointer<LLImageFormatted> image_frmted = LLImageFormatted::createFromType(codec);
|
||||
if (gDirUtilp->fileExists(filename) && image_frmted->load(filename))
|
||||
{
|
||||
if (image_frmted->getWidth() * image_frmted->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost();
|
||||
if (expected_upload_cost >= 0)
|
||||
{
|
||||
resource_upload = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
|
||||
resource_upload = true;
|
||||
}
|
||||
expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(image_frmted);
|
||||
resource_upload = true;
|
||||
}
|
||||
}
|
||||
else if (LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost))
|
||||
|
|
@ -632,8 +621,6 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3
|
|||
total_cost = 0;
|
||||
file_count = 0;
|
||||
bvh_count = 0;
|
||||
S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
|
||||
S32 texture_2k_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost();
|
||||
for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
|
||||
{
|
||||
std::string filename = (*in_iter);
|
||||
|
|
@ -655,19 +642,8 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3
|
|||
LLPointer<LLImageFormatted> image_frmted = LLImageFormatted::createFromType(codec);
|
||||
if (gDirUtilp->fileExists(filename) && image_frmted->load(filename))
|
||||
{
|
||||
if (image_frmted->getWidth() * image_frmted->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
if (texture_2k_upload_cost >= 0)
|
||||
{
|
||||
total_cost += texture_2k_upload_cost;
|
||||
file_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
total_cost += texture_upload_cost;
|
||||
file_count++;
|
||||
}
|
||||
total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(image_frmted);
|
||||
file_count++;
|
||||
}
|
||||
}
|
||||
else if (LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost))
|
||||
|
|
@ -695,53 +671,22 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3
|
|||
{
|
||||
// Todo: make it account for possibility of same texture in different
|
||||
// materials and even in scope of same material
|
||||
S32 texture_count = 0;
|
||||
S32 texture_2k_count = 0;
|
||||
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && material->mBaseColorTexture)
|
||||
{
|
||||
if (material->mBaseColorTexture->getFullHeight() * material->mBaseColorTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
texture_2k_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_count++;
|
||||
}
|
||||
total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mBaseColorTexture);
|
||||
}
|
||||
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && material->mMetallicRoughnessTexture)
|
||||
{
|
||||
if (material->mMetallicRoughnessTexture->getFullHeight() * material->mMetallicRoughnessTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
texture_2k_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_count++;
|
||||
}
|
||||
total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mMetallicRoughnessTexture);
|
||||
}
|
||||
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && material->mNormalTexture)
|
||||
{
|
||||
if (material->mNormalTexture->getFullHeight() * material->mNormalTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
texture_2k_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_count++;
|
||||
}
|
||||
total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mNormalTexture);
|
||||
}
|
||||
if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && material->mEmissiveTexture)
|
||||
{
|
||||
if (material->mEmissiveTexture->getFullHeight() * material->mEmissiveTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA)
|
||||
{
|
||||
texture_2k_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_count++;
|
||||
}
|
||||
total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mEmissiveTexture);
|
||||
}
|
||||
total_cost += texture_count * texture_upload_cost + texture_2k_count * texture_2k_upload_cost;
|
||||
file_count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "llbbox.h"
|
||||
#include "llrigginginfo.h"
|
||||
#include "llreflectionmap.h"
|
||||
#include "gltf/asset.h"
|
||||
|
||||
#include "fsregioncross.h" // <FS:JN> Improved region crossing support
|
||||
|
||||
|
|
@ -739,6 +740,8 @@ public:
|
|||
F32 mPhysicsDensity;
|
||||
F32 mPhysicsRestitution;
|
||||
|
||||
// Associated GLTF Asset
|
||||
LLPointer<LL::GLTF::Asset> mGLTFAsset;
|
||||
|
||||
// Pipeline classes
|
||||
LLPointer<LLDrawable> mDrawable;
|
||||
|
|
|
|||
|
|
@ -844,13 +844,9 @@ void LLViewerRegion::loadObjectCache()
|
|||
if(LLVOCache::instanceExists())
|
||||
{
|
||||
LLVOCache & vocache = LLVOCache::instance();
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap);
|
||||
// vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD);
|
||||
// mark as dirty if read fails to force a rewrite.
|
||||
// Without this a "corrupted" vocache persists until a cache clear or other rewrite. Mark as dirty hereif read fails to force a rewrite.
|
||||
mCacheDirty = !vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap);
|
||||
vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mImpl->mCacheMap);
|
||||
// </FS:Beq>
|
||||
|
||||
if (mImpl->mCacheMap.empty())
|
||||
{
|
||||
|
|
@ -1256,17 +1252,13 @@ void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering)
|
|||
child = entry->getChild();
|
||||
}
|
||||
}
|
||||
|
||||
// <FS:Beq> Fix the missing kill on overrides
|
||||
// Kill the assocaited overrides
|
||||
mImpl->mGLTFOverridesLLSD.erase(entry->getLocalID());
|
||||
// </FS:Beq>
|
||||
//will remove it from the object cache, real deletion
|
||||
entry->setState(LLVOCacheEntry::INACTIVE);
|
||||
entry->removeOctreeEntry();
|
||||
entry->setValid(FALSE);
|
||||
// <FS:Beq/> Fix the missing kill on overrides
|
||||
// // TODO kill extras/material overrides cache too
|
||||
|
||||
|
||||
}
|
||||
|
||||
//physically delete the cache entry
|
||||
|
|
@ -4021,12 +4013,11 @@ void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj)
|
|||
auto iter = mImpl->mGLTFOverridesLLSD.find(local_id);
|
||||
if (iter != mImpl->mGLTFOverridesLLSD.end())
|
||||
{
|
||||
// <FS:Beq> backfill the UUID if it was left empty
|
||||
// UUID can be inserted null, so backfill the UUID if it was left empty
|
||||
if (iter->second.mObjectId.isNull())
|
||||
{
|
||||
iter->second.mObjectId = obj->getID();
|
||||
}
|
||||
// </FS:Beq>
|
||||
llassert(iter->second.mGLTFMaterial.size() == iter->second.mSides.size());
|
||||
|
||||
for (auto& side : iter->second.mGLTFMaterial)
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ namespace
|
|||
if (!tex) { return; }
|
||||
tex->setBoostLevel(LLGLTexture::BOOST_NONE);
|
||||
tex->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
|
||||
|
||||
if (tex->getTextureState() == LLGLTexture::NO_DELETE)
|
||||
{
|
||||
tex->forceActive();
|
||||
}
|
||||
}
|
||||
|
||||
void unboost_minimap_material(LLPointer<LLFetchedGLTFMaterial>& mat)
|
||||
|
|
@ -91,6 +96,11 @@ LLTerrainMaterials::LLTerrainMaterials()
|
|||
|
||||
LLTerrainMaterials::~LLTerrainMaterials()
|
||||
{
|
||||
for (S32 i = 0; i < ASSET_COUNT; ++i)
|
||||
{
|
||||
unboost_minimap_texture(mDetailTextures[i]);
|
||||
unboost_minimap_material(mDetailMaterials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLTerrainMaterials::generateMaterials()
|
||||
|
|
@ -131,6 +141,12 @@ LLPointer<LLViewerFetchedTexture> fetch_terrain_texture(const LLUUID& id)
|
|||
|
||||
void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id)
|
||||
{
|
||||
// *NOTE: If there were multiple terrain swatches using the same asset
|
||||
// ID, the asset still in use will be temporarily unboosted.
|
||||
// It will be boosted again during terrain rendering.
|
||||
unboost_minimap_texture(mDetailTextures[asset]);
|
||||
unboost_minimap_material(mDetailMaterials[asset]);
|
||||
|
||||
// This is terrain texture, but we are not setting it as BOOST_TERRAIN
|
||||
// since we will be manipulating it later as needed.
|
||||
mDetailTextures[asset] = fetch_terrain_texture(id);
|
||||
|
|
|
|||
|
|
@ -1481,7 +1481,7 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
|
|||
switch (camera_mode)
|
||||
{
|
||||
case CAMERA_MODE_MOUSELOOK:
|
||||
if (LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson())
|
||||
if ((LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) || gPipeline.mHeroProbeManager.isMirrorPass())
|
||||
{
|
||||
// [RLVa:KB] - Checked: RLVa-2.0.2
|
||||
attachment->setAttachmentVisibility(fRlvCanShowAttachment);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "llagentcamera.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llagent.h" // <FS:Beq/> For gAgent
|
||||
#include "llworld.h" // <FS:Beq/> For LLWorld::getInstance()
|
||||
#include "llworld.h" // For LLWorld::getInstance()
|
||||
|
||||
//static variables
|
||||
U32 LLVOCacheEntry::sMinFrameRange = 0;
|
||||
|
|
@ -56,10 +56,10 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
|
|||
{
|
||||
return apr_file->write(src, n_bytes) == n_bytes ;
|
||||
}
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
|
||||
// Material Override Cache needs a version label, so we can upgrade this later.
|
||||
const std::string LLGLTFOverrideCacheEntry::VERSION_LABEL = {"GLTFCacheVer"};
|
||||
const int LLGLTFOverrideCacheEntry::VERSION = 1;
|
||||
// </FS:Beq>
|
||||
|
||||
bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data)
|
||||
{
|
||||
|
|
@ -241,7 +241,7 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
|
|||
}
|
||||
else
|
||||
{
|
||||
// <FS:Beq/> improve logging around vocache
|
||||
// Improve logging around vocache
|
||||
LL_WARNS() << "Error loading cache entry for " << mLocalID << ", size " << size << " aborting!" << LL_ENDL;
|
||||
delete[] mBuffer ;
|
||||
mBuffer = NULL ;
|
||||
|
|
@ -1296,11 +1296,10 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry)
|
|||
{
|
||||
return;
|
||||
}
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// Bit more tracking of cache creation/destruction.
|
||||
std::string filename;
|
||||
getObjectCacheFilename(entry->mHandle, filename);
|
||||
LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL;
|
||||
// </FS:Beq>
|
||||
|
||||
header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry);
|
||||
if(iter != mHeaderEntryQueue.end())
|
||||
|
|
@ -1371,11 +1370,10 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry)
|
|||
std::string filename;
|
||||
getObjectCacheFilename(entry->mHandle, filename);
|
||||
LLAPRFile::remove(filename, mLocalAPRFilePoolp);
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// Note that removeFromCache should take responsibility for cleaning up all cache artefactgs specfic to the handle/entry.
|
||||
// Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry.
|
||||
// as such this now includes the generic extras
|
||||
removeGenericExtrasForHandle(entry->mHandle);
|
||||
// </FS:Beq>
|
||||
|
||||
entry->mTime = INVALID_TIME ;
|
||||
updateEntry(entry) ; //update the head file.
|
||||
}
|
||||
|
|
@ -1524,17 +1522,15 @@ BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry)
|
|||
|
||||
return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ;
|
||||
}
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)
|
||||
|
||||
// we now return bool to trigger dirty cache
|
||||
// and force a rewrite after a partial read due to corruption.
|
||||
// this in turn forces a rewrite after a partial read due to corruption.
|
||||
bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)
|
||||
// </FS:Beq>
|
||||
{
|
||||
if(!mEnabled)
|
||||
{
|
||||
LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL;
|
||||
return true; // <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
return true; // no problem we're just read only
|
||||
}
|
||||
llassert_always(mInitialized);
|
||||
|
||||
|
|
@ -1542,12 +1538,12 @@ bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
|
|||
if(iter == mHandleEntryMap.end()) //no cache
|
||||
{
|
||||
LL_WARNS() << "No handle map entry for " << handle << LL_ENDL;
|
||||
return false; // <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
return false; // arguably no a problem, but we'll mark this as dirty anyway.
|
||||
}
|
||||
|
||||
bool success = true ;
|
||||
S32 num_entries=0; // <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
std::string filename;
|
||||
S32 num_entries = 0 ; // lifted out of inner loop.
|
||||
std::string filename; // lifted out of loop
|
||||
{
|
||||
LLUUID cache_id;
|
||||
getObjectCacheFilename(handle, filename);
|
||||
|
|
@ -1565,7 +1561,6 @@ bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
|
|||
|
||||
if(success)
|
||||
{
|
||||
// S32 num_entries; // if removal was enabled during write num_entries might be wrong
|
||||
success = check_read(&apr_file, &num_entries, sizeof(S32)) ;
|
||||
|
||||
if(success)
|
||||
|
|
@ -1576,7 +1571,7 @@ bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
|
|||
if (!entry->getLocalID())
|
||||
{
|
||||
LL_WARNS() << "Aborting cache file load for " << filename << ", cache file corruption!" << LL_ENDL;
|
||||
success = false ;
|
||||
success = false ;
|
||||
break ;
|
||||
}
|
||||
cache_entry_map[entry->getLocalID()] = entry;
|
||||
|
|
@ -1592,24 +1587,19 @@ bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
|
|||
{
|
||||
removeEntry(iter->second) ;
|
||||
}
|
||||
|
||||
}
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// return ;
|
||||
|
||||
LL_DEBUGS("GLTF", "VOCache") << "Read " << cache_entry_map.size() << " entries from object cache " << filename << ", expected " << num_entries << ", success=" << (success?"True":"False") << LL_ENDL;
|
||||
return success;
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map)
|
||||
// We now pass in the cache entry map, so that we can remove entries from extras that are no longer in the primary cache.
|
||||
void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)
|
||||
{
|
||||
int loaded= 0;
|
||||
int discarded = 0;
|
||||
// get ViewerRegion pointer from handle
|
||||
LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle);
|
||||
// </FS:Beq>
|
||||
int loaded= 0;
|
||||
int discarded = 0;
|
||||
// get ViewerRegion pointer from handle
|
||||
LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle);
|
||||
if(!mEnabled)
|
||||
{
|
||||
LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL;
|
||||
|
|
@ -1629,71 +1619,72 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac
|
|||
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
if(!in.good()) {
|
||||
if(!in.good())
|
||||
{
|
||||
LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL;
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
// </FS:Beq>
|
||||
return;
|
||||
}
|
||||
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// file formats need versions, let's add one. legacy cache files will be considered version 0
|
||||
// This will make it easier to upgrade/revise later.
|
||||
int versionNumber=0;
|
||||
if (line.compare(0, LLGLTFOverrideCacheEntry::VERSION_LABEL.length(), LLGLTFOverrideCacheEntry::VERSION_LABEL) == 0)
|
||||
{
|
||||
std::string versionStr = line.substr(LLGLTFOverrideCacheEntry::VERSION_LABEL.length()+1); // skip the version label and ':'
|
||||
versionNumber = std::stol(versionStr);
|
||||
std::getline(in, line); // read the next line for the region UUID check
|
||||
}
|
||||
// </FS:Beq>
|
||||
// For future versions we may call a legacy handler here, but realistically we'll just consider this cache out of date.
|
||||
// The important thing is to make sure it gets removed.
|
||||
if(versionNumber != LLGLTFOverrideCacheEntry::VERSION && versionNumber != 0)
|
||||
{
|
||||
LL_WARNS() << "Unexpected version number " << versionNumber << " for extras cache for handle " << handle << LL_ENDL;
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
LL_DEBUGS("VOCache") << "Reading extras cache for handle " << handle << ", version " << versionNumber << LL_ENDL;
|
||||
|
||||
if(!LLUUID::validate(line))
|
||||
{
|
||||
LL_WARNS() << "Failed reading extras cache for handle" << handle << ". invalid uuid line: '" << line << "'" << LL_ENDL;
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
// </FS:Beq>
|
||||
return;
|
||||
}
|
||||
|
||||
LLUUID cache_id(line);
|
||||
if(cache_id != id)
|
||||
{
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// if the cache id doesn't match the expected region we should just kill the file.
|
||||
LL_WARNS() << "Cache ID doesn't match for this region, deleting it" << LL_ENDL;
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
// </FS:Beq>
|
||||
return;
|
||||
}
|
||||
|
||||
U32 num_entries; // if removal was enabled during write num_entries might be wrong
|
||||
std::getline(in, line);
|
||||
if(!in.good()) {
|
||||
if(!in.good())
|
||||
{
|
||||
LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL;
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
// </FS:Beq>
|
||||
return;
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
num_entries = std::stol(line);
|
||||
}
|
||||
catch(std::logic_error&) // either invalid_argument or out_of_range
|
||||
{
|
||||
LL_WARNS() << "Failed reading extras cache for handle " << handle << ". unreadable num_entries" << LL_ENDL;
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
// </FS:Beq>
|
||||
return;
|
||||
}
|
||||
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_DEBUGS("GLTF") << "Beginning reading extras cache for handle " << handle << " from " << getObjectCacheExtrasFilename(handle) << LL_ENDL;
|
||||
|
||||
LLSD entry_llsd;
|
||||
|
|
@ -1702,22 +1693,19 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac
|
|||
static const U32 max_size = 4096;
|
||||
bool success = LLSDSerialize::deserialize(entry_llsd, in, max_size);
|
||||
// check bool(in) this time since eof is not a failure condition here
|
||||
if(!success || !in) {
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
if(!success || !in)
|
||||
{
|
||||
LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << " cache patrtial load only." << LL_ENDL;
|
||||
in.close();
|
||||
removeGenericExtrasForHandle(handle);
|
||||
break;
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
LLGLTFOverrideCacheEntry entry;
|
||||
entry.fromLLSD(entry_llsd);
|
||||
U32 local_id = entry_llsd["local_id"].asInteger();
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// cache_extras_entry_map[local_id] = entry;
|
||||
// only add entries that exist in the primary cache
|
||||
// this is a self-healing test that avoids us polluting the cache with entries that are no longer valid.
|
||||
// this is a self-healing test that avoids us polluting the cache with entries that are no longer valid based on the main cache.
|
||||
if(cache_entry_map.find(local_id)!= cache_entry_map.end())
|
||||
{
|
||||
// attempt to backfill a null objectId, though these shouldn't be in the persisted cache really
|
||||
|
|
@ -1734,37 +1722,29 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac
|
|||
}
|
||||
}
|
||||
LL_DEBUGS("GLTF") << "Completed reading extras cache for handle " << handle << ", " << loaded << " loaded, " << discarded << " discarded" << LL_ENDL;
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
void LLVOCache::purgeEntries(U32 size)
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_DEBUGS("VOCache","GLTF") << "Purging " << size << " entries from cache" << LL_ENDL;
|
||||
while(mHeaderEntryQueue.size() > size)
|
||||
{
|
||||
header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ;
|
||||
HeaderEntryInfo* entry = *iter ;
|
||||
mHandleEntryMap.erase(entry->mHandle);
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
mHeaderEntryQueue.erase(iter);
|
||||
removeFromCache(entry);
|
||||
// </FS:Beq>
|
||||
HeaderEntryInfo* entry = *iter ;
|
||||
mHandleEntryMap.erase(entry->mHandle) ;
|
||||
mHeaderEntryQueue.erase(iter) ;
|
||||
removeFromCache(entry) ; // This now handles removing extras cache where appropriate.
|
||||
delete entry;
|
||||
|
||||
}
|
||||
mNumEntries = mHandleEntryMap.size() ;
|
||||
}
|
||||
|
||||
void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled)
|
||||
{
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
std::string filename;
|
||||
getObjectCacheFilename(handle, filename);
|
||||
// </FS:Beq>
|
||||
if(!mEnabled)
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently disabled." << LL_ENDL;
|
||||
return ;
|
||||
}
|
||||
|
|
@ -1772,7 +1752,6 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
|
|||
|
||||
if(mReadOnly)
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently in read-only mode." << LL_ENDL;
|
||||
return ;
|
||||
}
|
||||
|
|
@ -1808,14 +1787,12 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
|
|||
//update cache header
|
||||
if(!updateEntry(entry))
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". " << filename << " handle = " << handle << LL_ENDL;
|
||||
return ; //update failed.
|
||||
}
|
||||
|
||||
if(!dirty_cache)
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_WARNS() << "Skipping write to cache for " << filename << " (handle:" << handle << "): cache not dirty" << LL_ENDL;
|
||||
return ; //nothing changed, no need to update.
|
||||
}
|
||||
|
|
@ -1852,7 +1829,6 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
|
|||
}
|
||||
else
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_WARNS() << "Failed to write cache entry to buffer for " << filename << ", entry number " << iter->second->getLocalID() << LL_ENDL;
|
||||
success = false;
|
||||
break;
|
||||
|
|
@ -1865,7 +1841,6 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
|
|||
size_in_buffer = 0;
|
||||
if (!success)
|
||||
{
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_WARNS() << "Failed to write cache to disk " << filename << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1877,15 +1852,12 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
|
|||
{
|
||||
// final write
|
||||
success = check_write(&apr_file, (void*)data_buffer, size_in_buffer);
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
if(!success)
|
||||
{
|
||||
LL_WARNS() << "Failed to write cache entry to disk " << filename << LL_ENDL;
|
||||
}
|
||||
// </FS:Beq>
|
||||
size_in_buffer = 0;
|
||||
}
|
||||
// <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
LL_DEBUGS("VOCache") << "Wrote " << num_entries << " entries to the primary VOCache file " << filename << ". success = " << (success ? "True":"False") << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1898,7 +1870,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
|
|||
|
||||
return ;
|
||||
}
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
|
||||
void LLVOCache::removeGenericExtrasForHandle(U64 handle)
|
||||
{
|
||||
if(mReadOnly)
|
||||
|
|
@ -1909,7 +1881,6 @@ void LLVOCache::removeGenericExtrasForHandle(U64 handle)
|
|||
LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << handle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL;
|
||||
LLFile::remove(getObjectCacheExtrasFilename(handle));
|
||||
}
|
||||
// </FS:Beq>
|
||||
|
||||
void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled)
|
||||
{
|
||||
|
|
@ -1933,27 +1904,6 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL
|
|||
if(!out.good())
|
||||
{
|
||||
LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL;
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// return;
|
||||
// // TODO - clean up broken cache file
|
||||
// }
|
||||
|
||||
// out << id << '\n';
|
||||
// if(!out.good())
|
||||
// {
|
||||
// LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL;
|
||||
// return;
|
||||
// // TODO - clean up broken cache file
|
||||
// }
|
||||
|
||||
// U32 num_entries = cache_extras_entry_map.size();
|
||||
// out << num_entries << '\n';
|
||||
// if(!out.good())
|
||||
// {
|
||||
// LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL;
|
||||
// return;
|
||||
// // TODO - clean up broken cache file
|
||||
// }
|
||||
removeGenericExtrasForHandle(handle);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1965,10 +1915,10 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL
|
|||
if(!out.good())
|
||||
{
|
||||
LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL;
|
||||
removeGenericExtrasForHandle(handle); // <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
removeGenericExtrasForHandle(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// Because we don't write out all the entries we need to record a placeholder and rewrite this later
|
||||
auto num_entries_placeholder = out.tellp();
|
||||
out << std::setw(10) << std::setfill('0') << 0 << '\n';
|
||||
if(!out.good())
|
||||
|
|
@ -1989,17 +1939,17 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL
|
|||
{
|
||||
// Only write out GLTFOverrides that we can actually apply again on import.
|
||||
// worst case we have an extra cache miss.
|
||||
// Note: mObjectId is valid in memory as we might have a data race between GLTF of the object itself.
|
||||
// Note: A null mObjectId is valid when in memory as we might have a data race between GLTF of the object itself.
|
||||
// This remains a valid state to persist as it is consistent with the localid checks on import with the main cache.
|
||||
// the mObjectId will be updated if/when the local object is updated from the gObject list (due to full update)
|
||||
if(entry.mObjectId.isNull() && pRegion)
|
||||
{
|
||||
gObjectList.getUUIDFromLocal( entry.mObjectId, local_id, pRegion->getHost().getAddress(), pRegion->getHost().getPort() );
|
||||
}
|
||||
|
||||
if( /*entry.mObjectId.notNull() &&*/
|
||||
entry.mSides.size() > 0 &&
|
||||
if( entry.mSides.size() > 0 &&
|
||||
entry.mSides.size() == entry.mGLTFMaterial.size()
|
||||
)
|
||||
)
|
||||
{
|
||||
LLSD entry_llsd = entry.toLLSD();
|
||||
entry_llsd["local_id"] = (S32)local_id;
|
||||
|
|
@ -2019,6 +1969,7 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL
|
|||
skipped++;
|
||||
}
|
||||
}
|
||||
// Rewrite the placeholder
|
||||
out.seekp(num_entries_placeholder);
|
||||
out << std::setw(10) << std::setfill('0') << num_entries << '\n';
|
||||
if(!out.good())
|
||||
|
|
|
|||
|
|
@ -291,17 +291,14 @@ public:
|
|||
// We need this init to be separate from constructor, since we might construct cache, purge it, then init.
|
||||
void initCache(ELLPath location, U32 size, U32 cache_version);
|
||||
void removeCache(ELLPath location, bool started = false) ;
|
||||
// <FS:Beq> FIRE-33808 - Material Override Cache causes long delays
|
||||
// void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
|
||||
// void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map);
|
||||
|
||||
bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
|
||||
void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map);
|
||||
// </FS:Beq>
|
||||
|
||||
void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled);
|
||||
void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled);
|
||||
void removeEntry(U64 handle) ;
|
||||
void removeGenericExtrasForHandle(U64 handle); // <FS:Beq/> FIRE-33808 - Material Override Cache causes long delays
|
||||
void removeGenericExtrasForHandle(U64 handle);
|
||||
|
||||
U32 getCacheEntries() { return mNumEntries; }
|
||||
U32 getCacheEntriesMax() { return mCacheSize; }
|
||||
|
|
|
|||
|
|
@ -4842,7 +4842,7 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const
|
|||
|
||||
|
||||
BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
|
||||
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
|
||||
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
|
||||
{
|
||||
if (!mbCanSelect
|
||||
|| mDrawable->isDead()
|
||||
|
|
@ -5049,7 +5049,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -411,6 +411,114 @@ private:
|
|||
return parseValues(status_string, "", param);
|
||||
}
|
||||
|
||||
LLSD parseValue(std::string& status_string, const std::string& key, const std::string& key_pfx, XMLRPC_VALUE param)
|
||||
{
|
||||
LLSD response;
|
||||
|
||||
XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(param);
|
||||
switch (type)
|
||||
{
|
||||
case xmlrpc_type_empty:
|
||||
LL_INFOS("LLXMLRPCListener") << "Empty result for key " << key_pfx << key << LL_ENDL;
|
||||
break;
|
||||
case xmlrpc_type_base64:
|
||||
{
|
||||
S32 len = XMLRPC_GetValueStringLen(param);
|
||||
const char* buf = XMLRPC_GetValueBase64(param);
|
||||
if ((len > 0) && buf)
|
||||
{
|
||||
// During implementation this code was not tested
|
||||
// If you encounter this, please make sure this is correct,
|
||||
// then remove llassert
|
||||
llassert(0);
|
||||
|
||||
LLSD::Binary data;
|
||||
data.resize(len);
|
||||
memcpy((void*)&data[0], (void*)buf, len);
|
||||
response = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("LLXMLRPCListener") << "Potentially malformed xmlrpc_type_base64 for key "
|
||||
<< key_pfx << key << LL_ENDL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_boolean:
|
||||
{
|
||||
response = LLSD::Boolean(XMLRPC_GetValueBoolean(param));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_datetime:
|
||||
{
|
||||
std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(param));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << iso8601_date << LL_ENDL;
|
||||
response = LLSD::Date(iso8601_date);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_double:
|
||||
{
|
||||
response = LLSD::Real(XMLRPC_GetValueDouble(param));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_int:
|
||||
{
|
||||
response = LLSD::Integer(XMLRPC_GetValueInt(param));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_string:
|
||||
{
|
||||
response = LLSD::String(XMLRPC_GetValueString(param));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_mixed:
|
||||
case xmlrpc_type_array:
|
||||
{
|
||||
// We expect this to be an array of submaps. Walk the array,
|
||||
// recursively parsing each submap and collecting them.
|
||||
LLSD array;
|
||||
int i = 0; // for descriptive purposes
|
||||
for (XMLRPC_VALUE row = XMLRPC_VectorRewind(param); row;
|
||||
row = XMLRPC_VectorNext(param), ++i)
|
||||
{
|
||||
// Recursive call. For the lower-level key_pfx, if 'key'
|
||||
// is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
|
||||
// nested call, a subkey "bar" will then be logged as
|
||||
// "foo[0]:bar", and so forth.
|
||||
// Parse the scalar subkey/value pairs from this array
|
||||
// entry into a temp submap. Collect such submaps in 'array'.
|
||||
|
||||
array.append(parseValue(status_string, "",
|
||||
STRINGIZE(key_pfx << key << '[' << i << "]:"),
|
||||
row));
|
||||
}
|
||||
// Having collected an 'array' of 'submap's, insert that whole
|
||||
// 'array' as the value of this 'key'.
|
||||
response = array;
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_struct:
|
||||
{
|
||||
response = parseValues(status_string,
|
||||
STRINGIZE(key_pfx << key << ':'),
|
||||
param);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_none: // Not expected
|
||||
default:
|
||||
// whoops - unrecognized type
|
||||
LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key "
|
||||
<< key_pfx << key << LL_ENDL;
|
||||
response = STRINGIZE("<bad XMLRPC type " << type << '>');
|
||||
status_string = "BadType";
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map.
|
||||
* @param key_pfx Used to describe a given key in log messages. At top
|
||||
|
|
@ -428,113 +536,7 @@ private:
|
|||
{
|
||||
std::string key(XMLRPC_GetValueID(current));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL;
|
||||
XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current);
|
||||
switch (type)
|
||||
{
|
||||
case xmlrpc_type_empty:
|
||||
LL_INFOS("LLXMLRPCListener") << "Empty result for key " << key_pfx << key << LL_ENDL;
|
||||
responses.insert(key, LLSD());
|
||||
break;
|
||||
case xmlrpc_type_base64:
|
||||
{
|
||||
S32 len = XMLRPC_GetValueStringLen(current);
|
||||
const char* buf = XMLRPC_GetValueBase64(current);
|
||||
if ((len > 0) && buf)
|
||||
{
|
||||
// During implementation this code was not tested
|
||||
// If you encounter this, please make sure this is correct,
|
||||
// then remove llassert
|
||||
llassert(0);
|
||||
|
||||
LLSD::Binary data;
|
||||
data.resize(len);
|
||||
memcpy((void*)&data[0], (void*)buf, len);
|
||||
responses.insert(key, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("LLXMLRPCListener") << "Potentially malformed xmlrpc_type_base64 for key "
|
||||
<< key_pfx << key << LL_ENDL;
|
||||
responses.insert(key, LLSD());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_boolean:
|
||||
{
|
||||
LLSD::Boolean val(XMLRPC_GetValueBoolean(current));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
|
||||
responses.insert(key, val);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_datetime:
|
||||
{
|
||||
std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(current));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << iso8601_date << LL_ENDL;
|
||||
responses.insert(key, LLSD::Date(iso8601_date));
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_double:
|
||||
{
|
||||
LLSD::Real val(XMLRPC_GetValueDouble(current));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
|
||||
responses.insert(key, val);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_int:
|
||||
{
|
||||
LLSD::Integer val(XMLRPC_GetValueInt(current));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
|
||||
responses.insert(key, val);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_string:
|
||||
{
|
||||
LLSD::String val(XMLRPC_GetValueString(current));
|
||||
LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
|
||||
responses.insert(key, val);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_mixed:
|
||||
case xmlrpc_type_array:
|
||||
{
|
||||
// We expect this to be an array of submaps. Walk the array,
|
||||
// recursively parsing each submap and collecting them.
|
||||
LLSD array;
|
||||
int i = 0; // for descriptive purposes
|
||||
for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row;
|
||||
row = XMLRPC_VectorNext(current), ++i)
|
||||
{
|
||||
// Recursive call. For the lower-level key_pfx, if 'key'
|
||||
// is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
|
||||
// nested call, a subkey "bar" will then be logged as
|
||||
// "foo[0]:bar", and so forth.
|
||||
// Parse the scalar subkey/value pairs from this array
|
||||
// entry into a temp submap. Collect such submaps in 'array'.
|
||||
array.append(parseValues(status_string,
|
||||
STRINGIZE(key_pfx << key << '[' << i << "]:"),
|
||||
row));
|
||||
}
|
||||
// Having collected an 'array' of 'submap's, insert that whole
|
||||
// 'array' as the value of this 'key'.
|
||||
responses.insert(key, array);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_struct:
|
||||
{
|
||||
LLSD submap = parseValues(status_string,
|
||||
STRINGIZE(key_pfx << key << ':'),
|
||||
current);
|
||||
responses.insert(key, submap);
|
||||
break;
|
||||
}
|
||||
case xmlrpc_type_none: // Not expected
|
||||
default:
|
||||
// whoops - unrecognized type
|
||||
LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key "
|
||||
<< key_pfx << key << LL_ENDL;
|
||||
responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>'));
|
||||
status_string = "BadType";
|
||||
}
|
||||
responses.insert(key, parseValue(status_string, key, key_pfx, current));
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@
|
|||
#include "llscenemonitor.h"
|
||||
#include "llprogressview.h"
|
||||
#include "llcleanup.h"
|
||||
#include "gltfscenemanager.h"
|
||||
// [RLVa:KB] - Checked: RLVa-2.0.0
|
||||
#include "llvisualeffect.h"
|
||||
#include "rlvactions.h"
|
||||
|
|
@ -858,6 +859,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
|
||||
if (RenderMirrors)
|
||||
{
|
||||
mHeroProbeManager.initReflectionMaps();
|
||||
res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it.
|
||||
mRT = &mHeroProbeRT;
|
||||
allocateScreenBuffer(res, res, samples);
|
||||
|
|
@ -1254,6 +1256,12 @@ void LLPipeline::releaseScreenBuffers()
|
|||
mRT->fxaaBuffer.release();
|
||||
mRT->deferredScreen.release();
|
||||
mRT->deferredLight.release();
|
||||
|
||||
mHeroProbeRT.uiScreen.release();
|
||||
mHeroProbeRT.screen.release();
|
||||
mHeroProbeRT.fxaaBuffer.release();
|
||||
mHeroProbeRT.deferredScreen.release();
|
||||
mHeroProbeRT.deferredLight.release();
|
||||
}
|
||||
|
||||
void LLPipeline::releaseSunShadowTarget(U32 index)
|
||||
|
|
@ -4671,6 +4679,8 @@ void LLPipeline::renderDebug()
|
|||
}
|
||||
}
|
||||
|
||||
LL::GLTFSceneManager::instance().renderDebug();
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
|
||||
{ //render visible selected group occlusion geometry
|
||||
gDebugProgram.bind();
|
||||
|
|
@ -6482,6 +6492,15 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 node_hit = -1;
|
||||
S32 primitive_hit = -1;
|
||||
LLDrawable* hit = LL::GLTFSceneManager::instance().lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, &node_hit, &primitive_hit, &position, tex_coord, normal, tangent);
|
||||
if (hit)
|
||||
{
|
||||
drawable = hit;
|
||||
local_end = position;
|
||||
}
|
||||
|
||||
if (!sPickAvatar)
|
||||
{
|
||||
|
|
@ -6698,6 +6717,11 @@ void LLPipeline::renderGLTFObjects(U32 type, bool texture, bool rigged)
|
|||
|
||||
gGL.loadMatrix(gGLModelView);
|
||||
gGLLastMatrix = NULL;
|
||||
|
||||
if (!rigged)
|
||||
{
|
||||
LL::GLTFSceneManager::instance().renderOpaque();
|
||||
}
|
||||
}
|
||||
|
||||
// Currently only used for shadows -Cosmic,2023-04-19
|
||||
|
|
|
|||
|
|
@ -335,42 +335,10 @@
|
|||
name="FSAADisabled"
|
||||
value="0" />
|
||||
<combo_box.item
|
||||
label="2x"
|
||||
name="2x"
|
||||
label="FXAA"
|
||||
name="FXAA"
|
||||
value="2" />
|
||||
<combo_box.item
|
||||
label="4x"
|
||||
name="4x"
|
||||
value="4" />
|
||||
<combo_box.item
|
||||
label="8x"
|
||||
name="8x"
|
||||
value="8" />
|
||||
<combo_box.item
|
||||
label="16x"
|
||||
name="16x"
|
||||
value="16" />
|
||||
</combo_box>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
name="antialiasing restart"
|
||||
top_delta="0"
|
||||
width="130">
|
||||
(requires restart)
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="in"
|
||||
height="322"
|
||||
layout="topleft"
|
||||
left="385"
|
||||
name="vert_border"
|
||||
top="16"
|
||||
width="0"/>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -378,23 +346,22 @@
|
|||
height="16"
|
||||
layout="topleft"
|
||||
name="MeshText"
|
||||
top_delta="20"
|
||||
left="400"
|
||||
top="21"
|
||||
top_delta="16"
|
||||
left="10"
|
||||
width="128">
|
||||
Mesh
|
||||
Mesh
|
||||
</text>
|
||||
|
||||
<slider
|
||||
control_name="RenderTerrainLODFactor"
|
||||
follows="left|top"
|
||||
follows="topleft"
|
||||
height="16"
|
||||
increment="0.125"
|
||||
initial_value="160"
|
||||
label="Terrain Mesh Detail:"
|
||||
label_width="185"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
left="30"
|
||||
min_val="1"
|
||||
max_val="2"
|
||||
name="TerrainMeshDetail"
|
||||
|
|
@ -408,7 +375,7 @@
|
|||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
follows="topleft"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
name="TerrainMeshDetailText"
|
||||
|
|
@ -416,19 +383,19 @@
|
|||
top_delta="0"
|
||||
left_delta="304"
|
||||
width="65">
|
||||
Low
|
||||
Low
|
||||
</text>
|
||||
|
||||
<slider
|
||||
control_name="RenderTreeLODFactor"
|
||||
follows="left|top"
|
||||
follows="topleft"
|
||||
height="16"
|
||||
increment="0.125"
|
||||
initial_value="160"
|
||||
label="Trees:"
|
||||
label_width="185"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
left="30"
|
||||
name="TreeMeshDetail"
|
||||
show_text="false"
|
||||
top_delta="16"
|
||||
|
|
@ -447,7 +414,7 @@
|
|||
top_delta="0"
|
||||
left_delta="304"
|
||||
width="65">
|
||||
Low
|
||||
Low
|
||||
</text>
|
||||
|
||||
<slider
|
||||
|
|
@ -459,7 +426,7 @@
|
|||
label="Objects:"
|
||||
label_width="185"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
left="30"
|
||||
min_val="0"
|
||||
max_val="4"
|
||||
name="ObjectMeshDetail"
|
||||
|
|
@ -480,7 +447,7 @@
|
|||
top_delta="0"
|
||||
left_delta="304"
|
||||
width="65">
|
||||
Low
|
||||
Low
|
||||
</text>
|
||||
|
||||
<slider
|
||||
|
|
@ -491,7 +458,7 @@
|
|||
label="Flexiprims:"
|
||||
label_width="185"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
left="30"
|
||||
name="FlexibleMeshDetail"
|
||||
show_text="false"
|
||||
top_delta="16"
|
||||
|
|
@ -510,8 +477,28 @@
|
|||
top_delta="0"
|
||||
left_delta="304"
|
||||
width="65">
|
||||
Low
|
||||
Low
|
||||
</text>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
name="antialiasing restart"
|
||||
top_delta="0"
|
||||
width="130">
|
||||
(requires restart)
|
||||
</text>
|
||||
<view_border
|
||||
bevel_style="in"
|
||||
height="322"
|
||||
layout="topleft"
|
||||
left="385"
|
||||
name="vert_border"
|
||||
top="16"
|
||||
width="0"/>
|
||||
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -520,7 +507,7 @@
|
|||
height="16"
|
||||
layout="topleft"
|
||||
name="ShadersText"
|
||||
top_delta="20"
|
||||
top_delta="-10"
|
||||
left="400"
|
||||
width="128">
|
||||
Shaders
|
||||
|
|
@ -747,6 +734,102 @@
|
|||
width="260">
|
||||
</slider>
|
||||
|
||||
<!-- Mirror settings. -->
|
||||
<check_box
|
||||
control_name="RenderMirrors"
|
||||
height="16"
|
||||
initial_value="false"
|
||||
label="Mirrors"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
name="Mirrors"
|
||||
top_delta="24"
|
||||
width="240">
|
||||
<check_box.commit_callback
|
||||
function="Pref.RenderOptionUpdate" />
|
||||
</check_box>
|
||||
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
name="MirrorResolutionText"
|
||||
text_readonly_color="LabelDisabledColor"
|
||||
top_delta="22"
|
||||
width="128">
|
||||
Mirror Resolution:
|
||||
</text>
|
||||
|
||||
<combo_box
|
||||
control_name="RenderHeroProbeResolution"
|
||||
height="18"
|
||||
layout="topleft"
|
||||
left_delta="130"
|
||||
top_delta="0"
|
||||
name="MirrorResolution"
|
||||
width="150">
|
||||
<combo_box.item
|
||||
label="256"
|
||||
name="0"
|
||||
value="256"/>
|
||||
<combo_box.item
|
||||
label="512"
|
||||
name="1"
|
||||
value="512"/>
|
||||
<combo_box.item
|
||||
label="1024"
|
||||
name="2"
|
||||
value="1024"/>
|
||||
<combo_box.item
|
||||
label="2048"
|
||||
name="3"
|
||||
value="2048"/>
|
||||
</combo_box>
|
||||
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
layout="topleft"
|
||||
left="420"
|
||||
name="HeroProbeUpdateText"
|
||||
text_readonly_color="LabelDisabledColor"
|
||||
top_delta="22"
|
||||
width="128">
|
||||
Mirror Update Rate:
|
||||
</text>
|
||||
|
||||
<combo_box
|
||||
control_name="RenderHeroProbeUpdateRate"
|
||||
height="18"
|
||||
layout="topleft"
|
||||
left_delta="130"
|
||||
top_delta="0"
|
||||
name="HeroProbeUpdateRate"
|
||||
width="150">
|
||||
<combo_box.item
|
||||
label="Every Frame"
|
||||
name="0"
|
||||
value="1"/>
|
||||
<combo_box.item
|
||||
label="Every 2nd Frame"
|
||||
name="1"
|
||||
value="2"/>
|
||||
<combo_box.item
|
||||
label="Every 3rd Frame"
|
||||
name="2"
|
||||
value="3"/>
|
||||
<combo_box.item
|
||||
label="Every 4th Frame"
|
||||
name="3"
|
||||
value="4"/>
|
||||
</combo_box>
|
||||
<!-- End of mirror settings -->
|
||||
|
||||
<!-- End of Advanced Settings block -->
|
||||
<view_border
|
||||
bevel_style="in"
|
||||
|
|
|
|||
|
|
@ -4124,6 +4124,12 @@
|
|||
<menu_item_call.on_click
|
||||
function="Advanced.ClickHDRIPreview" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="GLTF Scene Preview"
|
||||
name="GLTF Scene Preview">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ClickGLTFScenePreview" />
|
||||
</menu_item_call>
|
||||
</menu>
|
||||
<menu
|
||||
create_jump_keys="true"
|
||||
|
|
|
|||
|
|
@ -14291,7 +14291,18 @@ If you want to see this object, remove it and re-attach it to an avatar attachme
|
|||
name="okignore"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="GLTFPreviewSelection"
|
||||
type="alert">
|
||||
You must select an object to act as a handle to the GLTF asset you are previewing.
|
||||
<tag>fail</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
|
|
|
|||
|
|
@ -221,26 +221,15 @@
|
|||
width="80">
|
||||
Ultra
|
||||
</text>
|
||||
<check_box
|
||||
control_name="FullScreen"
|
||||
height="16"
|
||||
initial_value="false"
|
||||
label="Fullscreen Mode"
|
||||
layout="topleft"
|
||||
left="4"
|
||||
name="Fullscreen Mode"
|
||||
tool_tip="Run Firestorm in Fullscreen mode. A restart is required to change mode."
|
||||
top="80"
|
||||
width="280" />
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="12"
|
||||
layout="topleft"
|
||||
left_delta="1"
|
||||
left="4"
|
||||
name="ShadersText"
|
||||
top_pad="5"
|
||||
top="70"
|
||||
width="128">
|
||||
Shaders:
|
||||
</text>
|
||||
|
|
@ -283,6 +272,19 @@
|
|||
<check_box.commit_callback
|
||||
function="Pref.RenderOptionUpdate" />
|
||||
</check_box>
|
||||
<check_box
|
||||
control_name="RenderMirrors"
|
||||
height="16"
|
||||
initial_value="false"
|
||||
label="Mirrors"
|
||||
layout="topleft"
|
||||
left_delta="0"
|
||||
name="Mirrors"
|
||||
top_pad="1"
|
||||
width="280">
|
||||
<check_box.commit_callback
|
||||
function="Pref.RenderOptionUpdate" />
|
||||
</check_box>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -391,8 +393,6 @@
|
|||
name="3"
|
||||
value="3"/>
|
||||
</combo_box>
|
||||
<!-- FS:TM Avatar Physics was moved down to LOD section-->
|
||||
<!-- FS:TM Point Lighting added instead of above-->
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -428,7 +428,101 @@
|
|||
name="1"
|
||||
value="1"/>
|
||||
</combo_box>
|
||||
|
||||
<!-- Mirror settings. -->
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="12"
|
||||
layout="topleft"
|
||||
left_delta="-5"
|
||||
name="MirrorResolutionText"
|
||||
text_readonly_color="LabelDisabledColor"
|
||||
top_pad="4"
|
||||
width="170">
|
||||
Mirror Resolution:
|
||||
</text>
|
||||
<combo_box
|
||||
control_name="RenderHeroProbeResolution"
|
||||
enabled_control="RenderMirrors"
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left_delta="5"
|
||||
top_pad="3"
|
||||
name="MirrorResolution"
|
||||
width="150">
|
||||
<combo_box.item
|
||||
label="256"
|
||||
name="0"
|
||||
value="256"/>
|
||||
<combo_box.item
|
||||
label="512"
|
||||
name="1"
|
||||
value="512"/>
|
||||
<combo_box.item
|
||||
label="1024"
|
||||
name="2"
|
||||
value="1024"/>
|
||||
<combo_box.item
|
||||
label="2048"
|
||||
name="3"
|
||||
value="2048"/>
|
||||
</combo_box>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="12"
|
||||
layout="topleft"
|
||||
left_delta="-5"
|
||||
name="HeroProbeUpdateText"
|
||||
text_readonly_color="LabelDisabledColor"
|
||||
top_pad="4"
|
||||
width="170">
|
||||
Mirror Update Rate:
|
||||
</text>
|
||||
<combo_box
|
||||
control_name="RenderHeroProbeUpdateRate"
|
||||
enabled_control="RenderMirrors"
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left_delta="5"
|
||||
top_pad="3"
|
||||
name="HeroProbeUpdateRate"
|
||||
width="150">
|
||||
<combo_box.item
|
||||
label="Every Frame"
|
||||
name="0"
|
||||
value="1"/>
|
||||
<combo_box.item
|
||||
label="Every 2nd Frame"
|
||||
name="1"
|
||||
value="2"/>
|
||||
<combo_box.item
|
||||
label="Every 3rd Frame"
|
||||
name="2"
|
||||
value="3"/>
|
||||
<combo_box.item
|
||||
label="Every 4th Frame"
|
||||
name="3"
|
||||
value="4"/>
|
||||
</combo_box>
|
||||
<!-- End of mirror settings -->
|
||||
|
||||
<!--Top of second column in General tab-->
|
||||
<check_box
|
||||
control_name="FullScreen"
|
||||
height="16"
|
||||
initial_value="false"
|
||||
label="Fullscreen Mode"
|
||||
layout="topleft"
|
||||
left="196"
|
||||
name="Fullscreen Mode"
|
||||
tool_tip="Run Firestorm in Fullscreen mode. A restart is required to change mode."
|
||||
top="80"
|
||||
width="280" />
|
||||
|
||||
<slider
|
||||
control_name="RenderFarClip"
|
||||
decimal_digits="0"
|
||||
|
|
@ -443,7 +537,7 @@
|
|||
max_val="1024"
|
||||
min_val="32"
|
||||
name="DrawDistance"
|
||||
top="80"
|
||||
top_pad="6"
|
||||
width="301" />
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -877,21 +971,9 @@
|
|||
name="FSAADisabled"
|
||||
value="0" />
|
||||
<combo_box.item
|
||||
label="2x"
|
||||
name="2x"
|
||||
label="FXAA"
|
||||
name="FXAA"
|
||||
value="2" />
|
||||
<combo_box.item
|
||||
label="4x"
|
||||
name="4x"
|
||||
value="4" />
|
||||
<combo_box.item
|
||||
label="8x"
|
||||
name="8x"
|
||||
value="8" />
|
||||
<combo_box.item
|
||||
label="16x"
|
||||
name="16x"
|
||||
value="16" />
|
||||
</combo_box>
|
||||
</panel>
|
||||
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
|
|||
# 'secondlife-bin.*',
|
||||
# '*_Setup.exe',
|
||||
# '*.bat',
|
||||
# '*.tar.bz2')))
|
||||
# '*.tar.xz')))
|
||||
# </FS:Ansariel>
|
||||
|
||||
# <FS:Ansariel> Remove VMP
|
||||
|
|
|
|||
Loading…
Reference in New Issue