diff options
| -rw-r--r-- | indra/newview/gltf/llgltfloader.cpp | 210 | ||||
| -rw-r--r-- | indra/newview/gltf/llgltfloader.h | 14 | 
2 files changed, 151 insertions, 73 deletions
| diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp index 4d705279a5..c99d7c2993 100644 --- a/indra/newview/gltf/llgltfloader.cpp +++ b/indra/newview/gltf/llgltfloader.cpp @@ -153,9 +153,9 @@ bool LLGLTFLoader::parseMeshes()      // Populate the joints from skins first.      // There's not many skins - and you can pretty easily iterate through the nodes from that. -    for (auto& skin : mGLTFAsset.mSkins) +    for (S32 i = 0; i < mGLTFAsset.mSkins.size(); i++)      { -        populateJointFromSkin(skin); +        populateJointFromSkin(i);      }      // Track how many times each mesh name has been used @@ -293,6 +293,8 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&          base_name = "mesh_" + std::to_string(mesh_index);      } +    LL_INFOS("GLTF_DEBUG") << "Processing model " << base_name << LL_ENDL; +      if (instance_count > 0)      {          pModel->mLabel = base_name + "_copy_" + std::to_string(instance_count); @@ -672,16 +674,8 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&          LL::GLTF::Skin& gltf_skin = mGLTFAsset.mSkins[skinIdx];          LLMeshSkinInfo& skin_info = pModel->mSkinInfo; -        size_t jointCnt = gltf_skin.mJoints.size(); -        if (gltf_skin.mInverseBindMatrices >= 0 && jointCnt != gltf_skin.mInverseBindMatricesData.size()) -        { -            LL_INFOS("GLTF_IMPORT") << "Bind matrices count mismatch joints count" << LL_ENDL; -            LLSD args; -            args["Message"] = "InvBindCountMismatch"; -            mWarningsArray.append(args); -        } -          std::vector<S32> gltfindex_to_joitindex_map; +        size_t jointCnt = gltf_skin.mJoints.size();          gltfindex_to_joitindex_map.resize(jointCnt);          S32 replacement_index = 0; @@ -711,44 +705,24 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&              skin_info.mJointNames.push_back(legal_name);              skin_info.mJointNums.push_back(-1); -            if (i < gltf_skin.mInverseBindMatricesData.size()) -            { -                // Use pre-computed coord_system_rotation instead of recreating it -                LL::GLTF::mat4 gltf_mat = gltf_skin.mInverseBindMatricesData[i]; - -                glm::mat4 original_bind_matrix = glm::inverse(gltf_mat); -                glm::mat4 rotated_original = coord_system_rotation * original_bind_matrix; -                glm::mat4 rotated_inverse_bind_matrix = glm::inverse(rotated_original); - -                LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(rotated_inverse_bind_matrix)); -                skin_info.mInvBindMatrix.push_back(LLMatrix4a(gltf_transform)); - -                LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL; +            // In scope of same skin multiple meshes reuse same bind matrices +            skin_info.mInvBindMatrix.push_back(mInverseBindMatrices[skinIdx][i]); -                // For alternate bind matrix, use the ORIGINAL joint transform (before rotation) -                // Get the original joint node and use its matrix directly -                S32 joint = gltf_skin.mJoints[i]; -                LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint]; -                glm::mat4 joint_mat = jointNode.mMatrix; -                S32 root_joint = findValidRootJoint(joint, gltf_skin); // skeleton can have multiple real roots -                if (root_joint == joint) -                { -                    // This is very likely incomplete in some way. -                    // Root shouldn't be the only one to need full coordinate fix -                    joint_mat = coord_system_rotation * joint_mat; -                } -                LLMatrix4 original_joint_transform(glm::value_ptr(joint_mat)); - -                LL_INFOS("GLTF_DEBUG") << "mAlternateBindMatrix name: " << legal_name << " val: " << original_joint_transform << LL_ENDL; -                skin_info.mAlternateBindMatrix.push_back(LLMatrix4a(original_joint_transform)); -            } -            else +            // For alternate bind matrix, use the ORIGINAL joint transform (before rotation) +            // Get the original joint node and use its matrix directly +            // Todo: this seems blatantly wrong, it should have been rotated +            glm::mat4 joint_mat = jointNode.mMatrix; +            S32 root_joint = findValidRootJointNode(joint, gltf_skin); // skeleton can have multiple real roots +            if (root_joint == joint)              { -                // For gltf mInverseBindMatrices are optional, but not for viewer -                // todo: get a model that triggers this -                skin_info.mInvBindMatrix.push_back(LLMatrix4a(mJointList[legal_name])); // might need to be an 'identity' -                skin_info.mAlternateBindMatrix.push_back(LLMatrix4a(mJointList[legal_name])); +                // This is very likely incomplete in some way. +                // Root shouldn't be the only one to need full coordinate fix +                joint_mat = coord_system_rotation * joint_mat;              } +            LLMatrix4 original_joint_transform(glm::value_ptr(joint_mat)); + +            LL_INFOS("GLTF_DEBUG") << "mAlternateBindMatrix name: " << legal_name << " val: " << original_joint_transform << LL_ENDL; +            skin_info.mAlternateBindMatrix.push_back(LLMatrix4a(original_joint_transform));          }          // Remap indices for pModel->mSkinWeights @@ -764,23 +738,71 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&      return true;  } -void LLGLTFLoader::populateJointFromSkin(const LL::GLTF::Skin& skin) +void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)  { -    LL_INFOS("GLTF_DEBUG") << "populateJointFromSkin: Processing " << skin.mJoints.size() << " joints" << LL_ENDL; +    const LL::GLTF::Skin& skin = mGLTFAsset.mSkins[skin_idx]; -    for (auto joint : skin.mJoints) +    LL_INFOS("GLTF_DEBUG") << "populateJointFromSkin: Processing skin " << skin_idx << " with " << skin.mJoints.size() << " joints" << LL_ENDL; + +    if (skin.mInverseBindMatrices > 0 && skin.mJoints.size() != skin.mInverseBindMatricesData.size())      { -        auto jointNode = mGLTFAsset.mNodes[joint]; +        LL_INFOS("GLTF_IMPORT") << "Bind matrices count mismatch joints count" << LL_ENDL; +        LLSD args; +        args["Message"] = "InvBindCountMismatch"; +        mWarningsArray.append(args); +    } +    S32 joint_count = (S32)skin.mJoints.size(); +    S32 inverse_count = (S32)skin.mInverseBindMatricesData.size(); +    if (mInverseBindMatrices.size() <= skin_idx) +    { +        mInverseBindMatrices.resize(skin_idx + 1); +    } + +    for (S32 i = 0; i < joint_count; i++) +    { +        S32 joint = skin.mJoints[i]; +        LL::GLTF::Node jointNode = mGLTFAsset.mNodes[joint];          std::string legal_name(jointNode.mName); +        bool legal_joint = false;          if (mJointMap.find(legal_name) != mJointMap.end())          {              legal_name = mJointMap[legal_name]; +            legal_joint = true; +        } + +        if (!legal_joint) +        { +            // add placeholder to not break index +            LLMatrix4 gltf_transform; +            gltf_transform.setIdentity(); +            mInverseBindMatrices[skin_idx].push_back(LLMatrix4a(gltf_transform)); +        } +        else if (inverse_count > i) +        { +            LL::GLTF::mat4 gltf_mat = skin.mInverseBindMatricesData[i]; + +            // Todo: there should be a simpler way +            glm::mat4 original_bind_matrix = glm::inverse(gltf_mat); +            glm::mat4 rotated_original = coord_system_rotation * original_bind_matrix; +            glm::mat4 rotated_inverse_bind_matrix = glm::inverse(rotated_original); +            LLMatrix4 gltf_transform = LLMatrix4(glm::value_ptr(rotated_inverse_bind_matrix)); + +            LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL; +            mInverseBindMatrices[skin_idx].push_back(LLMatrix4a(gltf_transform));          }          else          { -            // ignore unrecognized joint -            LL_DEBUGS("GLTF") << "Ignoring joint: " << legal_name << LL_ENDL; +            LLMatrix4 gltf_transform; +            gltf_transform.setIdentity(); +            LL_INFOS("GLTF_DEBUG") << "mInvBindMatrix name: " << legal_name << " val: " << gltf_transform << LL_ENDL; +            mInverseBindMatrices[skin_idx].push_back(LLMatrix4a(gltf_transform)); +        } +        // todo: prepare mAlternateBindMatrix here + +        if (!legal_joint) +        { +            LL_DEBUGS("GLTF") << "Ignoring unrecognized joint: " << legal_name << LL_ENDL;              continue;          } @@ -812,14 +834,45 @@ void LLGLTFLoader::populateJointFromSkin(const LL::GLTF::Skin& skin)      }  } -S32 LLGLTFLoader::findValidRootJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const + +S32 LLGLTFLoader::findClosestValidJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const  { -    S32 root_joint = 0; -    S32 found_joint = source_joint; +    S32 source_joint_node = gltf_skin.mJoints[source_joint]; +    S32 root_node = source_joint_node; +    S32 found_node = source_joint_node;      S32 size = (S32)gltf_skin.mJoints.size();      do      { -        root_joint = found_joint; +        root_node = found_node; +        for (S32 i = 0; i < size; i++) +        { +            S32 joint = gltf_skin.mJoints[i]; +            const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint]; +            std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_node); +            if (it != jointNode.mChildren.end()) +            { +                // Found node's parent +                found_node = joint; +                if (mJointMap.find(jointNode.mName) != mJointMap.end()) +                { +                    return i; +                } +                break; +            } +        } +    } while (root_node != found_node); + +    return -1; +} + +S32 LLGLTFLoader::findValidRootJointNode(S32 source_joint_node, const LL::GLTF::Skin& gltf_skin) const +{ +    S32 root_node = 0; +    S32 found_node = source_joint_node; +    S32 size = (S32)gltf_skin.mJoints.size(); +    do +    { +        root_node = found_node;          for (S32 i = 0; i < size; i++)          {              S32 joint = gltf_skin.mJoints[i]; @@ -827,44 +880,61 @@ S32 LLGLTFLoader::findValidRootJoint(S32 source_joint, const LL::GLTF::Skin& glt              if (mJointMap.find(jointNode.mName) != mJointMap.end())              { -                std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_joint); +                std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_node);                  if (it != jointNode.mChildren.end())                  { -                    found_joint = joint; +                    // Found node's parent +                    found_node = joint;                      break;                  }              }          } -    } while (root_joint != found_joint); +    } while (root_node != found_node); -    return root_joint; +    return root_node;  } -S32 LLGLTFLoader::findGLTFRootJoint(const LL::GLTF::Skin& gltf_skin) const +S32 LLGLTFLoader::findGLTFRootJointNode(const LL::GLTF::Skin& gltf_skin) const  { -    S32 root_joint = 0; -    S32 found_joint = 0; +    S32 root_node = 0; +    S32 found_node = 0;      S32 size = (S32)gltf_skin.mJoints.size();      do      { -        root_joint = found_joint; +        root_node = found_node;          for (S32 i = 0; i < size; i++)          {              S32 joint = gltf_skin.mJoints[i];              const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint]; -            std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_joint); +            std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), root_node);              if (it != jointNode.mChildren.end())              { -                found_joint = joint; +                // Found node's parent +                found_node = joint;                  break;              }          } -    } while (root_joint != found_joint); +    } while (root_node != found_node);      LL_INFOS("GLTF_DEBUG") << "mJointList name: "; -    const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[root_joint]; -    LL_CONT << jointNode.mName << " index: " << root_joint << LL_ENDL; -    return root_joint; +    const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[root_node]; +    LL_CONT << jointNode.mName << " index: " << root_node << LL_ENDL; +    return root_node; +} + +S32 LLGLTFLoader::findParentNode(S32 node) const +{ +    S32 size = (S32)mGLTFAsset.mNodes.size(); +    for (S32 i = 0; i < size; i++) +    { +        const LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[i]; +        std::vector<S32>::const_iterator it = std::find(jointNode.mChildren.begin(), jointNode.mChildren.end(), node); +        if (it != jointNode.mChildren.end()) +        { +            return i; +        } +    } +    return -1;  }  bool LLGLTFLoader::parseMaterials() diff --git a/indra/newview/gltf/llgltfloader.h b/indra/newview/gltf/llgltfloader.h index 6e0fe2b32c..a9572a5bfc 100644 --- a/indra/newview/gltf/llgltfloader.h +++ b/indra/newview/gltf/llgltfloader.h @@ -121,6 +121,7 @@ class LLGLTFLoader : public LLModelLoader  {    public:      typedef std::map<std::string, LLImportMaterial> material_map; +    typedef std::map<std::string, LLVector3> joint_pos_map_t;      LLGLTFLoader(std::string filename,                      S32                                 lod, @@ -162,6 +163,11 @@ protected:      std::vector<gltf_image>             mImages;      std::vector<gltf_sampler>           mSamplers; + +    // vector of vectors because of a posibility of having more than one skin +    typedef std::vector<LLMeshSkinInfo::matrix_list_t> bind_matrices_t; +    bind_matrices_t                     mInverseBindMatrices; +  private:      bool parseMeshes();      void uploadMeshes(); @@ -169,9 +175,11 @@ private:      void uploadMaterials();      void computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S32 node_index, glm::mat4& combined_transform) const;      bool populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &mesh, const LL::GLTF::Node &node, material_map& mats, S32 instance_count); -    void populateJointFromSkin(const LL::GLTF::Skin& skin); -    S32 findValidRootJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const; -    S32 findGLTFRootJoint(const LL::GLTF::Skin& gltf_skin) const; // if there are multiple roots, gltf stores them under one commor joint +    void populateJointFromSkin(S32 skin_idx); +    S32 findClosestValidJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const; +    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;      LLUUID imageBufferToTextureUUID(const gltf_texture& tex);      void notifyUnsupportedExtension(bool unsupported); | 
