示例#1
0
文件: fbxRMesh.cpp 项目: BodyViz/osg
void addBindMatrix(
    BindMatrixMap& boneBindMatrices,
    KFbxNode* pBone,
    const osg::Matrix& bindMatrix,
    osgAnimation::RigGeometry* pRigGeometry)
{
    boneBindMatrices.insert(BindMatrixMap::value_type(
        BindMatrixMap::key_type(pBone, pRigGeometry), bindMatrix));
}
void resolveBindMatrices(
    osg::Node& root,
    const BindMatrixMap& boneBindMatrices,
    const std::map<KFbxNode*, osg::Node*>& nodeMap)
{
    std::set<std::string> nodeNames;
    for (std::map<KFbxNode*, osg::Node*>::const_iterator it = nodeMap.begin(); it != nodeMap.end(); ++it)
    {
        nodeNames.insert(it->second->getName());
    }

    for (BindMatrixMap::const_iterator it = boneBindMatrices.begin();
        it != boneBindMatrices.end();)
    {
        KFbxNode* const fbxBone = it->first.first;
        std::map<KFbxNode*, osg::Node*>::const_iterator nodeIt = nodeMap.find(fbxBone);
        if (nodeIt != nodeMap.end())
        {
            const osg::Matrix bindMatrix = it->second;
            osgAnimation::Bone& osgBone = dynamic_cast<osgAnimation::Bone&>(*nodeIt->second);
            osgBone.setInvBindMatrixInSkeletonSpace(bindMatrix);

            ++it;
            for (; it != boneBindMatrices.end() && it->first.first == fbxBone; ++it)
            {
                if (it->second != bindMatrix)
                {
                    std::string name;
                    for (int i = 0;; ++i)
                    {
                        std::stringstream ss;
                        ss << osgBone.getName() << '_' << i;
                        name = ss.str();
                        if (nodeNames.insert(name).second)
                        {
                            break;
                        }
                    }
                    osgAnimation::Bone* newBone = new osgAnimation::Bone(name);
                    newBone->setDefaultUpdateCallback();
                    newBone->setInvBindMatrixInSkeletonSpace(it->second);
                    osgBone.addChild(newBone);

                    osgAnimation::RigGeometry* pRigGeometry = it->first.second;

                    osgAnimation::VertexInfluenceMap* vertexInfluences = pRigGeometry->getInfluenceMap();

                    osgAnimation::VertexInfluenceMap::iterator vimIt = vertexInfluences->find(osgBone.getName());
                    if (vimIt != vertexInfluences->end())
                    {
                        osgAnimation::VertexInfluence vi;
                        vi.swap(vimIt->second);
                        vertexInfluences->erase(vimIt);
                        osgAnimation::VertexInfluence& vi2 = (*vertexInfluences)[name];
                        vi.swap(vi2);
                        vi2.setName(name);
                    }
                    else
                    {
                        OSG_WARN << "No vertex influences found for \"" << osgBone.getName() << "\"" << std::endl;
                    }
                }
            }
        }
        else
        {
            OSG_WARN << "No bone found for \"" << fbxBone->GetName() << "\"" << std::endl;
            ++it;
        }
    }
}
void resolveBindMatrices(
    osg::Node& root,
    const BindMatrixMap& boneBindMatrices,
    const std::map<FbxNode*, osg::Node*>& nodeMap)
{
    std::set<std::string> nodeNames;
    for (std::map<FbxNode*, osg::Node*>::const_iterator it = nodeMap.begin(); it != nodeMap.end(); ++it)
    {
        nodeNames.insert(it->second->getName());
    }

    for (BindMatrixMap::const_iterator it = boneBindMatrices.begin(); it != boneBindMatrices.end(); ++it)
    {
        FbxNode* const fbxBone = it->first;
        std::map<FbxNode*, osg::Node*>::const_iterator nodeIt = nodeMap.find(fbxBone);
        if (nodeIt != nodeMap.end())
        {
            osgAnimation::Bone* originalBone = dynamic_cast<osgAnimation::Bone*>(nodeIt->second);

            // Iterate bind matrices and create new bones if needed
            const BindMatrixGeometryMap& bindMatrixGeom = it->second;
            for ( BindMatrixGeometryMap::const_iterator bindIt = bindMatrixGeom.begin(); bindIt != bindMatrixGeom.end(); ++bindIt)
            {
                // First matrix will use original bone
                if (bindIt == bindMatrixGeom.begin())
                {
                    originalBone->setInvBindMatrixInSkeletonSpace(bindIt->first);
                }
                else
                {
                    // Additional matrices need new bone
                    std::string name;
                    for (int i = 0;; ++i)
                    {
                        std::stringstream ss;
                        ss << originalBone->getName() << '_' << i;
                        name = ss.str();
                        if (nodeNames.insert(name).second)
                        {
                            break;
                        }
                    }
                    osgAnimation::Bone* newBone = new osgAnimation::Bone(name);
                    newBone->setDefaultUpdateCallback();
                    newBone->setInvBindMatrixInSkeletonSpace(bindIt->first);
                    originalBone->addChild(newBone);

                    // Update rig geometry with new bone names
                    for (std::set<osgAnimation::RigGeometry*>::const_iterator rigIt = bindIt->second.begin();
                         rigIt != bindIt->second.end();
                         ++rigIt)
                    {
                        osgAnimation::RigGeometry* pRigGeometry = (*rigIt);

                        osgAnimation::VertexInfluenceMap* vertexInfluences = pRigGeometry->getInfluenceMap();

                        osgAnimation::VertexInfluenceMap::iterator vimIt = vertexInfluences->find(originalBone->getName());
                        if (vimIt != vertexInfluences->end())
                        {
                            osgAnimation::VertexInfluence vi;
                            vi.swap(vimIt->second);
                            vertexInfluences->erase(vimIt);
                            osgAnimation::VertexInfluence& vi2 = (*vertexInfluences)[name];
                            vi.swap(vi2);
                            vi2.setName(name);
                        }
                        else
                        {
                            OSG_WARN << "No vertex influences found for \"" << originalBone->getName() << "\"" << std::endl;
                        }
                    }
                }
            }
        }
        else
        {
            OSG_WARN << "No bone found for \"" << fbxBone->GetName() << "\"" << std::endl;
            ++it;
        }
    }
}