diff options
| -rw-r--r-- | indra/llappearance/llavatarappearance.cpp | 22 | ||||
| -rw-r--r-- | indra/llappearance/llavatarappearance.h | 3 | ||||
| -rw-r--r-- | indra/newview/gltf/llgltfloader.cpp | 126 | ||||
| -rw-r--r-- | indra/newview/gltf/llgltfloader.h | 12 | ||||
| -rw-r--r-- | indra/newview/llmodelpreview.cpp | 7 | 
5 files changed, 97 insertions, 73 deletions
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index a3032325c9..f3e474dba7 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -108,7 +108,12 @@ public:  private:      typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t; -    static void getJointRestMatrices(const bone_info_list_t& bone_list, LLAvatarAppearance::joint_rest_map_t& result, const glm::mat4 &parent_mat); +    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, +        const glm::mat4& parent_mat);  private:      S32 mNumBones; @@ -1674,14 +1679,17 @@ bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)  void LLAvatarSkeletonInfo::getJointRestMatrices(      const bone_info_list_t& bone_list, -    LLAvatarAppearance::joint_rest_map_t& result, +    const std::string& parent_name, +    LLAvatarAppearance::joint_rest_map_t& rest, +    LLAvatarAppearance::joint_parent_map_t& parent_map,      const glm::mat4& parent_mat)  {      for (LLAvatarBoneInfo* bone_info : bone_list)      {          glm::mat4 rest_mat = parent_mat * bone_info->getJointMatrix(); -        result[bone_info->mName] = rest_mat; -        getJointRestMatrices(bone_info->mChildren, result, rest_mat); +        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);      }  } @@ -1746,12 +1754,10 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases      return mJointAliasMap;  } -LLAvatarAppearance::joint_rest_map_t LLAvatarAppearance:: getJointRestMatrices() const +void LLAvatarAppearance:: getJointRestMatrices(LLAvatarAppearance::joint_rest_map_t& rest_map, LLAvatarAppearance::joint_parent_map_t& parent_map) const  { -    LLAvatarAppearance::joint_rest_map_t result;      glm::mat4 identity(1.f); -    LLAvatarSkeletonInfo::getJointRestMatrices(sAvatarSkeletonInfo->mBoneInfoList, result, identity); -    return result; +    LLAvatarSkeletonInfo::getJointRestMatrices(sAvatarSkeletonInfo->mBoneInfoList, std::string(), rest_map, parent_map, identity);  } diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index cea2a837cd..e48d80b8ce 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -154,8 +154,9 @@ public:      const avatar_joint_list_t& getSkeleton() { return mSkeleton; }      typedef std::map<std::string, std::string> joint_alias_map_t;      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; -    joint_rest_map_t getJointRestMatrices() const; +    void getJointRestMatrices(joint_rest_map_t& rest_map, joint_parent_map_t& parent_map) const;  protected:      static bool         parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp index 40b9334e63..292fd09035 100644 --- a/indra/newview/gltf/llgltfloader.cpp +++ b/indra/newview/gltf/llgltfloader.cpp @@ -95,7 +95,8 @@ LLGLTFLoader::LLGLTFLoader(std::string filename,      std::map<std::string, std::string> &jointAliasMap,      U32                                 maxJointsPerMesh,      U32                                 modelLimit, -    joint_rest_map_t                    jointRestMatrices) //, +    joint_viewer_rest_map_t             jointRestMatrices, +    joint_viewer_parent_map_t           jointParentMap) //,      //bool                                preprocess)      : LLModelLoader( filename,                       lod, @@ -107,12 +108,13 @@ LLGLTFLoader::LLGLTFLoader(std::string filename,                       jointTransformMap,                       jointsFromNodes,                       jointAliasMap, -                     maxJointsPerMesh ), +                     maxJointsPerMesh )      //mPreprocessGLTF(preprocess), -    mMeshesLoaded(false), -    mMaterialsLoaded(false), -    mGeneratedModelLimit(modelLimit), -    mJointRestMatrices(jointRestMatrices) +    , mMeshesLoaded(false) +    , mMaterialsLoaded(false) +    , mGeneratedModelLimit(modelLimit) +    , mJointViewerRestMatrices(jointRestMatrices) +    , mJointViewerParentMap(jointParentMap)  {  } @@ -929,6 +931,16 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)      if (mInverseBindMatrices.size() <= skin_idx)      {          mInverseBindMatrices.resize(skin_idx + 1); +        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; +    for (S32 i = 0; i < joint_count; i++) +    { +        S32 joint = skin.mJoints[i]; +        gltf_rest_map[joint] = buildGltfRestMatrix(joint, skin);      }      for (S32 i = 0; i < joint_count; i++) @@ -943,86 +955,84 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)              legal_joint = true;          } +        // Compute bind matrices +          if (!legal_joint)          { -            // add placeholder to not break index +            // Add placeholder to not break index. +            // Not going to be used by viewer, will be stripped from skin_info.              LLMatrix4 gltf_transform;              gltf_transform.setIdentity();              mInverseBindMatrices[skin_idx].push_back(LLMatrix4a(gltf_transform));          }          else if (inverse_count > i)          { +            // Transalte existing bind matrix to viewer's skeleton +            // 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(skin, i, legal_name); +            glm::mat4 skeleton_transform = computeGltfToViewerSkeletonTransform(gltf_rest_map, joint, legal_name);              glm::mat4 tranlated_original = skeleton_transform * rotated_original;              glm::mat4 final_inverse_bind_matrix = glm::inverse(tranlated_original);              LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(final_inverse_bind_matrix)); - -            LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL; +            LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " Translated val: " << gltf_transform << LL_ENDL;              mInverseBindMatrices[skin_idx].push_back(LLMatrix4a(gltf_transform));          }          else          { +            // If bind matrices aren't present (they are optional in gltf), +            // 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(skin, i, legal_name); +            glm::mat4 skeleton_transform = computeGltfToViewerSkeletonTransform(gltf_rest_map, joint, legal_name);              inv_bind = glm::inverse(skeleton_transform * inv_bind);              LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(inv_bind)); -            gltf_transform.setIdentity(); -            LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL; +            LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " Generated val: " << gltf_transform << LL_ENDL;              mInverseBindMatrices[skin_idx].push_back(LLMatrix4a(gltf_transform));          } -        // Todo: this seems blatantly wrong -        glm::mat4 joint_mat = jointNode.mMatrix; -        S32 root_joint = findValidRootJointNode(joint, skin); // skeleton can have multiple real roots and one gltf root to group them -        if (root_joint == joint) +        // Compute Alternative matrices also known as overrides + +        glm::mat4 joint_mat = glm::mat4(1.f); +        if (legal_joint)          { -            // This is very likely incomplete in some way. -            joint_mat = coord_system_rotation; -            if (mApplyXYRotation) +            joint_viewer_parent_map_t::const_iterator found = mJointViewerParentMap.find(legal_name); +            if (found != mJointViewerParentMap.end() && !found->second.empty())              { -                joint_mat = coord_system_rotationxy * joint_mat; +                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)); +        // 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)); -        if (!legal_joint) -        { -            LL_DEBUGS("GLTF") << "Ignoring unrecognized joint: " << legal_name << LL_ENDL; -            continue; -        } - -        // Debug: Log original joint matrix -        glm::mat4 gltf_joint_matrix = jointNode.mMatrix; -        LL_INFOS("GLTF_DEBUG") << "Joint '" << legal_name << "' original matrix:" << LL_ENDL; -        for(int i = 0; i < 4; i++) -        { -            LL_INFOS("GLTF_DEBUG") << "  [" << gltf_joint_matrix[i][0] << ", " << gltf_joint_matrix[i][1] -                                   << ", " << gltf_joint_matrix[i][2] << ", " << gltf_joint_matrix[i][3] << "]" << LL_ENDL; -        } - -        // Apply coordinate system rotation to joint transform -        glm::mat4 rotated_joint_matrix = coord_system_rotation * gltf_joint_matrix; - -        // Debug: Log rotated joint matrix -        LL_INFOS("GLTF_DEBUG") << "Joint '" << legal_name << "' rotated matrix:" << LL_ENDL; -        for(int i = 0; i < 4; i++) +        if (legal_joint)          { -            LL_INFOS("GLTF_DEBUG") << "  [" << rotated_joint_matrix[i][0] << ", " << rotated_joint_matrix[i][1] -                                   << ", " << rotated_joint_matrix[i][2] << ", " << rotated_joint_matrix[i][3] << "]" << LL_ENDL; +            // Might be needed for uploader UI to correctly identify overriden joints +            // but going to be incorrect if multiple skins are present +            mJointList[legal_name] = newInverse; +            mJointsFromNode.push_front(legal_name);          } - -        LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(rotated_joint_matrix)); -        mJointList[legal_name] = gltf_transform; -        mJointsFromNode.push_front(legal_name); - -        LL_INFOS("GLTF_DEBUG") << "mJointList name: " << legal_name << " val: " << gltf_transform << LL_ENDL;      }  } @@ -1164,10 +1174,11 @@ glm::mat4 LLGLTFLoader::buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF  // 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 LL::GLTF::Skin& gltf_skin, S32 gltf_joint_index, const std::string& joint_name) const + +glm::mat4 LLGLTFLoader::computeGltfToViewerSkeletonTransform(const joint_node_mat4_map_t& gltf_rest_map, S32 gltf_node_index, const std::string& joint_name) const  { -    joint_rest_map_t::const_iterator found = mJointRestMatrices.find(joint_name); -    if (found == mJointRestMatrices.end()) +    joint_viewer_rest_map_t::const_iterator found = mJointViewerRestMatrices.find(joint_name); +    if (found == mJointViewerRestMatrices.end())      {          // 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 @@ -1177,19 +1188,18 @@ glm::mat4 LLGLTFLoader::computeGltfToViewerSkeletonTransform(const LL::GLTF::Ski      glm::mat4 viewer_joint_rest_pose = found->second;      // Get the GLTF joint's rest pose (in GLTF coordinate system) -    S32 joint_node_index = gltf_skin.mJoints[gltf_joint_index]; -    glm::mat4 gltf_joint_rest_pose = buildGltfRestMatrix(joint_node_index, gltf_skin); -    gltf_joint_rest_pose = coord_system_rotation * gltf_joint_rest_pose; +    const glm::mat4 &gltf_joint_rest_pose = gltf_rest_map.at(gltf_node_index); +    glm::mat4 rest_pose = coord_system_rotation * gltf_joint_rest_pose;      LL_INFOS("GLTF_DEBUG") << "rest matrix for joint " << joint_name << ": "; -    LLMatrix4 transform(glm::value_ptr(gltf_joint_rest_pose)); +    LLMatrix4 transform(glm::value_ptr(rest_pose));      LL_CONT << transform << LL_ENDL;      // Compute transformation from GLTF space to viewer space      // This assumes both skeletons are in rest pose initially -    return viewer_joint_rest_pose * glm::inverse(gltf_joint_rest_pose); +    return viewer_joint_rest_pose * 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 6009a8e0c7..bf5f830d47 100644 --- a/indra/newview/gltf/llgltfloader.h +++ b/indra/newview/gltf/llgltfloader.h @@ -121,7 +121,9 @@ class LLGLTFLoader : public LLModelLoader  {    public:      typedef std::map<std::string, LLImportMaterial> material_map; -    typedef std::map<std::string, glm::mat4> joint_rest_map_t; +    typedef std::map<std::string, std::string> joint_viewer_parent_map_t; +    typedef std::map<std::string, glm::mat4> joint_viewer_rest_map_t; +    typedef std::map<S32, glm::mat4> joint_node_mat4_map_t;      LLGLTFLoader(std::string filename,                      S32                                 lod, @@ -135,7 +137,8 @@ class LLGLTFLoader : public LLModelLoader                      std::map<std::string, std::string> &jointAliasMap,                      U32                                 maxJointsPerMesh,                      U32                                 modelLimit, -                    joint_rest_map_t                    jointRestMatrices); //, +                    joint_viewer_rest_map_t             jointRestMatrices, +                    joint_viewer_parent_map_t           jointParentPap); //,                      //bool                                preprocess );      virtual ~LLGLTFLoader(); @@ -169,7 +172,8 @@ 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_rest_map_t                    mJointRestMatrices; +    joint_viewer_rest_map_t             mJointViewerRestMatrices; +    joint_viewer_parent_map_t           mJointViewerParentMap;      // vector of vectors because of a posibility of having more than one skin      typedef std::vector<LLMeshSkinInfo::matrix_list_t> bind_matrices_t; @@ -191,7 +195,7 @@ private:      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;      glm::mat4 buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF::Skin& gltf_skin) const; -    glm::mat4 computeGltfToViewerSkeletonTransform(const LL::GLTF::Skin& gltf_skin, S32 joint_index, const std::string& joint_name) const; +    glm::mat4 computeGltfToViewerSkeletonTransform(const joint_node_mat4_map_t &gltf_rest_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 40b6d186b8..d6b438a6e2 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -811,7 +811,9 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable      else      {          LLVOAvatar* av = getPreviewAvatar(); -        LLAvatarAppearance::joint_rest_map_t rest_pose = av->getJointRestMatrices(); +        LLAvatarAppearance::joint_rest_map_t rest_pose; +        LLAvatarAppearance::joint_parent_map_t rest_parent_map; +        av->getJointRestMatrices(rest_pose, rest_parent_map);          mModelLoader = new LLGLTFLoader(              filename,              lod, @@ -825,7 +827,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable              joint_alias_map,              LLSkinningUtil::getMaxJointCount(),              gSavedSettings.getU32("ImporterModelLimit"), -            rest_pose); +            rest_pose, +            rest_parent_map);      }      if (force_disable_slm)  | 
