summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-06-13 18:33:49 +0300
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-06-13 21:49:02 +0300
commit54660c8931593ceb465605acf872d5227e1d2d63 (patch)
tree6460f98d9e12a5640d93516a39ccc78aabdcf76b
parent8322a9a61e951275278fbf80b0a46880f5318107 (diff)
#4147 Joint Overrides #3
Remande skeleton translation from default skeleton to overriden skeleton
-rw-r--r--indra/llappearance/CMakeLists.txt1
-rw-r--r--indra/llappearance/llavatarappearance.cpp36
-rw-r--r--indra/llappearance/llavatarappearance.h3
-rw-r--r--indra/llappearance/lljointdata.h44
-rw-r--r--indra/newview/gltf/llgltfloader.cpp162
-rw-r--r--indra/newview/gltf/llgltfloader.h39
-rw-r--r--indra/newview/llmodelpreview.cpp9
7 files changed, 223 insertions, 71 deletions
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
index c3be8bc78e..6744c8d8a4 100644
--- a/indra/llappearance/CMakeLists.txt
+++ b/indra/llappearance/CMakeLists.txt
@@ -14,6 +14,7 @@ set(llappearance_SOURCE_FILES
llavatarjoint.cpp
llavatarjointmesh.cpp
lldriverparam.cpp
+ lljointdata.h
lllocaltextureobject.cpp
llpolyskeletaldistortion.cpp
llpolymesh.cpp
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index f3e474dba7..13bea1e5ea 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -29,6 +29,7 @@
#include "llavatarappearance.h"
#include "llavatarappearancedefines.h"
#include "llavatarjointmesh.h"
+#include "lljointdata.h"
#include "llstl.h"
#include "lldir.h"
#include "llpolymorph.h"
@@ -108,11 +109,9 @@ public:
private:
typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t;
- static void getJointRestMatrices(
- const bone_info_list_t& bone_list,
- const std::string &parent_name,
- LLAvatarAppearance::joint_rest_map_t& rest,
- LLAvatarAppearance::joint_parent_map_t& parent_map,
+ static void getJointMatricesAndHierarhy(
+ LLAvatarBoneInfo* bone_info,
+ LLJointData& data,
const glm::mat4& parent_mat);
private:
@@ -1677,19 +1676,18 @@ bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
return true;
}
-void LLAvatarSkeletonInfo::getJointRestMatrices(
- const bone_info_list_t& bone_list,
- const std::string& parent_name,
- LLAvatarAppearance::joint_rest_map_t& rest,
- LLAvatarAppearance::joint_parent_map_t& parent_map,
+void LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(
+ LLAvatarBoneInfo* bone_info,
+ LLJointData& data,
const glm::mat4& parent_mat)
{
- for (LLAvatarBoneInfo* bone_info : bone_list)
+ data.mName = bone_info->mName;
+ data.mJointMatrix = bone_info->getJointMatrix();
+ data.mRestMatrix = parent_mat * data.mJointMatrix;
+ for (LLAvatarBoneInfo* child_info : bone_info->mChildren)
{
- glm::mat4 rest_mat = parent_mat * bone_info->getJointMatrix();
- rest[bone_info->mName] = rest_mat;
- parent_map[bone_info->mName] = parent_name;
- getJointRestMatrices(bone_info->mChildren, bone_info->mName, rest, parent_map, rest_mat);
+ LLJointData& child_data = data.mChildren.emplace_back();
+ getJointMatricesAndHierarhy(child_info, child_data, data.mRestMatrix);
}
}
@@ -1754,10 +1752,14 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases
return mJointAliasMap;
}
-void LLAvatarAppearance:: getJointRestMatrices(LLAvatarAppearance::joint_rest_map_t& rest_map, LLAvatarAppearance::joint_parent_map_t& parent_map) const
+void LLAvatarAppearance::getJointMatricesAndHierarhy(std::vector<LLJointData> &data) const
{
glm::mat4 identity(1.f);
- LLAvatarSkeletonInfo::getJointRestMatrices(sAvatarSkeletonInfo->mBoneInfoList, std::string(), rest_map, parent_map, identity);
+ for (LLAvatarBoneInfo* bone_info : sAvatarSkeletonInfo->mBoneInfoList)
+ {
+ LLJointData& child_data = data.emplace_back();
+ LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(bone_info, child_data, identity);
+ }
}
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index e48d80b8ce..2748da9a1d 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -42,6 +42,7 @@ class LLTexGlobalColorInfo;
class LLWearableData;
class LLAvatarBoneInfo;
class LLAvatarSkeletonInfo;
+class LLJointData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLAvatarAppearance
@@ -156,7 +157,7 @@ public:
const joint_alias_map_t& getJointAliases();
typedef std::map<std::string, std::string> joint_parent_map_t; // matrix plus parent
typedef std::map<std::string, glm::mat4> joint_rest_map_t;
- void getJointRestMatrices(joint_rest_map_t& rest_map, joint_parent_map_t& parent_map) const;
+ void getJointMatricesAndHierarhy(std::vector<LLJointData> &data) const;
protected:
static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree);
diff --git a/indra/llappearance/lljointdata.h b/indra/llappearance/lljointdata.h
new file mode 100644
index 0000000000..549f4af041
--- /dev/null
+++ b/indra/llappearance/lljointdata.h
@@ -0,0 +1,44 @@
+/**
+ * @file lljointdata.h
+ * @brief LLJointData class for holding individual joint data and skeleton
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLJOINTDATA_H
+#define LL_LLJOINTDATA_H
+
+#include "v4math.h"
+
+// may be just move LLAvatarBoneInfo
+class LLJointData
+{
+public:
+ std::string mName;
+ glm::mat4 mJointMatrix;
+ glm::mat4 mRestMatrix;
+
+ typedef std::vector<LLJointData> bones_t;
+ bones_t mChildren;
+};
+
+#endif //LL_LLJOINTDATA_H
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 292fd09035..c6d2bec238 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -95,8 +95,7 @@ LLGLTFLoader::LLGLTFLoader(std::string filename,
std::map<std::string, std::string> &jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit,
- joint_viewer_rest_map_t jointRestMatrices,
- joint_viewer_parent_map_t jointParentMap) //,
+ std::vector<LLJointData> viewer_skeleton) //,
//bool preprocess)
: LLModelLoader( filename,
lod,
@@ -113,8 +112,7 @@ LLGLTFLoader::LLGLTFLoader(std::string filename,
, mMeshesLoaded(false)
, mMaterialsLoaded(false)
, mGeneratedModelLimit(modelLimit)
- , mJointViewerRestMatrices(jointRestMatrices)
- , mJointViewerParentMap(jointParentMap)
+ , mViewerJointData(viewer_skeleton)
{
}
@@ -934,13 +932,45 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
mAlternateBindMatrices.resize(skin_idx + 1);
}
- // Build gltf rest matrices
- // This is very inefficienct, todo: run from root to children, not from children to root
- joint_node_mat4_map_t gltf_rest_map;
+ // fill up joints related data
+ joints_data_map_t joints_data;
+ joints_name_to_node_map_t names_to_nodes;
for (S32 i = 0; i < joint_count; i++)
{
S32 joint = skin.mJoints[i];
- gltf_rest_map[joint] = buildGltfRestMatrix(joint, skin);
+ LL::GLTF::Node jointNode = mGLTFAsset.mNodes[joint];
+ JointNodeData& data = joints_data[joint];
+ data.mNodeIdx = joint;
+ data.mJointListIdx = i;
+ data.mGltfRestMatrix = buildGltfRestMatrix(joint, skin);
+ data.mGltfMatrix = jointNode.mMatrix;
+ data.mOverrideMatrix = glm::mat4(1.f);
+
+ if (mJointMap.find(jointNode.mName) != mJointMap.end())
+ {
+ data.mName = mJointMap[jointNode.mName];
+ data.mIsValidViewerJoint = true;
+ }
+ else
+ {
+ data.mName = jointNode.mName;
+ data.mIsValidViewerJoint = false;
+ }
+ names_to_nodes[data.mName] = joint;
+
+ for (S32 child : jointNode.mChildren)
+ {
+ JointNodeData& child_data = joints_data[child];
+ child_data.mParentNodeIdx = joint;
+ child_data.mIsParentValidViewerJoint = data.mIsValidViewerJoint;
+ }
+ }
+
+ // Go over viewer joints and build overrides
+ glm::mat4 ident(1.0);
+ for (auto &viewer_data : mViewerJointData)
+ {
+ buildOverrideMatrix(viewer_data, joints_data, names_to_nodes, ident, ident);
}
for (S32 i = 0; i < joint_count; i++)
@@ -971,7 +1001,7 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
// todo: probably should be 'to viewer's overriden skeleton'
glm::mat4 original_bind_matrix = glm::inverse(skin.mInverseBindMatricesData[i]);
glm::mat4 rotated_original = coord_system_rotation * original_bind_matrix;
- glm::mat4 skeleton_transform = computeGltfToViewerSkeletonTransform(gltf_rest_map, joint, legal_name);
+ glm::mat4 skeleton_transform = computeGltfToViewerSkeletonTransform(joints_data, joint, legal_name);
glm::mat4 tranlated_original = skeleton_transform * rotated_original;
glm::mat4 final_inverse_bind_matrix = glm::inverse(tranlated_original);
@@ -985,7 +1015,7 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
// assume an identy matrix
// todo: find a model with this, might need to use rotated matrix
glm::mat4 inv_bind(1.0f);
- glm::mat4 skeleton_transform = computeGltfToViewerSkeletonTransform(gltf_rest_map, joint, legal_name);
+ glm::mat4 skeleton_transform = computeGltfToViewerSkeletonTransform(joints_data, joint, legal_name);
inv_bind = glm::inverse(skeleton_transform * inv_bind);
LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(inv_bind));
@@ -994,37 +1024,15 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
}
// Compute Alternative matrices also known as overrides
-
- glm::mat4 joint_mat = glm::mat4(1.f);
- if (legal_joint)
- {
- joint_viewer_parent_map_t::const_iterator found = mJointViewerParentMap.find(legal_name);
- if (found != mJointViewerParentMap.end() && !found->second.empty())
- {
- glm::mat4 gltf_joint_rest_pose = coord_system_rotation * buildGltfRestMatrix(joint, skin);
- if (mApplyXYRotation)
- {
- gltf_joint_rest_pose = coord_system_rotationxy * gltf_joint_rest_pose;
- }
- // Compute viewer's override by moving joint to viewer's base
- // This might be overused or somewhat incorect for regular cases
- // But this logic should be solid for cases where model lacks
- // parent joints that viewer has.
- // ex: like boots that have only knees and feet, but no pelvis,
- // or anything else, in which case we take viewer's pelvis
- glm::mat4 viewer_rest = mJointViewerRestMatrices[found->second];
- joint_mat = glm::inverse(viewer_rest) * gltf_joint_rest_pose;
- }
- }
- LLMatrix4 original_joint_transform(glm::value_ptr(joint_mat));
+ LLMatrix4 original_joint_transform(glm::value_ptr(joints_data[joint].mOverrideMatrix));
// Viewer seems to care only about translation part,
// but for parity with collada taking original value
LLMatrix4 newInverse = LLMatrix4(mInverseBindMatrices[skin_idx].back().getF32ptr());
newInverse.setTranslation(original_joint_transform.getTranslation());
- LL_INFOS("GLTF_DEBUG") << "mAlternateBindMatrix name: " << legal_name << " val: " << original_joint_transform << LL_ENDL;
- mAlternateBindMatrices[skin_idx].push_back(LLMatrix4a(original_joint_transform));
+ LL_INFOS("GLTF_DEBUG") << "mAlternateBindMatrix name: " << legal_name << " val: " << newInverse << LL_ENDL;
+ mAlternateBindMatrices[skin_idx].push_back(LLMatrix4a(newInverse));
if (legal_joint)
{
@@ -1139,6 +1147,57 @@ S32 LLGLTFLoader::findParentNode(S32 node) const
return -1;
}
+void LLGLTFLoader::buildOverrideMatrix(LLJointData& viewer_data, joints_data_map_t &gltf_nodes, joints_name_to_node_map_t &names_to_nodes, glm::mat4& parent_rest, glm::mat4& leftover) const
+{
+ glm::mat4 new_lefover(1.f);
+ glm::mat4 rest(1.f);
+ joints_name_to_node_map_t::iterator found_node = names_to_nodes.find(viewer_data.mName);
+ if (found_node != names_to_nodes.end())
+ {
+ S32 gltf_node_idx = found_node->second;
+ JointNodeData& node = gltf_nodes[gltf_node_idx];
+ node.mIsOverrideValid = true;
+
+ glm::mat4 gltf_joint_rest_pose = coord_system_rotation * node.mGltfRestMatrix;
+ if (mApplyXYRotation)
+ {
+ gltf_joint_rest_pose = coord_system_rotationxy * gltf_joint_rest_pose;
+ }
+ node.mOverrideMatrix = glm::inverse(parent_rest) * gltf_joint_rest_pose;
+
+ glm::vec3 override;
+ glm::vec3 skew;
+ glm::vec3 scale;
+ glm::vec4 perspective;
+ glm::quat rotation;
+ glm::decompose(node.mOverrideMatrix, scale, rotation, override, skew, perspective);
+ glm::vec3 translate;
+ glm::decompose(viewer_data.mJointMatrix, scale, rotation, translate, skew, perspective);
+ glm::mat4 viewer_joint = glm::recompose(scale, rotation, override, skew, perspective);
+
+ node.mOverrideMatrix = viewer_joint;
+ rest = parent_rest * viewer_joint;
+ node.mOverrideRestMatrix = rest;
+ if (viewer_data.mName == "mPelvis")
+ {
+ // Todo: This is wrong, but this is a temporary
+ // solution for parts staying behind.
+ // Something is still missing with override mechanics
+ node.mOverrideMatrix = glm::mat4(1.f);
+ }
+ }
+ else
+ {
+ // No override for this joint
+ new_lefover = leftover * viewer_data.mJointMatrix;
+ rest = parent_rest * viewer_data.mJointMatrix;
+ }
+ for (LLJointData& child_data : viewer_data.mChildren)
+ {
+ buildOverrideMatrix(child_data, gltf_nodes, names_to_nodes, rest, new_lefover);
+ }
+}
+
glm::mat4 LLGLTFLoader::buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF::Skin& gltf_skin) const
{
// This is inefficient since we are recalculating some joints multiple times over
@@ -1172,23 +1231,40 @@ glm::mat4 LLGLTFLoader::buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF
return node.mMatrix;
}
+glm::mat4 LLGLTFLoader::buildGltfRestMatrix(S32 joint_node_index, const joints_data_map_t& joint_data) const
+{
+ // This is inefficient since we are recalculating some joints multiple times over
+ // Todo: cache it?
+
+ if (joint_node_index < 0 || joint_node_index >= static_cast<S32>(mGLTFAsset.mNodes.size()))
+ {
+ return glm::mat4(1.0f);
+ }
+
+ auto& data = joint_data.at(joint_node_index);
+
+ if (data.mParentNodeIdx >=0)
+ {
+ return buildGltfRestMatrix(data.mParentNodeIdx, joint_data) * data.mGltfMatrix;
+ }
+ // Should we return armature or stop earlier?
+ return data.mGltfMatrix;
+}
+
// This function computes the transformation matrix needed to convert from GLTF skeleton space
// to viewer skeleton space for a specific joint
-glm::mat4 LLGLTFLoader::computeGltfToViewerSkeletonTransform(const joint_node_mat4_map_t& gltf_rest_map, S32 gltf_node_index, const std::string& joint_name) const
+glm::mat4 LLGLTFLoader::computeGltfToViewerSkeletonTransform(const joints_data_map_t& joints_data_map, S32 gltf_node_index, const std::string& joint_name) const
{
- joint_viewer_rest_map_t::const_iterator found = mJointViewerRestMatrices.find(joint_name);
- if (found == mJointViewerRestMatrices.end())
+ const JointNodeData& node_data = joints_data_map.at(gltf_node_index);
+ if (!node_data.mIsOverrideValid)
{
// For now assume they are identical and return an identity (for ease of debuging)
- // But there should be no joints viewer isn't aware about
- // Warn or assert about missing joints
return glm::mat4(1.0f);
}
- glm::mat4 viewer_joint_rest_pose = found->second;
// Get the GLTF joint's rest pose (in GLTF coordinate system)
- const glm::mat4 &gltf_joint_rest_pose = gltf_rest_map.at(gltf_node_index);
+ const glm::mat4 &gltf_joint_rest_pose = node_data.mGltfRestMatrix;
glm::mat4 rest_pose = coord_system_rotation * gltf_joint_rest_pose;
LL_INFOS("GLTF_DEBUG") << "rest matrix for joint " << joint_name << ": ";
@@ -1199,7 +1275,7 @@ glm::mat4 LLGLTFLoader::computeGltfToViewerSkeletonTransform(const joint_node_ma
// Compute transformation from GLTF space to viewer space
// This assumes both skeletons are in rest pose initially
- return viewer_joint_rest_pose * glm::inverse(rest_pose);
+ return node_data.mOverrideRestMatrix * glm::inverse(rest_pose);
}
bool LLGLTFLoader::checkForXYrotation(const LL::GLTF::Skin& gltf_skin, S32 joint_idx, S32 bind_indx)
diff --git a/indra/newview/gltf/llgltfloader.h b/indra/newview/gltf/llgltfloader.h
index bf5f830d47..408f9243c7 100644
--- a/indra/newview/gltf/llgltfloader.h
+++ b/indra/newview/gltf/llgltfloader.h
@@ -32,6 +32,7 @@
#include "asset.h"
#include "llglheaders.h"
+#include "lljointdata.h"
#include "llmodelloader.h"
// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD
@@ -125,6 +126,34 @@ class LLGLTFLoader : public LLModelLoader
typedef std::map<std::string, glm::mat4> joint_viewer_rest_map_t;
typedef std::map<S32, glm::mat4> joint_node_mat4_map_t;
+ struct JointNodeData
+ {
+ JointNodeData()
+ : mJointListIdx(-1)
+ , mNodeIdx(-1)
+ , mParentNodeIdx(-1)
+ , mIsValidViewerJoint(false)
+ , mIsParentValidViewerJoint(false)
+ , mIsOverrideValid(false)
+ {
+
+ }
+ S32 mJointListIdx;
+ S32 mNodeIdx;
+ S32 mParentNodeIdx;
+ glm::mat4 mGltfRestMatrix;
+ glm::mat4 mViewerRestMatrix;
+ glm::mat4 mOverrideRestMatrix;
+ glm::mat4 mGltfMatrix;
+ glm::mat4 mOverrideMatrix;
+ std::string mName;
+ bool mIsValidViewerJoint;
+ bool mIsParentValidViewerJoint;
+ bool mIsOverrideValid;
+ };
+ typedef std::map <S32, JointNodeData> joints_data_map_t;
+ typedef std::map <std::string, S32> joints_name_to_node_map_t;
+
LLGLTFLoader(std::string filename,
S32 lod,
LLModelLoader::load_callback_t load_cb,
@@ -137,8 +166,7 @@ class LLGLTFLoader : public LLModelLoader
std::map<std::string, std::string> &jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit,
- joint_viewer_rest_map_t jointRestMatrices,
- joint_viewer_parent_map_t jointParentPap); //,
+ std::vector<LLJointData> viewer_skeleton); //,
//bool preprocess );
virtual ~LLGLTFLoader();
@@ -172,8 +200,7 @@ protected:
// GLTF isn't aware of viewer's skeleton and uses it's own,
// so need to take viewer's joints and use them to
// recalculate iverse bind matrices
- joint_viewer_rest_map_t mJointViewerRestMatrices;
- joint_viewer_parent_map_t mJointViewerParentMap;
+ std::vector<LLJointData> mViewerJointData;
// vector of vectors because of a posibility of having more than one skin
typedef std::vector<LLMeshSkinInfo::matrix_list_t> bind_matrices_t;
@@ -194,8 +221,10 @@ private:
S32 findValidRootJointNode(S32 source_joint_node, const LL::GLTF::Skin& gltf_skin) const;
S32 findGLTFRootJointNode(const LL::GLTF::Skin& gltf_skin) const; // if there are multiple roots, gltf stores them under one commor joint
S32 findParentNode(S32 node) const;
+ void buildOverrideMatrix(LLJointData& data, joints_data_map_t &gltf_nodes, joints_name_to_node_map_t &names_to_nodes, glm::mat4& parent_rest, glm::mat4& leftover) const;
glm::mat4 buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF::Skin& gltf_skin) const;
- glm::mat4 computeGltfToViewerSkeletonTransform(const joint_node_mat4_map_t &gltf_rest_map, S32 gltf_node_index, const std::string& joint_name) const;
+ glm::mat4 buildGltfRestMatrix(S32 joint_node_index, const joints_data_map_t& joint_data) const;
+ glm::mat4 computeGltfToViewerSkeletonTransform(const joints_data_map_t& joints_data_map, S32 gltf_node_index, const std::string& joint_name) const;
bool checkForXYrotation(const LL::GLTF::Skin& gltf_skin, S32 joint_idx, S32 bind_indx);
void checkForXYrotation(const LL::GLTF::Skin& gltf_skin);
LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index d6b438a6e2..fc0a3ec58f 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -40,6 +40,7 @@
#include "lldrawable.h"
#include "llface.h"
#include "lliconctrl.h"
+#include "lljointdata.h"
#include "llmatrix4a.h"
#include "llmeshrepository.h"
#include "llmeshoptimizer.h"
@@ -811,9 +812,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
else
{
LLVOAvatar* av = getPreviewAvatar();
- LLAvatarAppearance::joint_rest_map_t rest_pose;
- LLAvatarAppearance::joint_parent_map_t rest_parent_map;
- av->getJointRestMatrices(rest_pose, rest_parent_map);
+ std::vector<LLJointData> viewer_skeleton;
+ av->getJointMatricesAndHierarhy(viewer_skeleton);
mModelLoader = new LLGLTFLoader(
filename,
lod,
@@ -827,8 +827,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
joint_alias_map,
LLSkinningUtil::getMaxJointCount(),
gSavedSettings.getU32("ImporterModelLimit"),
- rest_pose,
- rest_parent_map);
+ viewer_skeleton);
}
if (force_disable_slm)